#この記事について
タイトル通りです。仕事でつかうデータ(主にファイルor文字列)に変更があったかどうかを知りたいときに便利かなと思い,調べたSHA256の計算方法をまとめてみます。
#参考にした記事
Excel VBA で SHA256
VBAでバイナリの読み書き
目的の文字コードに合ったEncodingオブジェクトを取得する
#環境
64bit版 Windows10 / VBA(EXCEL): Retail 7.1.1091
#準備
.NET Framework 3.5が有効になっていることを確認しましょう。CreateObjectで.NETの関数を借りてくるので, これが有効になっていないとハッシュを計算するためのオブジェクトが作れません。私はこれでしばらく足止めを食らいました。
「コントロールパネル>プログラム>Windowsの機能の有効化または無効化」から有効にできます。
#処理の流れ
- ファイルのハッシュ化
- $ファイル\xrightarrow{\rm コピー}{\rm Byte()}\xrightarrow{\rm SHA256} {\rm Byte(31)}\rightarrow 16進法表示$
- 文字列のハッシュ化
- $文字列\xrightarrow{\rm エンコード} {\rm Byte()}\xrightarrow{\rm SHA256} {\rm Byte(31)}\rightarrow 16進法表示$
#コード
CreateObjectは比較的重い処理のようなので,何度もハッシュを計算する場合を想定して一度生成したオブジェクトは開放せずに使いまわすようにした。(暗号学的ハッシュは…と言って一般化しすぎるとそうでない例もあるかもしれないので,少なくとも)SHA256のアウトプットは固定長(256bit)の整数で,Byte()としての長さと16進法表示したときの長さは初めからわかっているのでそれらは定数として定義した。
Option Explicit
Private Const SHA256_LENGTH = 32
Private Const SHA256_LENGTH_AS_STRING = 64
Private objUTF8 As Object
Private objSHA256 As Object
'文字列からハッシュを計算する関数
Public Function String2SHA256$(str$)
'必要ならオブジェクトを初期化してエンコード
If objUTF8 Is Nothing Then
Set objUTF8 = CreateObject("System.Text.UTF8Encoding")
End If
Dim code() As Byte
code = objUTF8.GetBytes_4(str)
'必要ならオブジェクトを初期化してハッシュを計算
If objSHA256 Is Nothing Then
Set objSHA256 = CreateObject("System.Security.Cryptography.SHA256Managed")
End If
Dim hashValue() As Byte
hashValue = objSHA256.ComputeHash_2(code)
'16進法表示に変換
Dim description As String * SHA256_LENGTH_AS_STRING
Dim i&
For i = 0 To SHA256_LENGTH - 1
Mid(description, i * 2 + 1) = Right("0" & Hex(hashValue(i)), 2)
Next i
String2SHA256 = description
End Function
'ファイル(のフルパス)からハッシュを計算する関数
Public Function File2SHA256$(fullPath$)
'指定したファイルがあるかどうか確認
Dim targetFileExists As Boolean
targetFileExists = Len(Dir(fullPath)) <> 0
If Not targetFileExists Then GoTo NoSuchFile
'ファイル読み込み
Dim buff() As Byte
Dim ff&
ff = FreeFile
Open fullPath For Binary Lock Read As #ff
ReDim buff(LOF(ff)-1)
Get #ff, , buff
Close #ff
'必要ならオブジェクトを初期化してハッシュを計算
If objSHA256 Is Nothing Then
Set objSHA256 = CreateObject("System.Security.Cryptography.SHA256Managed")
End If
Dim hashValue() As Byte
hashValue = objSHA256.ComputeHash_2(buff)
'16進法表示に変換
Dim description As String * SHA256_LENGTH_AS_STRING
Dim i&
For i = 0 To SHA256_LENGTH - 1
Mid(description, i * 2 + 1) = Right("0" & Hex(hashValue(i)), 2)
Next i
File2SHA256 = description
Exit Function
NoSuchFile:
MsgBox "そんなファイルないよ。"
End Function