LoginSignup
5
5

More than 3 years have passed since last update.

VBAでSHA256を計算する。

Last updated at Posted at 2019-11-20

この記事について

タイトル通りです。仕事でつかうデータ(主にファイル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進法表示$

このこのうち,ハッシュ(SHA256)の計算はオブジェクトに丸投げするので,
1. 対象データをどうByteの配列に落とすか
2. アウトプットの表示をどうするか
という2点を考えればいいことになる。特に,Byte()に変換してからの処理は全く同じ。
文字列はエンコーディング次第で様々なハッシュ値を持ちうるので,文字列のハッシュ値を求める場合にはエンコーディングの種類を決めておく必要がある。…が調べてみるとなぜか文字列のハッシュを計算するのにつかわれるエンコーディングはutf8が主流のようなので,この記事でもそれに従うことにした。

コード

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



5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5