Home >
Windows にまつわる e.t.c.
PowerShell でファイルの AES256 暗号/復号
このサイトで暗号系のサンプル実装をいろいろ書いていますが、サンプルなのでテキストにして結果を見る感じの実装になっています。
でも、実際の運用で暗号系の実装する場合は、byte 配列でデーターをハンドリングするのがセオリーなんですね。
AES256 暗号が必要だったので、byte 配列ハンドリングの AES256 暗号/復号の PowerShell
スクリプトを書いたので公開します。
以下 ReadMe より
■ これは何?
AES 256 共通鍵暗号を使ってファイルを暗号/復号します
■ 動作環境は?
PowerShell 3.0 以降環境で動作します
動作確認したバージョンは以下の通り
3.0 |
Windows 7 |
5.1 |
Windows 10 |
6.0 |
Windows 10 CentOS 7 |
■ 使用方法
・暗号化
以下スクリプトに、暗号化するファイルのパス(又は Get-ChildItem で得られる
fileinfo)と共通鍵のフルパス又は Base64 文字列(-KeyBase64)を与えると、AES256 で暗号化したファイルを作成します(拡張子
.enc)
暗号化するファイルは複数指定できます。
AES256.ps1 -Encrypto -KeyPath 共通鍵のフルパス -Path
暗号化するファイル AES256.ps1 -Encrypto -KeyBase64 Base64共通鍵 -Path 暗号化するファイル |
・復号化
以下スクリプトに、復号化するファイルのパス(又は Get-ChildItem で得られる fileinfo)と共通鍵のフルパス又は Base64
文字列(-KeyBase64)を与えると、復号ファイルを作成します(注意:既存ファイルがあれば上書き)
復号化するファイルは複数指定できます。
AES256.ps1 -Decrypto -KeyPath 共通鍵のフルパス -Path
復号化するファイル AES256.ps1 -Decrypto -KeyBase64 Base64共通鍵 -Path 復号化するファイル |
・共通鍵の作成
以下スクリプトに共通鍵のフルパスを与えると、ランダムな 256 bit の共通鍵を生成します(Base64
でエンコード)
■ 実行例
・鍵ファイルを指定して暗号化
PS C:\Script\aes256> .\AES256.ps1 -Encrypto
-KeyPath "C:\Key\Shared.key" -Path "C:\Data\TestData.txt" |
・複数ファイルを暗号化
PS C:\Script\aes256> $EncFiles = dir C:\Data
PS C:\Script\aes256> .\AES256.ps1 -Encrypto -KeyPath "C:\Key\Shared.key"
-Path $EncFiles |
・Base64鍵を指定して復号化
PS C:\Script\aes256> .\AES256.ps1 -Decrypto
-KeyBase64 "X6iFs1i1wB1nFJaRxAM3PuzduvRS/Kyh8+cfcE+7FxA=" -Path
"C:\Data\TestData.txt" |
・共通鍵を作成
PS C:\Script\aes256> .\Make256Key.ps1
"C:\Key\Shared.key" |
■ 注意事項
AES256 のストリーミングを使わず、オンメモリーで暗号/復号しています。
このため、でかいファイルを暗号/復号する場合は、メモリーに余裕のある環境での実行をお勧めします。
リポジトリ公開場所
GitHub でリポジトリ公開しています。
https://github.com/MuraAtVwnet/AES256
ダウンロード
リポジトリを Clone して下さい。
git@github.com:MuraAtVwnet/AES256.git |
Clone が面倒な場合は、以下スクリプトでのダウンロードでもイケます。
(PowerShell 4.0 以降)
$Terget = "C:\Script\aes256" $DowunLoadFile =
Join-Path $Terget "AES256.zip" if( -not(Test-Path $Terget) ){ md
$Terget } Invoke-WebRequest
https://github.com/MuraAtVwnet/AES256/archive/master.zip -OutFile
$DowunLoadFile ii $Terget |
コード
以下公開時点のソースコードです
(コピペして .ps1 を作っても動きますが、最新版をリポジトリから Clone
してもらえると嬉しいです)
[AES256.ps1]
##################################################
# AES256 暗号/復号
##################################################
Param(
[switch]$Encrypto, # 暗号化
[switch]$Decrypto, # 復号化
$KeyPath, # 共通鍵ファイルの Path
$KeyBase64, # 共通鍵(Base64)
[array]$Path # 処理対象ファイル
)
# 暗号ファイルの拡張子
$ExtName = "enc"
# AES 定数
$AES_KeySize = 256
$AES_BlockSize = 128
$AES_IVSize = $AES_BlockSize / 8
$AES_Mode = "CBC"
$AES_Padding = "PKCS7"
##################################################
# Base64 をバイト配列にする
##################################################
function Base642Byte( $Base64 ){
$Byte = [System.Convert]::FromBase64String($Base64)
return $Byte
}
##################################################
# AES 暗号化
##################################################
function AESEncrypto($ByteKey, $BytePlain){
if( $ByteKey.Length * 8 -ne $AES_KeySize ){
echo "[FAIL] Key size error"
return $null
}
# アセンブリロード
Add-Type -AssemblyName System.Security
# AES オブジェクトの生成
$AES = New-Object System.Security.Cryptography.AesCryptoServiceProvider
# 各値セット
$AES.KeySize = $AES_KeySize
$AES.BlockSize = $AES_BlockSize
$AES.Mode = $AES_Mode
$AES.Padding = $AES_Padding
# IV 生成
$AES.GenerateIV()
# 生成した IV
$IV = $AES.IV
# 鍵セット
$AES.Key = $ByteKey
# 暗号化オブジェクト生成
$Encryptor = $AES.CreateEncryptor()
# 暗号化
$EncryptoByte = $Encryptor.TransformFinalBlock($BytePlain, 0, $BytePlain.Length)
# IV と暗号化した文字列を結合
$DataByte = $IV + $EncryptoByte
# オブジェクト削除
$Encryptor.Dispose()
$AES.Dispose()
return $DataByte
}
##################################################
# AES 復号化
##################################################
function AESDecrypto($ByteKey, $ByteEncrypto){
if( $ByteKey.Length * 8 -ne $AES_KeySize ){
echo "[FAIL] Key size error"
return $null
}
# IV を取り出す
$IV = @()
for( $i = 0; $i -lt $AES_IVSize; $i++){
$IV += $ByteEncrypto[$i]
}
# アセンブリロード
Add-Type -AssemblyName System.Security
# オブジェクトの生成
$AES = New-Object System.Security.Cryptography.AesCryptoServiceProvider
# 各値セット
$AES.KeySize = $AES_KeySize
$AES.BlockSize = $AES_BlockSize
$AES.Mode = $AES_Mode
$AES.Padding = $AES_Padding
# IV セット
$AES.IV = $IV
# 鍵セット
$AES.Key = $ByteKey
# 復号化オブジェクト生成
$Decryptor = $AES.CreateDecryptor()
try{
# 復号化
$DecryptoByte = $Decryptor.TransformFinalBlock($ByteEncrypto, $AES_IVSize, $ByteEncrypto.Length - $AES_IVSize)
}
catch{
$DecryptoByte = $null
}
# オブジェクト削除
$Decryptor.Dispose()
$AES.Dispose()
return $DecryptoByte
}
##################################################
# main
##################################################
$PsMajorVertion = $PSVersionTable.PSVersion.Major
if( $PsMajorVertion -le 2 ){
echo "[FAIL] PowerShell 2.0 以下はサポートしていません"
exit
}
if( $Path -eq $null ){
echo "Usage..."
echo " .\aes256.ps1 [-Encrypto|-Decrypto] [-KeyPath KeyFilePath|-KeyBase64 KeyText] -Path InputFilePath(s)"
exit
}
# 鍵指定
if( ($KeyPath -eq $null) -and `
($KeyBase64 -eq $null)){
echo "[FAIL] Set -KeyPath or KeyBase64"
exit
}
# 暗号/復号オプション
if( (($Encrypto -eq $fals) -and ( $Decrypto -eq $false)) -or `
(($Encrypto -eq $true) -and ( $Decrypto -eq $true))){
echo "[FAIL] select -Encrypto or -Decrypto"
exit
}
### 鍵読み込み
# ファイルを読む
if( $KeyPath -ne $null ){
if( -not (Test-Path $KeyPath )){
echo "[FAIL] $KeyPath not found."
exit
}
$Base64Key = Get-Content $KeyPath
}
# 引数に指定された値を使う
else{
$Base64Key = $KeyBase64
}
$ByteKey = Base642Byte $Base64Key
if( $ByteKey -eq $null ){
echo "[FAIL] 鍵エラー"
exit
}
foreach($TergetFile in $Path){
# 文字列の場合
if( $TergetFile.GetType().Name -eq "String" ){
# フルパスにする
$TergetFileName = Convert-Path $TergetFile -ErrorAction SilentlyContinue
}
# fileinfo
elseif( $TergetFile.GetType().Name -eq "FileInfo" ){
$TergetFileName = $TergetFile.FullName
}
# 意図しないデータ
else{
echo "[ERROR] $TergetFile is bad data."
continue
}
# 正常にフルパスが取れなかった
if( $TergetFileName -eq $null ){
echo "[ERROR] $TergetFile is not file name."
continue
}
# Data
if( -not (Test-Path $TergetFileName )){
echo "[ERROR] $TergetFileName not found."
continue
}
# 暗号化
if( $Encrypto ){
echo "[INFO] Encrypto : $TergetFileName"
# 暗号化ファイル名
$EncryptoFileName = $TergetFileName + "." + $ExtName
# データファイル読み込み
$BytePlainData = [System.IO.File]::ReadAllBytes($TergetFileName)
# 暗号
$ByteEncryptoData = AESEncrypto $ByteKey $BytePlainData
if( $ByteEncryptoData -eq $null ){
echo "[FAIL] 暗号失敗"
exit
}
# ファイル出力
[System.IO.File]::WriteAllBytes($EncryptoFileName, $ByteEncryptoData)
}
# 復号化
else{
# 拡張子確認
if( $TergetFileName -notmatch "$ExtName$" ){
echo "[ERROR] $TergetFileName は暗号化ファイルではない"
continue
}
echo "[INFO] Decrypto : $TergetFileName"
# 復号ファイル名
$ChangeString = "."+ $ExtName
$DecryptoFileName = $TergetFileName.Replace($ChangeString,"")
# 暗号化ファイル読み込み
$ByteEncryptoData = [System.IO.File]::ReadAllBytes($TergetFileName)
# 復号
$BytePlainData = AESDecrypto $ByteKey $ByteEncryptoData
if( $BytePlainData -eq $null ){
echo "[ERROR] 復号失敗"
continue
}
# 平文ファイル出力
[System.IO.File]::WriteAllBytes($DecryptoFileName, $BytePlainData)
}
}
|
[Make256Key.ps1]
#####################################################################
# 256 bit の共通鍵を生成する
#####################################################################
Param($Path)
#####################################################################
# バイト配列を Base64 にする
#####################################################################
function Byte2Base64( $Byte ){
$Base64 = [System.Convert]::ToBase64String($Byte)
return $Base64
}
##################################################
# セッション鍵生成
##################################################
function CreateRandomKey( $BitSize ){
if( ($BitSize % 8) -ne 0 ){
echo "Key size Error"
return $null
}
# アセンブリロード
Add-Type -AssemblyName System.Security
# バイト数にする
$ByteSize = $BitSize / 8
# 入れ物作成
$KeyBytes = New-Object byte[] $ByteSize
# オブジェクト 作成
$RNG = New-Object System.Security.Cryptography.RNGCryptoServiceProvider
# 鍵サイズ分の乱数を生成
$RNG.GetNonZeroBytes($KeyBytes)
# オブジェクト削除
$RNG.Dispose()
return $KeyBytes
}
##################################################
# main
##################################################
if( $PSVersionTable.PSVersion.Major -le 2 ){
echo "[FAIL] PowerShell 2.0 以下はサポートしていません"
exit
}
if( $Path -eq $null ){
echo "Usage..."
echo " .\make256key.ps1 -Path KeyFile"
exit
}
# 256 Bitの共通鍵生成
$ByteKey = CreateRandomKey 256
# Base 64 にする
$Base64Key = Byte2Base64 $ByteKey
# ファイル出力
Set-Content -Path $Path -Value $Base64Key -Encoding UTF8
|
関連情報
SHA-2(SHA256) の PowerShell 実装
http://www.vwnet.jp/Windows/PowerShell/SHA256.htm
RSA 公開鍵暗号の PowerShell 実装
http://www.vwnet.jp/Windows/PowerShell/RSACrypto.htm
RSA 電子署名(SHA256)の PowerShell 実装
http://www.vwnet.jp/Windows/PowerShell/RSASignature.htm
HMAC(SHA256) の PowerShell 実装
http://www.vwnet.jp/Windows/PowerShell/HMAC-SHA256.htm
スケジュールジョブ(PowerShell)でパスワードをセキュアに使う(証明書編)
http://www.vwnet.jp/Windows/WS12R2/Password/CertPassword.htm
PowerShell で指定サイズのランダムな文字列/バイナリ列を生成する
http://www.vwnet.jp/Windows/PowerShell/CreateRandomData.htm
PowerShell で公開鍵方式暗号ファイルを交換をする
http://www.vwnet.jp/Windows/PowerShell/PublicKeyCrypto.htm
文字列/Base64/Byte配列を PowerShell で相互変換する
http://www.vwnet.jp/Windows/PowerShell/2017110301/ConvertStringBase64Byte.htm
Copyright © MURA
All rights reserved.