Column

コラム

  • 【テックコラム】JavaScript Web Crypto ...
  • JavaScript
  • SHA256
  • テックコラム
  • ハッシュ化

【テックコラム】JavaScript Web Crypto API で SHA256 ハッシュ値を作る

● はじめに


こんにちは。

今回は外部ライブラリを使わず、JavaScriptの標準ライブラリのWeb Crypto APIでSHA256でハッシュ化した話をします。

● SHA256とは


SHA256はハッシュ関数のうちのひとつです

ハッシュ関数とは、渡されたデータを決まった手順で計算し、一定の長さの文字列を出力する関数のことです。

SHA256でハッシュ化することで、256bit(32バイト)の長さのハッシュ値を得ることができます。

例)

12345abcde(ハッシュ化前)

3c373f4953b85cdea588e0436c134c819f570b72c1db740eb35cfc942baa2bce(ハッシュ化後)

ハッシュ化された値を元の値に戻すことは非常に困難です。

同じ入力データでハッシュ化を行うと、毎回同じハッシュ値が生成されます。

● JavaScriptでハッシュ化する方法


1.ライブラリを利用する

jsSHAなど、サードパーティ製のライブラリがあります。これらを利用して文字列をハッシュ化することもできます。

タイトルの通り今回はこの方法は使っていません。

サーバー上に JavaScriptファイル を設置することになり、設置先サーバー等の検討をしなければいけなくなるため、JavaScript のみで出来る方法を採用しました。

2.Web Crypto APIを利用する

JavaScriptに標準で備わっているAPIです。今回はこちらの形で、SHA256への変換を行っています。

外部のコードに依存することなく変換を行うことができ便利でした。

ただし、非SSL環境で使用できない、IE11に対応したい場合はコードの変更など制約があります。以下でご紹介するコードはIE11に対応していません。※後述

コードの作成にあたっては、以下のMDNの記事を参考にしました。

SubtleCrypto.digest() – Web API | MDN

● コード


var text = 'ハッシュ化したい文字';

function async_digestMessage(message) {
    return new Promise(function(resolve){
    var msgUint8 = new TextEncoder("utf-8").encode(message);
    crypto.subtle.digest('SHA-256', msgUint8).then(
        function(hashBuffer){
            var hashArray = Array.from(new Uint8Array(hashBuffer));
            var hashHex = hashArray.map(function(b){return b.toString(16).padStart(2, '0')}).join('');
            return resolve(hashHex);
        });
    })
}

function getHashText(text) {
    // ハッシュ化後の文字列を表示
    console.log(text);
}

if(window.Promise && window.crypto){
    async_digestMessage(text).then(
        function(shatxt){
            getHashText(shatxt);
        }
    ).catch(function(e){
        console.log('エラー:', e.message);
    })
}else{
    console.log('Promiseかcryptoに非対応');
}

こちらのコードの、

var text = 'ハッシュ化したい文字';

にハッシュ化したい文字を入力してコードを実行すると、ハッシュ化後のコードを得ることができます。

試しに、この【ハッシュ化したい文字】を入力したままコードを実行してみます。

ハッシュ化後の値
3b1f06cbba487277c3ec1d35335bae10e026fd1095721f9ad1bb50cfea380d93

という文字列を得ることができました。正しくハッシュ化できているかどうかを確認するために、他のSHA256ハッシュ化を扱うプログラムで同じ文字列 【ハッシュ化したい文字】 を変換し、同じハッシュ値になることを確認してみます。

Pythonのhashlibライブラリを使って、同じ文字を変換しました。

pythonでのハッシュ化結果

同じ値になりました!

● コードの中身について


下記がハッシュ化のためにWeb Crypto APIを使用している関数です。どういった手順でハッシュ値を得ているのか見てみましょう。

function async_digestMessage(message) {
    return new Promise(function(resolve){
    var msgUint8 = new TextEncoder("utf-8").encode(message);
    crypto.subtle.digest('SHA-256', msgUint8).then(
        function(hashBuffer){
            var hashArray = Array.from(new Uint8Array(hashBuffer));
            var hashHex = hashArray.map(function(b){return b.toString(16).padStart(2, '0')}).join('');
            return resolve(hashHex);
        });
    })
}

まず、async_digestMessage関数を下記のように呼び出します。ハッシュ化したい文字列を引数としてasync_digestMessage関数に渡します。

async_digestMessage(text).then(
        function(shatxt){
            getHashText(shatxt);
      }
)

結果はPromiseで返ってくるので、.then(…)内に記載した関数の引数(shatxt)としてハッシュ化後の値が渡されます。

async_digestMessage関数の中では、引数messageにハッシュ化したい文字列が渡されます。

function async_digestMessage(message) {

最初に、文字列をバイナリへ変換しします。

  var msgUint8 = new TextEncoder("utf-8").encode(message);

次に、Web Crypto APIの出番です。変換した値をcrypto.subtle.digestに渡します。

crypto.subtle.digest('SHA-256', msgUint8).then(

Promiseで返ってきた結果がhashBuffer変数に渡されます。

ここではArrayBufferとしてハッシュ値のバイナリデータが得られるので、それを16進文字列に加工します。

function(hashBuffer){
    var hashArray = Array.from(new Uint8Array(hashBuffer));
    var hashHex = hashArray.map(function(b){return b.toString(16).padStart(2, '0')}).join('');
   return resolve(hashHex);
});

加工後の値をハッシュ値として返します。

● 利用上の制限について


・window.crypto.subtleはSSL非対応ページでは利用不可です。

非SSLページでのエラーメッセージ

http://~… のページで実行すると、エラーになります。

Web Crypto APIでハッシュ化を行いたいページではSSL対応を行いましょう。

・対応ブラウザ

上記のコードはPromiseが使えないIE11は非対応としています。

また、参考にしたMDNサイトに記載のコードではasync/awaitを利用していますが、async/awaitを含む記述がある場合IE11ではスクリプト自体が構文エラーになってしまう点を鑑みて、Promiseを利用した書き方を採用しました。

● さいごに


Web Crypto APIを利用することで、標準ライブラリのみでSHA256でのハッシュ化を行うことができました。

JavaScriptのAPIはブラウザの対応状況によって使うかどうか悩むところですが、使えるものは積極的に利用を検討していきたいですね。

弊社では事業会社様のデジタルマーケティング活動の支援を行っています。

また、自社に専門人材がいない、リソースが足りない等の課題をお持ちの方に、エンジニア領域の支援サービス(Data Engineer Hub)をご提供しています。

お困りごとがございましたら、是非お気軽にご相談ください。

》エンジニア領域支援サービスの詳細はこちら

Data Engineer Hubサービス 資料イメージ

本件に関するお問い合わせは下記にて承ります。
株式会社DataCurrent
info@datacurrent.co.jp

人気のコラムランキング

PICK UP

CMP導入時の注意点

コラム

Treasure Data CDPを活用したOneID(統合ID)構築4 日付の落とし穴

コラム

今、CMPは導入するべきか?

コラム

Treasure Data CDPを活用したOneID(統合ID)構築3 姓名突合での落とし穴

コラム

TOPへ
戻る