暗号化キーと初期化ベクタを生成は、RijndaelManagedのGenerateKeyメソッド・GenerateIVメソッドでランダムな暗号化キーと初期化ベクタを生成するようにしました。
そして、生成した暗号化キーと初期化ベクタはレジストリのHKEY_CURRENT_USER以下の任意の場所に保存し、復号化に備えています。
Public Class CrypticClass
Public RegistryKey As String 'レジストリのキー
Private Key As String '暗号化キー(16進文字列)
Private IV As String '初期化ベクタ(16進文字列)
Private aes As System.Security.Cryptography.RijndaelManaged
'定数
Private Const SubkeyKey = "Key" '暗号キー保存用のレジストリのサブキー
Private Const SubkeyIV = "IV" '初期化ベクタ保存用のレジストリのサブキー
Public Sub New()
'初期化
RegistryKey = ""
Key = ""
IV = ""
'RijndaelManagedオブジェクトの作成
aes = New System.Security.Cryptography.RijndaelManaged
End Sub
''' <summary>
''' 暗号化&(無ければ)暗号化キーの生成と保存もします
''' </summary>
''' <param name="strSrc">暗号化する文字列</param>
''' <returns>暗号化された文字列</returns>
Public Function Encrypt(ByVal strSrc As String) As String
Encrypt = ""
If strSrc = "" Then
Exit Function
End If
If RegistryKey = "" Then
Throw New ApplicationException("CrypticClass.RegistryKeyプロパティが設定されていません。")
End If
'暗号化キー・初期化ベクタを取得
GetKey()
'暗号化キー・初期化ベクタが無ければランダムな暗号化キー・初期化ベクタを生成&保存
If (Key = "") Or (IV = "") Then
'ランダムな暗号化キーを生成
aes.GenerateKey()
'ランダムな初期化ベクタを生成
aes.GenerateIV()
'ハイフン区切りの16進数表記に変換
Key = BitConverter.ToString(aes.Key)
IV = BitConverter.ToString(aes.IV)
'生成された暗号化キー・初期化ベクタをレジストリに保存
SaveKey()
'念のため暗号化キー・初期化ベクタを再度読み込む
GetKey()
End If
'キー・初期化ベクタの内容をチェック
If (Key = "") Or (IV = "") Then
Throw New ApplicationException("暗号化キーの生成に失敗しました。")
End If
'暗号化
Encrypt = EncryptString(strSrc)
End Function
''' <summary>
''' キーの取得&復号化
''' </summary>
''' <param name="strSrc">復号化する文字列</param>
''' <returns>復号化された文字列</returns>
Public Function Decrypt(ByVal strSrc As String) As String
Decrypt = ""
If strSrc = "" Then
Exit Function
End If
If RegistryKey = "" Then
Throw New ApplicationException("CrypticClass.RegistryKeyプロパティが設定されていません。")
End If
'暗号化キーを取得
GetKey()
'暗号化キーが無い場合
If (Key = "") Or (IV = "") Then
Throw New ApplicationException("暗号化キーが存在しません。")
End If
'復号化
Decrypt = DecryptString(strSrc)
End Function
''' <summary>
''' キーの所得
''' </summary>
Private Sub GetKey()
'レジストリのキーを開く
Using regkey As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(RegistryKey, False)
'レジストリのキーが存在しない場合
If (regkey Is Nothing) Then
Exit Sub
End If
'サブキーに保存されている暗号化キーを読み込む
Dim strKeyValue As String = CType(regkey.GetValue(SubkeyKey), String)
'サブキーが存在しない場合
If (strKeyValue Is Nothing) Then
Exit Sub
End If
'サブキーに保存されている初期化ベクタを読み込む
Dim strIVValue As String = CType(regkey.GetValue(SubkeyIV), String)
'サブキーが存在しない場合
If (strIVValue Is Nothing) Then
Exit Sub
End If
'値のセット
Key = strKeyValue
IV = strIVValue
End Using
End Sub
''' <summary>
''' キーの保存
''' </summary>
Private Sub SaveKey()
'レジストリのキーを開く(無い場合は作成)
Using regkey As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(RegistryKey)
'レジストリへの書き込み
'サブキーに暗号化キーと初期化ベクタを書き込む
regkey.SetValue(SubkeyKey, Key)
regkey.SetValue(SubkeyIV, IV)
End Using
End Sub
''' <summary>
''' 文字列を暗号化する
''' </summary>
''' <param name="str">暗号化する文字列</param>
''' <returns>暗号化された文字列</returns>
Private Function EncryptString(ByVal str As String) As String
EncryptString = ""
'文字列をバイト型配列にする
Dim bytesIn As Byte() = System.Text.Encoding.UTF8.GetBytes(str)
'共有キーと初期化ベクタを設定
aes.Key = HexToByte(Key)
aes.IV = HexToByte(IV)
'暗号化されたデータを書き出すためのMemoryStream
Using msOut As New System.IO.MemoryStream
'AES暗号化オブジェクトの作成
Dim aesdecrypt As System.Security.Cryptography.ICryptoTransform = aes.CreateEncryptor()
'書き込むためのCryptoStreamの作成
Using cryptStreem As New System.Security.Cryptography.CryptoStream(msOut, aesdecrypt, System.Security.Cryptography.CryptoStreamMode.Write)
'書き込む
cryptStreem.Write(bytesIn, 0, bytesIn.Length)
cryptStreem.FlushFinalBlock()
'暗号化されたデータを取得
Dim bytesOut As Byte() = msOut.ToArray()
'Base64で文字列に変更して結果を返す
EncryptString = System.Convert.ToBase64String(bytesOut)
End Using
End Using
End Function
''' <summary>
''' 暗号化された文字列を復号化する
''' </summary>
''' <param name="str">暗号化された文字列</param>
''' <returns>復号化された文字列</returns>
Private Function DecryptString(ByVal str As String) As String
DecryptString = ""
'共有キーと初期化ベクタを設定
aes.Key = HexToByte(Key)
aes.IV = HexToByte(IV)
'Base64で文字列をバイト配列に戻す
Dim bytesIn As Byte() = System.Convert.FromBase64String(str)
'暗号化されたデータを読み込むためのMemoryStream
Using msIn As New System.IO.MemoryStream(bytesIn)
'AES復号化オブジェクトの作成
Dim aesdecrypt As System.Security.Cryptography.ICryptoTransform = aes.CreateDecryptor()
'読み込むためのCryptoStreamの作成
Using cryptStreem As New System.Security.Cryptography.CryptoStream(msIn, aesdecrypt, System.Security.Cryptography.CryptoStreamMode.Read)
'復号化されたデータを取得するためのStreamReader
Using srOut As New System.IO.StreamReader(cryptStreem, System.Text.Encoding.UTF8)
'復号化されたデータを取得する
Dim result As String = srOut.ReadToEnd()
DecryptString = result
End Using
End Using
End Using
End Function
''' <summary>
''' BitConverter.ToStringの16進数表記をバイト配列に復元する
''' </summary>
''' <param name="strHex">16進数表記の文字列</param>
''' <returns>復元されたバイト配列</returns>
Private Function HexToByte(ByVal strHex As String) As Byte()
Dim i As Integer = 0
Dim strHexChr() As String = Split(strHex, "-")
Dim newBytes(UBound(strHexChr)) As Byte
For i = 0 To UBound(strHexChr)
newBytes(i) = Convert.ToByte(strHexChr(i), 16)
Next i
HexToByte = newBytes
End Function
End Class
また、Encryptメソッドは指定されたレジストリの場所に暗号化キーと初期化ベクタの値が存在しているのかをチェックし、無ければRijndaelManagedのGenerateKeyメソッド・GenerateIVメソッドでランダムな暗号化キーと初期化ベクタを生成してレジストリに保存しています。
ちなみに生成された暗号化キーと初期化ベクタはBitConverter.ToStringメソッドでハイフン区切りの16進数表記の文字列でレジストリに登録されています。
また、暗号化キーと初期化ベクタはアクセスコントロールがチャンとしている場所に保存しないと第三者が覗けてしまって意味が無くなるので保存場所に気を使う必要があります。
最近のコメント