Перейти к содержимому
ecdsa.com
JJWT (Java)Java

Сообщение об ошибке

The specified key byte array is 96 bits which is not secure enough for any JWT HMAC-SHA algorithm.

Также выводится как

  • io.jsonwebtoken.security.WeakKeyException: The specified key byte array is 96 bits which is not secure enough for any JWT HMAC-SHA algorithm.
  • io.jsonwebtoken.security.SignatureException: Unable to compute HS512 signature. Cause: The signing key's size is 256 bits which is not secure enough for the HS512 algorithm.
  • io.jsonwebtoken.security.WeakKeyException: The signing key's size is 256 bits which is not secure enough for the HS512 algorithm.

Число бит соответствует вашему ключу. `Keys.hmacShaKeyFor` сообщает «…not secure enough for any JWT HMAC-SHA algorithm». Если подписывать с явно заданным алгоритмом, для которого ключ слишком короткий, в сообщении будет назван этот алгоритм: JJWT 0.12+ оборачивает ошибку в «SignatureException: Unable to compute HS512 signature. Cause: The signing key's size is 256 bits…», а 0.11 выбрасывает её напрямую как `WeakKeyException`.

JJWT (Java) — io.jsonwebtoken.security.WeakKeyException from Keys.hmacShaKeyFor / signWith

Что это означает

JJWT отказывается создавать ключ HMAC, если в нём меньше бит, чем на выходе хеш-функции алгоритма: нужно не менее 256 бит (32 байта) для HS256, 384 для HS384 и 512 для HS512. В RFC 7518, § 3.2 это требование уровня MUST, потому что короткий общий секрет можно подобрать перебором офлайн по любому подписанному им токену. После этого кто угодно сможет выпускать действительные токены. Число в сообщении — размер переданных вами байтов.

Почему это происходит

Как исправить

  1. 1.

    Сгенерируйте случайный секрет нужного размера

    Используйте криптографически случайное значение (64 байта подходят для всех вариантов HMAC) и храните его в менеджере секретов в кодировке base64.

    bash
    # 64 random bytes, base64-encoded: enough for HS256, HS384 and HS512
    openssl rand -base64 64 | tr -d '\n'
  2. 2.

    Декодируйте сохранённый секрет в байты

    Создавайте ключ из декодированных байтов, а не из текста base64, чтобы все сервисы получали одинаковый ключ.

    java
    import io.jsonwebtoken.io.Decoders;
    import io.jsonwebtoken.security.Keys;
    
    javax.crypto.SecretKey key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(System.getenv("JWT_SECRET_B64")));
    String token = io.jsonwebtoken.Jwts.builder().subject("user-42").signWith(key).compact();

Связанные ошибки

Открыть всю базу ошибок подписей