JScriptでHash取得


## はじめに

JScript関連を調べていたところ、どうやら.NETの一部が使えるらしいという事を知りました。
期待したのですが、本当に一部しか公開していませんでした。

その中で使えそうな物として、Hash取得をしてみようと思います。

## 準備

.NET関数を使うにあたり変数にbyte配列を利用する事が多い為、
JScriptから.NET関数用のbyte配列関連のメソッドを用意します。

### 「文字列」⇔「byte配列」

「文字列」と「byte配列」での相互変換のメソッドです。
.NETの「System.Text.Encoding」系のクラスを利用します。
その為、「encode」は以下のものが指定出来るようです。

* System.Text.ASCIIEncoding
* System.Text.UnicodeEncoding
* System.Text.UTF7Encoding
* System.Text.UTF8Encoding

```js
// 「System.Text.UTF8Encoding」生成
var encorde = new ActiveXObject("System.Text.UTF8Encoding");

// 「文字列」から「byte配列」へ変換
function string2bytes(string) {
    var bytes = null;
    // byte配列取得
    bytes = encorde.GetBytes_4(string);
    return bytes;
}

// 「byte配列」から「文字列」へ変換
function bytes2string(bytes) {
    var string = null;
    // 文字列取得
    string = encorde.GetString(bytes);
    return string;
}
```

「GetBytes_4」というメソッドがあります。
.NETでは「GetBytes」というメソッドが複数あり、
それを強制的に指定する為に「_n」（nは数値）とするそうです。
何番にどれが入っているかは、詳しく調べてません。

### 「ファイル」⇒「byte配列」

ファイルの「byte配列」を取得するメソッドです。
「ADODB.Stream」を利用してバイナリとしてファイルを読込、その後データを読み取ります。

```js
// 「ファイル」から「byte配列」
function file2bytes(fileName) {
    var bytes = null;
    // 「ADODB.Stream」生成
    var stream = new ActiveXObject("ADODB.Stream");
    // 「Type」設定（1、バイナリ）
    stream.Type = 1;
    // 開く
    stream.Open();
    // ファイルロード
    stream.LoadFromFile(fileName);
    // データ読込
    bytes = stream.Read();
    // 閉じる
    stream.Close();
    stream = null;
    return bytes;
}
```

### 「byte配列」⇔「16進数文字列」

「byte配列」と「16進数文字列」での相互変換のメソッドです。
MSXMLの「DOMDocument」を利用します。

```js
// 「byte配列」から「16進数文字列」
function bytes2hex(bytes) {
    var hex = null;
    // 「DOMDocument」生成
    var doc = new ActiveXObject("Msxml2.DOMDocument");
    // 「DomNode」生成（hex）
    var element = doc.createElement("hex");
    // 「dataType」に「bin.hex」を設定
    element.dataType = "bin.hex";
    // 「nodeTypedValue」に「byte配列」を設定
    element.nodeTypedValue = bytes;
    // 「text」を取得
    hex = element.text;
    // 後処理
    element = null;
    doc = null;
    return hex;
}

// 「16進数文字列」から「byte配列」
function hex2bytes(hex) {
    var bytes = null;
    // 「DOMDocument」生成
    var doc = new ActiveXObject("Msxml2.DOMDocument");
    // 「DomNode」生成（hex）
    var element = doc.createElement("hex");
    // 「dataType」に「bin.hex」を設定
    element.dataType = "bin.hex";
    // 「text」に「16進数文字列」を設定
    element.text = hex;
    // 「nodeTypedValue」を取得
    bytes = element.nodeTypedValue;
    // 後処理
    element = null;
    doc = null;
    return bytes;
}
```
「dataType」に指定した、「bin.hex」はバイナリを16進数で格納する形式らしいのですが、詳細な仕様は見つける事ができませんでした。

## Hash取得

「MD5」と「SHA1」を取得してみます。

### 文字列のHash

```js
// Hash取得対象文字列
var string = "0123456789abcdefghijklmnopqrstuvwxyz";
// 文字列をbyte配列に変換
var bytes = string2bytes(string);
var hash = null;

// MD5用プロバイダ生成
var md5 = new ActiveXObject("System.Security.Cryptography.MD5CryptoServiceProvider");
// Hash値計算
md5.ComputeHash_2(bytes);
// Hash値取得
hash = md5.Hash;
// Hash値を16進数文字列に変換
WScript.Echo("MD5 :" + bytes2hex(hash));
// 後処理
md5.Clear();
md5 = null;

// SHA1用プロバイダ生成
var sha1 = new ActiveXObject("System.Security.Cryptography.SHA1CryptoServiceProvider");
// Hash値計算
sha1.ComputeHash_2(bytes);
// Hash値取得
var hash = sha1.Hash;
// Hash値を16進数文字列に変換
WScript.Echo("SHA1:" + bytes2hex(hash));
// 後処理
sha1.Clear();
sha1 = null;
```

ここでも、「ComputeHash_2」で「_n」を利用しています。

### ファイルのHash

「byte配列」取得部分が異なるだけで、文字列の時と同じです。

```js
// スクリプト自身のファイルをbyte配列に変換
var bytes = file2bytes(WScript.ScriptFullName);
var hash = null;

// MD5用プロバイダ生成
var md5 = new ActiveXObject("System.Security.Cryptography.MD5CryptoServiceProvider");
// Hash値計算
md5.ComputeHash_2(bytes);
// Hash値取得
hash = md5.Hash;
// Hash値を16進数文字列に変換
WScript.Echo("MD5 :" + bytes2hex(hash));
// 後処理
md5.Clear();
md5 = null;

// SHA1用プロバイダ生成
var sha1 = new ActiveXObject("System.Security.Cryptography.SHA1CryptoServiceProvider");
// Hash値計算
sha1.ComputeHash_2(bytes);
// Hash値取得
var hash = sha1.Hash;
// Hash値を16進数文字列に変換
WScript.Echo("SHA1:" + bytes2hex(hash));
// 後処理
sha1.Clear();
sha1 = null;
```