Edited at

便利ページ:Javascriptで暗号化など追加

便利ページ:Javascriptでちょっとした便利な機能を作ってみた のシリーズものです。

今回は、WebAuthnを使ったFIDOサーバを立ててみた の実装をしていたところ、何かと便利になりそうなことがありそうだったので、追加してみようと思いました。


  • バイナリのBase64エンコード

  • Base64URLエンコード

  • 文字列のバイト配列変換

  • HMAC(SHA256)生成、AES暗号化

毎度の通り、デモページとGitHubです。

GitHub

 https://github.com/poruruba/utilities

デモページ

 https://poruruba.github.io/utilities/


バイナリのBase64エンコード

画像などのバイナリデータをJSON等で送る場合によく使われているようです。確かに、16進数文字列にするより、サイズ的に効率的ですね。

Webにたくさん転がっていましたので、盲目的に採用させていただきました。

function bufferToBase64(buf) {

if( buf instanceof ArrayBuffer )
buf = new Uint8Array(buf);
if( buf instanceof Uint8Array )
buf = Array.from(buf);

var binstr = buf.map(b => String.fromCharCode(b)).join("");
return btoa(binstr);
}

function base64ToBuffer(b64) {
var binstr = atob(b64);
var buf = new Uint8Array(binstr.length);
Array.from(binstr).forEach((ch, i) => buf[i] = ch.charCodeAt(0));
return buf;
}


Base64URLエンコード

BASE64URLとは、Webにおいて主にバイナリデータの送受で使われているようで、Base64エンコードに対して、Webで扱いやすいように、「+」を「-」に、「/」を「_」に置き換え、パディングも省略されたもののようです。

以下のモジュールを使わせていただきました。

Base64URL-ArrayBuffer

 https://github.com/herrjemand/Base64URL-ArrayBuffer


文字列のバイト配列変換

これも、Web上にたくさん情報がありますが、使いたい時にさっと使えるように、便利ツールに追加しました。

var encoder = new TextEncoder('utf-8');

output = encoder.encode('文字列');
var decoder = new TextDecoder('utf-8');
output = decoder.decode(バイト配列);


HMAC(SHA256)生成、AES暗号化

暗号演算には、以下のモジュールを使わせていただきました。

crypto-js

 https://github.com/brix/crypto-js

以下に、使い方の説明ページがあったので、すんなり実装できました。

 https://cryptojs.gitbook.io/docs/

具体的には、ソースコードを見ていただくとして、なぜ便利ツールに追加したかというと、AWS Cognitoのカスタム認証フローにSECRET_HASHなる仕様で必要だったためです。実装したものの、あまり使う機会がなく、忘れてしまいそうでした。

今回とはちょっと横道にそれますが、こんな感じだそうです。

function makeSecretHash(username, client_id, client_secret){

var hash = CryptoJS.HmacSHA256(username + client_id, client_secret);
var result = wordarray_to_uint8array(hash);
return bufferToBase64(result);
}

var secretHash = makeSecretHash(this.username, UserPoolClientId, UserPoolClientSecret);
var params = {
AuthFlow: 'CUSTOM_AUTH',
ClientId: UserPoolClientId,
AuthParameters: {
'USERNAME' : this.username,
'SECRET_HASH' : secretHash
}
};
do_post_aws(CognitoUrl, params, 'AWSCognitoIdentityProviderService.InitiateAuth' )

以上