designetwork

ネットワークを軸としたIT技術メモ

Node.jsでSJIS文字列をSHA1ハッシュする

日本国内のシステムでは、いまだに文字コードとしてSJIS(シフトJIS, Shift JIS)が使われているものがある。電文の送受信にあたり、整合性の確認のためにハッシュ値を付与する場合、暗号化ライブラリで文字コードを指定してハッシュを生成する必要がある。

参考

ja.stackoverflow.com

実装したい内容はこちらに近いのですが、質問が伝わらず回答が得られていない。

環境情報

Node.jsバージョン

  • Node.js: v16.17.0
  • npm: 8.19.2
  • TypeScript: 4.8.3

使用ライブラリ

TypeScript

npm install

npm install crypto-js
npm install --save-dev @types/crypto-js
npm install iconv-lite

sha1.ts

ポイントは後述。

import { SHA1, enc } from "crypto-js";
import * as iconv from "iconv-lite";

console.log(iconv.encode("testテスト", "Shift_JIS"));
console.log(iconv.encode("testテスト", "Shift_JIS").toString("base64"));

const sha1 : string = SHA1(enc.Base64.parse(iconv.encode("testテスト", "Shift_JIS").toString("base64"))).toString();
console.log("sha1:" +sha1);

実行結果

$ ts-node ./sha1.ts                  
<Buffer 74 65 73 74 83 65 83 58 83 67>
dGVzdINlg1iDZw==
sha1:fb71edbbaeaf718cd7f7734362a7ee14f30f5114 

sha1ハッシュが得られた。

SJISバイト列のbase64をcrypto-jsに渡すのがポイント

(method) CipherHelper.encrypt(message: string | CryptoJS.lib.WordArray, key: string | CryptoJS.lib.WordArray, cfg?: CipherOption | undefined): CryptoJS.lib.CipherParams

対象文字列はstring, CryptoJS.lib.WordArrayのいずれかとなるが、stringを渡すとUTF-8で扱われてしまうため、CryptoJS.lib.WordArrayを使用する。CryptoJS.lib.WordArrayを生成するとき、enc.xxx.parseでSJISは直接扱えないようなので、iconvでSJISバイト列をbase64にしたものを渡す。

結果検証

SJIS

SJIS SHA1ハッシュの整合性の検証として、こちらを使用させていただきました。

tool-taro.com

生成されるハッシュ値が一致している。

UTF-8

UTF-8の場合はopensslコマンドで検証できる。

const sha1_utf : string = SHA1(enc.Utf8.parse("testテスト")).toString();
console.log("sha1-utf:" +sha1_utf);
---
sha1-utf:bdafcf6b7484bdc7b836a669b8548b9eb5ae665b
$ echo -n "testテスト" | openssl sha1                         
bdafcf6b7484bdc7b836a669b8548b9eb5ae665b

JavaScript

npm install

npm install crypto-js
npm install iconv-lite

sha1.js

基本は同上。importrequireに置き換え、変数の型宣言を削除する。

var CryptoJS = require("crypto-js");
var SHA1 = CryptoJS.SHA1;
var enc = CryptoJS.enc;
var iconv = require("iconv-lite");

console.log(iconv.encode("testテスト", "Shift_JIS"));
console.log(iconv.encode("testテスト", "Shift_JIS").toString("base64"));

const sha1 = SHA1(enc.Base64.parse(iconv.encode("testテスト", "Shift_JIS").toString("base64"))).toString();
console.log("sha1:" +sha1);

実行結果

$ node ./sha1.js 
<Buffer 74 65 73 74 83 65 83 58 83 67>
dGVzdINlg1iDZw==
sha1:fb71edbbaeaf718cd7f7734362a7ee14f30f5114

結果は同上。

まとめ - Node.jsでSJIS文字列をSHA1ハッシュする

crypto-jsとiconv-liteを組み合わせ、SJISバイト列のbase64を渡すことで、SJIS文字列をSHA1ハッシュ化することができた。

関連情報

designetwork.daichi703n.com