hwtr-js
HWTプロトコル githubのJavaScriptリファレンス実装。 このライブラリを使ったデモはhwt-demo githubを参照。
Token format: hwt.signature.key-id.expires-unix-seconds.format.payload
インストール
// Deno / JSR
import Hwtr from 'jsr:@hwt/hwtr-js'
// Node / Bun via JSR
// npx jsr add @hwt/hwtr-js
// ローカル
import Hwtr from './hwtr.js'
クイックスタート
// 鍵を一度生成し、結果を安全に保管する
const keyConfig = await Hwtr.generateKeys({ type: 'Ed25519' })
// インスタンスを生成
const hwtr = await Hwtr.factory({}, keyConfig)
// 署名
const token = await hwtr.create({ sub: 'user:123', role: 'editor' })
// 検証
const result = await hwtr.verify(token)
if (result.ok) {
console.log(result.data) // { sub: 'user:123', role: 'editor' }
}
API
Hwtr.factory(options, keyConfig) → Promise<Hwtr>
推奨コンストラクター。new Hwtr(options).importKeys(keyConfig)と等価。
const hwtr = await Hwtr.factory({ expiresInSeconds: 3600 }, keyConfig)
コンストラクターオプション — すべてオプション:
| オプション | デフォルト | 説明 |
|---|---|---|
expiresInSeconds |
60 |
デフォルトトークンライフタイム |
maxTokenLifetimeSeconds |
86400 |
ハード上限;0 = 無制限 |
leewaySeconds |
1 |
クロックスキュー許容値。specは5分(300秒)を超えないことを推奨;最大値の強制はない。 |
maxTokenSizeBytes |
4096 |
範囲:512〜16384 |
format |
'j' |
payloadのcodec |
signatureSize |
0 |
HMAC署名をN文字に切り詰める;0 = フル長;非対称鍵では無視される |
throwOnInvalid |
false |
ok: falseを返す代わりにthrowする |
throwOnExpired |
false |
ok: falseを返す代わりにthrowする |
throwOnGenerate |
true |
署名失敗時にthrowする |
throwOnEncoding |
true |
codec失敗時にthrowする |
鍵の生成
// 完全な鍵セット — factoryまたはimportKeysに直接渡す
const keyConfig = await Hwtr.generateKeys({
count: 2, // 鍵の数(デフォルト:1)
current: 'primary', // 署名鍵のid
type: 'Ed25519', // アルゴリズム(デフォルト:'HMAC')
})
// → { current, type, keys: [{ id, created, privateKey, publicKey }] }
// 単一のHMAC鍵
const key = Hwtr.generateKey({ id: 'main' })
// → { id, secret, created }
// 単一の非対称鍵ペア
const pair = await Hwtr.generateKeyPair({ id: 'k1', type: 'ECDSA-P256' })
// → { id, created, publicKey, privateKey } (base64url SPKI/PKCS8)
サポートされているアルゴリズム:'HMAC'、'Ed25519'、'ECDSA-P256'、'ECDSA-P384'、'ECDSA-P521'
HMACは対称鍵 — 単一サービス専用。クロスサービス検証には非対称鍵タイプを使用すること。P-521のサポートは環境によって異なる;使用前にテストすること。
hwtr.importKeys(keyConfig) → Promise<Hwtr>
署名鍵および/または検証鍵をインポートする。factory()が自動的に呼び出す。
// keyConfigの構造
{
current: 'primary', // 新しいトークンの署名に使用する鍵のid
type: 'Ed25519',
keys: [
{ id: 'primary', created: '...', privateKey: 'BASE64URL', publicKey: 'BASE64URL' }
// HMAC: { id, created, secret }
],
publicKeys: { // オプション:他サービスからの検証専用鍵
'partner-key': 'BASE64URL'
}
}
ローテーションのために複数の鍵をサポートする。idがトークンのkidと一致する任意の鍵で検証できる。id === currentの鍵のみが新しいトークンに署名する。
hwtr.create(payload, hiddenData?) → Promise<string>
デフォルトの有効期限でトークンを生成する。
const token = await hwtr.create({ sub: 'user:123' })
// hiddenDataは署名されるが埋め込まれない — verifierは同一の値を提供する必要がある
const token = await hwtr.create({ sub: 'user:123' }, { ip: '203.0.113.1' })
トークンがmaxTokenSizeBytesを超える場合、''を返す(throwOnInvalidの場合はthrow)。
hwtr.createWith(expiresInSeconds, payload, hiddenData?) → Promise<string>
指定したライフタイムでトークンを生成する。maxTokenLifetimeSecondsを超える場合はthrowする。
const token = await hwtr.createWith(300, { sub: 'user:123', oneTime: true })
hwtr.verify(token, hiddenData?) → Promise<VerifyResult>
署名と有効期限を検証する。デフォルトではthrowしない。
const result = await hwtr.verify(token)
// result.ok — 有効な場合はtrue
// result.data — デコードされたpayload
// result.expired — 有効期限切れの場合はtrue
// result.expires — unix秒
// result.error — 失敗時に存在
result.errorの値:'hwt invalid'、'hwt invalid format'、'hwt expired'、'hwt unknown encoding "x"'、'hwt unknown key'、'hwt invalid signature'、'hwt data decoding failed'
hwtr.decode(token) → Promise<{ data, expires, error? }>
署名や有効期限を検証せずにpayloadをデコードする。検査専用。
クロスサービス検証
検証のみ(署名なし)のサービスは、秘密keysなしでpublicKeysを渡す:
const verifyOnly = await Hwtr.factory({}, {
type: 'Ed25519',
keys: [],
publicKeys: { 'auth-key': 'BASE64URL' }
})
鍵配布のための便利メソッド:
const pub = await hwtr.exportPublicKey('primary') // base64url SPKI文字列
const all = await hwtr.getPublicKeys() // { id: base64url, ... }
await hwtr.addPublicKey({ id, publicKeyBase64, type }) // ランタイムに外部鍵を追加
Codec
'j'(JSON)が唯一の組み込みcodecである。カスタムcodecをプロセスごとに一度登録する:
Hwtr.registerFormat('name', {
encode(data) { /* → Uint8Array */ },
decode(buffer) { /* → value */ }
})
Hwtr.formats // → ['j', 'name', ...]
フォーマット名:/^[a-zA-Z][a-zA-Z0-9]{1,19}$/。登録済みの名前はthrowする。
拡張JSONcodec(jx)はDate、BigInt、Map、Set、typed arrayをサポートし、ソースリポジトリのhwtr.formats.jsで利用可能 — 公開パッケージには含まれていない。
ユーティリティ
Hwtr.timingSafeEqual(a, b) // 定数時間比較;文字列またはUint8Array
Hwtr.bufferToBase64Url(buffer) // ArrayBuffer | Uint8Array → base64url文字列
Hwtr.base64urlToUint8Array(str) // base64url → Uint8Array;不正な入力の場合は空配列
Hwtr.textToBase64Url(text) // UTF-8文字列 → base64url
Hwtr.base64urlToText(str) // base64url → UTF-8文字列
Hwtr.isHwt(str) // strが有効なHWT署名セグメントを含む場合にtrue
Hwtr.ALGORITHMS // サポートされているアルゴリズムマップ
Hwtr.version // バージョン
すべてhwtr.jsからnamed exportとしてもエクスポートされる。
関連
ライセンス
Copyright 2026 Jim Montgomery
SPDX-License-Identifier: Apache-2.0
Apache License 2.0。LICENSEを参照。