web crypto apiでjwkから公開鍵を取得する
tags: javascript
最近oauth, oidcを勉強していて、jwkから公開鍵を生成する方法を調べた所、nodejsのcryptoモジュールを使う方法は紹介されていてweb crypto apiを使うパターンが気になって調べた。
web crypto api とは
Web Crypto API は、暗号化を使用してシステムを構築するためにスクリプトが暗号化プリミティブを使用することを可能にするインターフェイスです。
https://developer.mozilla.org/ja/docs/Web/API/Web_Crypto_API
テスト用の公開鍵を用意してjwkを生成する
公開鍵の生成にはopenssl、jwkの生成にはnodejsのpem-jwkライブラリを利用する
# 鍵の生成
openssl genrsa 2048 > private.pem
openssl rsa -pubout -in private.pem -out public.pem
# jwkの生成
pem-jwk public.pem
pem-jwk
コマンドを実行して表示されるjwkをコピーしておく
jwkから公開鍵を取得する
本題のweb crypto apiでjwkから公開鍵を取得する。最終的には元のpublic.pem
と同じになれば良い
// 表示されたjwkの内容を貼り付ける
const jwk = {
kty: 'RSA',
n: 'rvrWRLsp6Z~', // 省略
e: 'AQAB',
}
const arrayBufferToBase64Multiline = (arrayBuffer) => {
const bytes = new Uint8Array(arrayBuffer)
let binary = ''
for (let i = 0; i < bytes.length; i++) {
binary += String.fromCharCode(bytes[i])
}
// btoaでBase64エンコード → 見やすいように64文字ごとに改行
return btoa(binary).replace(/(.{64})(?!$)/g, '$1\n')
}
const spkiToPem = (spkiBuffer) => {
const base64 = arrayBufferToBase64Multiline(spkiBuffer)
return '-----BEGIN PUBLIC KEY-----\n' + base64 + '\n-----END PUBLIC KEY-----\n'
}
const pubKey = await crypto.subtle.importKey(
'jwk',
jwk,
{ name: 'RSASSA-PKCS1-v1_5', hash: { name: 'SHA-256' } },
true,
['verify'],
)
const spki = await crypto.subtle.exportKey('spki', pubKey)
const pemPublicKey = spkiToPem(spki)
console.log(pemPublicKey)
実行
node --experimental-default-type=module index.js
これでcatコマンドなので確認するとpublic.pem
と同じ内容が表示されるはず
まとめ
とりあえずjwkから公開鍵を取得することはできた。次はこの公開鍵を使ってjwtの検証をしてみようと思うんだけど、SubtleCrypto - Web API | MDN のドキュメントを見る限りは digest() メソッド を使えば検証できそう