XMLエレメントを暗号化・復号化する
XMLファイルに書かれたパスワードの暗号化というお題をいただきまして、あれやこれや検索してみた中でMSDNに「XML 暗号化と XML デジタル署名」というのがありました。
ここでは、DESの後継とされるRijndael(ラインダール)アルゴリズムを使用したXMLの暗号化・復号化を行います。
以下のソースは、ほぼMSDNのものです。(System.Securityの参照設定が必要です。)
MSDNで紹介されているソースは、RijndaelManagedを生成した時に、共通Key、IVが自動的に生成され、そのまま使用しています。以下のソースでは、共通Key、IVを指定するように変更してあります。
共通Keyは、決まったサイズが必要となり指定できるサイズは、LegalKeySizesプロパティで確認できます。(128bit,192bit,256bit)
IVも同様に、決まったサイズが必要となり指定できるサイズは、BlockSize プロパティで確認できます。(8bit)
Imports System
Imports System.Xml
Imports System.Text
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Module basXmlCrypt
Sub Main()
Dim key As RijndaelManaged = Nothing
Try
' Rijndaelオブジェクトの生成(この時、KeyとIVも生成される。)
key = New RijndaelManaged()
' 共通Key及びIVの指定
key.Key = Encoding.Unicode.GetBytes("0123456789012345")
key.IV = Encoding.Unicode.GetBytes("01234567")
Dim xmlDoc As New XmlDocument()
xmlDoc.PreserveWhitespace = True
' XMLを読み込みます。
xmlDoc.Load("test.xml")
' 指定したエレメントを暗号化します。
Encrypt(xmlDoc, "Password", key)
Console.WriteLine("The element was encrypted")
Console.WriteLine(xmlDoc.InnerXml)
Decrypt(xmlDoc, key)
Console.WriteLine("The element was decrypted")
Console.WriteLine(xmlDoc.InnerXml)
Catch e As Exception
Console.WriteLine(e.Message)
Finally
' Clear the key.
If Not (key Is Nothing) Then
key.Clear()
End If
End Try
End Sub
Sub Encrypt(ByVal Doc As XmlDocument, ByVal ElementName As String, ByVal Key As SymmetricAlgorithm)
' 引数確認
If Doc Is Nothing Then
Throw New ArgumentNullException("Doc")
End If
If ElementName Is Nothing Then
Throw New ArgumentNullException("ElementToEncrypt")
End If
If Key Is Nothing Then
Throw New ArgumentNullException("Alg")
End If
' 指定されたエレメントの取得
Dim elementToEncrypt As XmlElement = Doc.GetElementsByTagName(ElementName)(0)
' エレメントが存在しなかった時の例外
If elementToEncrypt Is Nothing Then
Throw New XmlException("The specified element was not found")
End If
' XML暗号化インスタンスの生成
Dim eXml As New EncryptedXml()
' 暗号化を行います。
Dim encryptedElement As Byte() = eXml.EncryptData(elementToEncrypt, Key, False)
' XMLの暗号化要素を作成します。
Dim edElement As New EncryptedData()
edElement.Type = EncryptedXml.XmlEncElementUrl
Dim encryptionMethod As String = Nothing
If TypeOf Key Is TripleDES Then
encryptionMethod = EncryptedXml.XmlEncTripleDESUrl
ElseIf TypeOf Key Is DES Then
encryptionMethod = EncryptedXml.XmlEncDESUrl
End If
If TypeOf Key Is Rijndael Then
Select Case Key.KeySize
Case 128
encryptionMethod = EncryptedXml.XmlEncAES128Url
Case 192
encryptionMethod = EncryptedXml.XmlEncAES192Url
Case 256
encryptionMethod = EncryptedXml.XmlEncAES256Url
End Select
Else
Throw New CryptographicException("The specified algorithm is not supported for XML Encryption.")
End If
edElement.EncryptionMethod = New EncryptionMethod(encryptionMethod)
' 暗号化されたデータを追加します。
edElement.CipherData.CipherValue = encryptedElement
' エレメントを暗号化されたエレメントへ置き換えます。
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, False)
End Sub
Sub Decrypt(ByVal Doc As XmlDocument, ByVal Alg As SymmetricAlgorithm)
' 引数確認
If Doc Is Nothing Then
Throw New ArgumentNullException("Doc")
End If
If Alg Is Nothing Then
Throw New ArgumentNullException("Alg")
End If
' 暗号化されたエレメントを取得します。
Dim encryptedElement As XmlElement = Doc.GetElementsByTagName("EncryptedData")(0)
' エレメントが存在しなかった時の例外
If encryptedElement Is Nothing Then
Throw New XmlException("The EncryptedData element was not found.")
End If
Dim edElement As New EncryptedData()
edElement.LoadXml(encryptedElement)
Dim exml As New EncryptedXml()
' 復号化を行います。
Dim rgbOutput As Byte() = exml.DecryptData(edElement, Alg)
' 復号化されたエレメントへ置き換えます。
exml.ReplaceData(encryptedElement, rgbOutput)
End Sub
End Module