JSON Web Signature (JWS) とは?
JSON Web Signature (JWS) は、JSON 形式のデータを署名および検証するための標準的な方法を定義します。 OpenID Connect (OIDC) などのモダンなアプリケーションやオープンスタンダードで、送信されたデータの完全性と信頼性を確保するために広く使用されています。
JWS は特に JSON Web トークン (JWT) と連携する場合に便利です。例えば、 ID トークン (ID token) または アクセストークン (Access token) は JWS を使用して署名され、受取側はネットワーク要求を送ることなくその信頼性を検証できます。
JWS はどのように機能するのか?
JWS は暗号アルゴリズムを使用してデータに署名し、署名を生成します。JWS には主に JWS ヘッダーと JWS シリアライズの2つの概念があります。
JWS ヘッダー
JWS には、署名アルゴリズムとキー管理に関する重要なメタデータが含まれるヘッダーがあります。JWS ヘッダーの一般的な属性には次のようなものがあります:
alg
(Algorithm): データ署名に使用された暗号アルゴリズム。typ
(Type): JWT などのトークンの種類。kid
(Key ID): データ署名に使用されたキーのユニークな識別子。jku
(JWK Set URL): JSON Web Key Set (JWKS) が配置されている URL。
JWS ヘッダーの属性の詳細については、 JOSE ヘッダー を参照してください。
JWS シリアライズ
JWS にはコンパクト形式と JSON 形式の2つのシリアライズ形式があります。それぞれの形式は署名されたデータを表現する独自の方法を持っています。
コンパクトシリアライズ
コンパクトシリアライズでは、JWS はドット (.
) で区切られた 3 つの Base64URL エンコードされた部分の文字列として表現されます。3 つの部分は以下の通りです:
{{header}}.{{payload}}.{{signature}}
各部分の目的は次のとおりです:
header
: Base64URL エンコードされた形式の署名アルゴリズムとキー管理に関するメタデータ。payload
: Base64URL エンコードされた形式の署名されるデータ。signature
: ヘッダーとペイロードの暗号署名。
[!Note] コンパクトシリアライズには無保護ヘッダーは含まれません。
例えば、JWS は次のように見えるかもしれません:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIn0.Xv9da66g3y4nxs_0hlR9CBkOG9GkxfPmq1_7u4tNeXE
Base64URL エンコードされた部分をデコードすると、JWS は次の要素で構成されています:
- ヘッダー:
{"alg":"HS256","typ":"JWT"}
- ペイロード:
{"sub":"1234567890","name":"Alice"}
- 署名:
Xv9da66g3y4nxs_0hlR9CBkOG9GkxfPmq1_7u4tNeXE
ヘッダーは JWS が HMAC-SHA256 アルゴリズム (HS256
) を使用して署名されており、トークンの種類は JWT (typ: "JWT"
) であることを示しています。ペイロードには、被験者 (sub
) と名前 (name
) などの基本的なユーザー情報が含まれています。
署名は以下の方法で計算されます:
Hash(
Base64URLEncode(header) || '.' || Base64URLEncode(payload),
secret
)
JWS ヘッダーによると、Hash
関数に HMAC-SHA256 アルゴリズムが使用され、secret
はこの場合、共有された秘密鍵 top-secret
です。
JWT と JWS の連携の詳細な例については、 署名キー (Signing key) 記事を参照してください。
JSON シリアライズ
JSON シリアライズは、JWS をより構造化された形で表現する方法を提供します。JWS は次のプロパティを持つ JSON オブジェクトとして表現されます:
{
"payload": "{{payload}}",
"signatures": [
{
"protected": "{{protected-header}}",
"header": "{{header}}",
"signature": "{{signature}}"
}
]
}
-
payload
: Base64URL エンコードされたペイロード。署名されるデータ。 -
signatures
: 保護されたヘッダー、ヘッダー、署名を含む署名オブジェクトの配列。各署名オブジェクトには以下が含まれる場合があります:
protected
: Base64URL エンコードされた保護されたヘッダー(コンパクトシリアライズのheader
)。header
: JSON 形式の無保護ヘッダー。ヘッダーは署名に含まれません。signature
: ヘッダーとペイロードの暗号署名(コンパクトシリアライズのsignature
)。
例えば、JSON シリアライズ形式の JWS は次のように見えるかもしれません:
{
"payload": "eyJzdWIiOiIx...bGciOiJIUzI1NiJ9",
"signatures": [
{
"protected": "eyJhbGci...InR5cCI6IkpXVCJ9",
"header": {
"kid": "2010-12-29"
},
"signature": "Xv9da66g3y4nxs...R9CBkOG9GkxfPmq1_7u4tNeXE"
},
{
"protected": "eyJhbGci...InR5cCI6IkpXVCJ9",
"header": {
"kid": "2010-12-30"
},
"signature": "Yv9da66g3y4nxs...R9CBkOG9GkxfPmq1_7u4tNeXE"
}
]
}
上記の例では、同じペイロードに対して2つの署名(signatures
配列)が存在します。各署名オブジェクトには保護されたヘッダー、ヘッダー、および署名が含まれています。