WSHのVBScriptでsha1ハッシュを生成するサンプル(DLL不要)
今日はコードサンプルを投稿したい気分だなぁ、ということで過去に作ったサンプルを漁っていたのですが、VBScriptでsha1ハッシュを生成するサンプルを発見しました。
コンパクトなサンプルだし、既にたくさん記事が出てるかなぁ、と「VBScript sha1」でググったら外部DLLをインストールして使うサンプルばかりなんですね。ちょっと驚いた。
わざわざ外部DLLをインストールしなくてもVBScriptでsha1ハッシュは生成できるので、さっそくサンプルコードを紹介していきます。
…といっても、.NET Frameworkは使うんですけどね。
VBScriptでsha1ハッシュを生成する
サンプルコード
'//ハッシュ化する文字列
strIn = "test1234"
'//入力された文字列(UTF8)をバイト配列へ変換
bytes = CreateObject("System.Text.UTF8Encoding").GetBytes_4(strIn)
'//ハッシュ計算
Set sha1 = CreateObject("System.Security.Cryptography.SHA1CryptoServiceProvider")
sha1.ComputeHash_2(bytes)
hash = sha1.Hash
解説
.NET Frameworkオブジェクトである System.Text.UTF8Encodingと System.Security.Cryptography.SHA1CryptoServiceProvider を使っていますが、Windows 10ならデフォルトで .NET Framework 4.6以降がインストールされているため問題なく使えるハズです。
やっていることは単純で、ハッシュ化したい文字列(strIn変数)をバイト配列に変換し、そのバイト配列を SHA1CryptoServiceProvider の ComputeHash_2 関数でハッシュ化しているだけ。
ただ、この後、WScript.Echo hash などとハッシュ文字列を表示しよう、と思っても文字化けしてちゃんと表示されません。だって、バイナリデータなんだもの。
VBScriptでsha1ハッシュ文字列を生成する
サンプルコード
'//ハッシュ化する文字列
strIn = "test1234"
'//入力された文字列(UTF8)をバイト配列へ変換
bytes = CreateObject("System.Text.UTF8Encoding").GetBytes_4(strIn)
'//ハッシュ計算
Set sha1 = CreateObject("System.Security.Cryptography.SHA1CryptoServiceProvider")
sha1.ComputeHash_2(bytes)
hash = sha1.Hash
'//バイト配列を16進文字列へ変換
For pos = 1 To LenB(hash)
strOut = strOut & Right("0" & Hex(AscB(MidB(hash, pos, 1))), 2)
Next
strOut = LCase(strOut)
WScript.Echo strOut
出力結果
9bc34549d565d9505b287de0cd20ac77be1d3f2c
解説
というわけで、今度は sha1.Hash でハッシュを取得するまでは同じ処理で、その後にバイト配列を16進文字列へ変換するコードを追加しています。
MSXML2.DOMDocumentを使って楽しても良いんですけどねー。コードの行数はほとんど変わらないし、VBScriptの機能だけで出来るならそのほうが良いかなってことで、MidBで1バイトずつ切り出して、AscBでコード抽出して、Hexで16進数にしています。
そしてHex関数だと英字が大文字になってなんだか気持ち悪いので、最後にLCaseで小文字にしています。それだけ。
まとめ
- VBScriptでsha1ハッシュ文字列を生成するのに別途DLLをインストールする必要はない。
- .NET Frameworkの UTF8Encoding と SHA1CryptoServiceProvider を使うのが(たぶん)最もスマート。
- Hashで返されるデータはバイナリ(バイト配列)なので、ハッシュ文字列にするためにはHex関数など、一工夫必要。
といったところでしょうか。
2021年1月 追記
コメント欄の指摘によりコードの間違いが発覚。訂正しました。
誤)bytes = CreateObject("System.Text.UnicodeEncoding").GetBytes_4(strIn)
正)bytes = CreateObject("System.Text.UTF8Encoding").GetBytes_4(strIn)