本気でVBAからAES-256 CBCを扱う方法を考える
VBAからAES-256 CBCを扱う方法を理解したので共有します。
本題の前に・・・
時折AESのKeyの値として、MD5で取得した16進数文字列をByte列にしたものを・・・
と言うコードサンプルを見る事があります。
16進数の文字種は0-9a-fの16種類ですから、AES-256のパスワード長は32byteなので、強度が著しく低下してしまう事が分かると思います。
SHA-256で生成したバイト列を使うと良いでしょう。
強度の差は下表のとおりです。
16進数文字列→Byte列 | 32^16 = 1.20892581961463E24 |
SHA-256のByte列 | 32^256 = 2.08158643893288E385 |
あと、IVはAESを提供するオブジェクトのデフォルト値を使うのが適切です。
万が一、そのサービスが生成するIVに十分な強度が無い場合は、ランダムに0~255の値が格納された16Byte列を利用すると良いでしょう。
IVは決して使い回さず、暗号化する時に生成し、復号時に使用したら、新たなIVを生成するようにします。
本題のソースです、Classにしてあります。
ライセンスはMITライセンスね。
Option Explicit Private privateAes As Object Private Const BLOCK_SIZE As Byte = 128 Enum AesKeySize AesKeySize_128 = 128 AesKeySize_192 = 192 AesKeySize_256 = 256 End Enum Enum AesMode AesMode_CBC = 1 AesMode_ECB = 2 AesMode_OFB = 3 AesMode_CFB = 4 AesMode_CTS = 5 End Enum Enum AesPaddingMode AesPaddingMode_None = 1 AesPaddingMode_PKCS7 = 2 AesPaddingMode_Zeros = 3 AesPaddingMode_ANSIX923 = 4 AesPaddingMode_ISO10126 = 5 End Enum Public Property Get GetKeySize() As AesKeySize GetKeySize = privateAes.KeySize End Property Public Property Let SetKeySize(key_size As AesKeySize) privateAes.KeySize = key_size End Property Public Property Get GetMode() As AesMode GetMode = privateAes.Mode End Property Public Property Let SetMode(field_mode As AesMode) privateAes.Mode = field_mode End Property Public Property Get GetPadding() As AesPaddingMode GetPadding = privateAes.Padding End Property Public Property Let SetPadding(padding_mode As AesPaddingMode) privateAes.Padding = padding_mode End Property Public Property Get GetIV() GetIV = privateAes.iv End Property Public Property Let SetIV(iv_bytes) Dim bytes() As Byte: bytes = iv_bytes privateAes.iv = bytes End Property Public Property Get GetKey() GetKey = privateAes.Key End Property Public Property Let SetKey(key_bytes) Dim bytes() As Byte: bytes = key_bytes privateAes.Key = bytes End Property Public Sub CreateKey() Call privateAes.GenerateKey End Sub Public Sub CreateIV() Call privateAes.GenerateIV End Sub Public Function Encryptor(target_bytes) Dim encrypto As Object Set encrypto = privateAes.CreateEncryptor Dim bytes() As Byte: bytes = target_bytes Dim result() As Byte result = encrypto.TransformFinalBlock(bytes, 0, UBound(bytes) + 1) Encryptor = result End Function Public Function Decryptor(encrypto_bytes) Dim decrypto As Object Set decrypto = privateAes.CreateDecryptor Dim bytes() As Byte: bytes = encrypto_bytes Dim result() As Byte result = decrypto.TransformFinalBlock(bytes, 0, UBound(bytes) + 1) Decryptor = result End Function Private Sub Class_Initialize() Set privateAes = CreateObject("System.Security.Cryptography.RijndaelManaged") With privateAes .KeySize = 256 .Mode = 1 .Padding = 2 .BlockSize = BLOCK_SIZE Call .GenerateKey Call .GenerateIV End With End Sub Private Sub Class_Terminate() Set privateAes = Nothing End Sub
簡単な使い方はこんな感じ。
Sub Sample() Dim aes As CryptoAes: Set aes = New CryptoAes Dim target As String: target = "暗号化する文字列" Dim encrypto() As Byte encrypto = aes.Encryptor(target) Dim decrypto() As Byte decrypto = aes.Decryptor(encrypto) Debug.Print decrypto End Sub
今度、実用に耐えられるサンプルコードを用意します。