ExcelマクロでTriple DESを組んでみた
本記事は、Triple DESについて述べます。
Triple DESのアルゴリズムは次の通りです。
まず、64ビットのDataと64ビットのIV(Initialization Vector)について、ビットごとのXOR(排他的論理和)をとり、改めてDataとします。
IVの初期値は、”0000000000000000h”のような値を取り決めておきます。次回からは、最後に暗号化した暗号コードがIVになります。
Triple DESは、一般に、2つの64ビットのキーを使います。
暗号化する場合は、まず、第1のキーで、暗号化します。
次に第2のキーで復号します。
最後に第3のキーで暗号化します。
もし、第1のキーと第2のキーが同じであれば、複合過程で元のデータに戻るので、DESを1回かけたことと同じになります。
では、Triple DESのVBAコードを示します。
'-----------------------------------------------------------------------
' Summary: 2つの16進文字列のビットごとのXorをとる
' Input : str1: 第1の16進数文字列
' : str2: 第2の16進数文字列
' Returns: Xorをとった結果
'-----------------------------------------------------------------------
Private Function ExclusiveOR( _
ByVal str1 As String, _
ByVal str2 As String) _
As String
Dim i As Integer ' 制御変数
Dim strTmp As String ' 戻り値作成用
' 戻り値をクリア
strTmp = ""
' 文字列の長さが一致していることをチェック
If Len(str1) <> Len(str2) Then Exit Function
' 頭から1文字ずつ処理する
For i = 1 To Len(str1)
' それぞれの文字列から1文字ずつ取り出してXorをとり、追記
strTmp = strTmp & Hex(("&H" & Mid(str1, i, 1)) _
Xor ("&H" & Mid(str2, i, 1)))
Next i
' 戻り値としてセットする
ExclusiveOR = strTmp
End Function
'-----------------------------------------------------------------------
' Summary: Triple DES
' Input : strDataHex: 16進文字列64ビット長のデータ
' : strKey1Hex: 16進文字列64ビット長の第1のキー
' : strKey2Hex: 16進文字列64ビット長の第2のキー
' : strIV : 16進文字列64ビット長のInitialization Vector
' : blnEnc : Ture → 暗号化, False → 復号
' Returns: Xorをとった結果
'-----------------------------------------------------------------------
Public Function TripleDES( _
ByVal strDataHex As String, _
ByVal strKey1Hex As String, _
ByVal strKey2Hex As String, _
ByVal strIV As String, _
ByVal blnEnc As Boolean) _
As String
Const cstDec As Boolean = False ' 復号を示す定数
Const cstEnc As Boolean = True ' 暗号化を示す定数
Dim bytData() As Byte ' バイト配列に変換されたData
Dim bytKey1() As Byte ' バイト配列に変換された第1のキー
Dim bytKey2() As Byte ' バイト配列に変換された第2のキー
Dim bytM1() As Byte ' バイト配列で得られる第1段階の暗号/復号
Dim bytM2() As Byte ' バイト配列で得られる第2段階の暗号/復号
Dim bytResult() As Byte ' バイト配列で得られる第3段階の暗号/復号
' 暗号化の場合、データとIVでビットごとのXorをとる
If blnEnc = cstEnc Then strDataHex = ExclusiveOR(strDataHex, strIV)
' Data、第1のキー、第2のキーをバイト配列に変換する
bytData = Bin2Byte(Hex2Bin(strDataHex))
bytKey1 = Bin2Byte(Hex2Bin(strKey1Hex))
bytKey2 = Bin2Byte(Hex2Bin(strKey2Hex))
' 暗号化/復号で分岐
If blnEnc = cstEnc Then
' 暗号化の場合は、第1のキーで暗号化する
bytM1 = DES(bytData, bytKey1, cstEnc)
' 第2のキーで復号する
bytM2 = DES(bytM1, bytKey2, cstDec)
' 第3のキーで暗号化する
bytResult = DES(bytM2, bytKey1, cstEnc)
Else
' 復号の場合は、第1のキーで復号する
bytM2 = DES(bytData, bytKey1, cstDec)
' 第2のキーで暗号化する
bytM1 = DES(bytM2, bytKey2, cstEnc)
' 第1のキーで復号する
bytResult = DES(bytM1, bytKey1, cstDec)
End If
' バイト配列を16進数の文字列に変換する
TripleDES = Bin2Hex(Byte2Num(bytResult))
' 復号の場合はIVとXorをとる
If blnEnc = cstDec Then TripleDES = ExclusiveOR(TripleDES, strIV)
End Function
申し訳ありませんが、本記事のコードだけですと、DESの機能が無いので動きません。
先ずは、以前の記事で示したDESのコードを標準モジュールにコピペし、その下に本記事のコードをコピペしてください。
動作確認
そもそも、僕は、MIFARE Ultralight CというICカードのデータシートを読んでいて、Triple DESが必要になったのでした。そのデータシートはこれです。
このデータシートの7.5.6にTriple DES(3DES)の使用例が載っているので、答え合わせができます。
Excelで認証過程をシミュレートした結果を以下に示します。
まず、カードが乱数を用いてRndBを生成し、暗号化してカードリーダに送ります。
カードリーダは、複号してRndBを得ます。
次に、カードリーダは乱数を用いてRndAを生成します。
さらに、RndBを8ビット左に回転させてRndB’を得ます。
このRndAとRndB’をつなげて暗号化し、カードに送ります。
この暗号化の過程では、先ほどカードから送られてきた暗号や、RndAの暗号がIVとして逐次使われます。
カードは、暗号を複号してRndAを得ます。
また、RndB’を得ることで、カードリーダがキーを共有していることが分かります。
さらに、RndAを8ビット左に回転させてRndA’を得て、これを暗号化してカードリーダに送ります。
カードリーダは暗号を復号して、RndA’を得ることにより、カードがキーを共有していることを知ります。
こうして、お互いに、認証を取ることができます。
シミュレーション結果の最後に至るまで、データシートと値が一致しましたので、IVの使い方を含めて動作確認ができました。
なお、この表を得るために使用している式を以下に示します。
式中で使っている名前とセルの対応はこちらです。
KEY1、KEY2については、当初から同じ名前のセルがあるので、前にアンダスコアを付けています。
まとめ
ExcelのVBAで、Triple DESを実現しました。
MIFARE Ultralight Cを早く使ってみたいのはやまやまですが、いつ着手できるかなぁ。
コメント