エラーメッセージ
IDX10720: Unable to create KeyedHashAlgorithm for algorithm 'HS256', the key size must be greater than: '256' bits, key has '128' bits.
別の表記
- System.ArgumentOutOfRangeException: IDX10720: Unable to create KeyedHashAlgorithm for algorithm 'HS256', the key size must be greater than: '256' bits, key has '128' bits. (Parameter 'keyBytes')
- IDX10653: The encryption algorithm 'HS256' requires a key size of at least '128' bits.
アルゴリズムとビット数は設定に応じて変わります。「must be greater than」とありますが、要求されるサイズちょうどの鍵は受け入れられます。複数のバージョンで確認したところ、6.8.0 以前は 128 ビットの HMAC 鍵を受け入れていましたが、それより後の 6.x(6.36.0)と 7.x/8.x は IDX10720 で拒否します(6.x では「UnsafeRelaxHmacKeySizeValidation」へのリンクが追加されます)。128 ビット未満の鍵は、それより前の段階で IDX10653「The encryption algorithm 'HS256' requires a key size of at least '128' bits」として失敗します。
Microsoft.IdentityModel.Tokens (.NET) — ArgumentOutOfRangeException from SymmetricSignatureProvider
このエラーの意味
IdentityModel は、アルゴリズムのハッシュ出力より短い HMAC 鍵の使用を拒否します。RFC 7518 §3.2 の要件どおり、HS256 には 256 ビット(32 バイト)以上、HS384 には 384 ビット以上、HS512 には 512 ビット以上が必要です。メッセージに示された鍵は 128 ビット、つまり 16 バイトで、`appsettings.json` に手で入力したシークレットによくある長さです。短い HMAC シークレットは、トークンがひとつあればオフラインで総当たりできるため、API が受け入れるトークンを誰でも発行できるようになってしまいます。
発生する理由
設定内の短いシークレット
よくあるチュートリアルでは `MySecretKey12345` や `supersecret` のような値が使われています。これらの UTF-8 のバイト数は 32 を大きく下回ります。
Microsoft.IdentityModel を初期の 6.x より新しいバージョンにアップグレードした
よくある少なくとも 6.8.0 までのリリースは 128 ビットの HMAC 鍵で署名していましたが、現在の 6.x、7.x、8.x は RFC の最小値を強制します。そのため、アップグレード(多くの場合 ASP.NET Core のアップグレードに伴って行われます)によって、短いシークレットを使うアプリケーションが動かなくなります。
HS256 向けのサイズの鍵で HS512 を使っている
ときどき32 バイトの鍵は HS256 には十分ですが、64 バイトが必要な HS512 には足りません。
修正方法
- 1.
適切なサイズのランダムな鍵を生成する
暗号論的に安全な乱数値を使い、ユーザーシークレットやシークレット保管庫に保存してください。ソース管理にコミットしてはいけません。
bash # 64 random bytes, base64: valid for HS256, HS384 and HS512 openssl rand -base64 64 | tr -d '\n' dotnet user-secrets set "Jwt:KeyBase64" "<the value above>" # development; use a vault in production - 2.
バイト列にデコードする
デコードしたバイト列から鍵を作成してください。そうすればエントロピーがすべて活用され、どのサービスでも同じ鍵が導出されます。
csharp var keyBytes = Convert.FromBase64String(builder.Configuration["Jwt:KeyBase64"]!); var signingKey = new SymmetricSecurityKey(keyBytes); // 64 bytes