为啥我的 Jose4j JSON Web Key 会导致这个 InvalidKeyException?

Posted

技术标签:

【中文标题】为啥我的 Jose4j JSON Web Key 会导致这个 InvalidKeyException?【英文标题】:Why does my Jose4j JSON Web Key cause this InvalidKeyException?为什么我的 Jose4j JSON Web Key 会导致这个 InvalidKeyException? 【发布时间】:2017-10-01 03:29:31 【问题描述】:

我正在使用 Jose4j 在 Java 中执行 JSON Web Token 的加密。

我创建一个密钥作为 JSON 格式的字符串传递给 JsonWebKey.Factory.newJwk 方法,因此:

    String jwkJson = "\"kty\":\"oct\",\"k\":\"5uP3r53cR37k3yPW\"";

我将它传递给工厂并获得JsonWebKey (jwk) 回复。 然后将密钥(来自jwk.getKey() 方法)传递给JsonWebEncryption 的setKey() 方法。 我设置了AlgorithmHeaderValueEncryptionMethodHeaderParameter...

然后,当我调用jwe.getCompactSerialization() 时,它会抛出以下异常

    org.jose4j.lang.InvalidKeyException: 
    Invalid key for JWE A128KW, expected a 128 bit key but a 96 bit key was provided.

我传入了 16 个字节,那么为什么这会计算为 128 的 96 位??

【问题讨论】:

【参考方案1】:

在将密钥字符串添加到 JSON 对象 jwkJson 之前,您需要对其进行 base64 编码。

例如

    String pass = "5uP3r53cR37k3yPW";
    String jwkJson = "\"kty\":\"oct\",\"k\":\""+ Base64Url.encodeUtf8ByteRepresentation(pass) +"\"";

在 JsonWebKey 的工厂方法中,它从 JSON 对象中检索到 key (k) 值后,对其进行 base64 解码。这具有将位模式表示的字符数减少 3 的效果(如果您没有先对其进行编码)。

至于为什么会发生这种情况,我有点困惑。我假设如果您使用一个二进制字符串来描述一个使用 8 位表示(UTF-8,Java 中的本机字符集)的字符串,那么使用 6 位表示(base64)将该二进制字符串重新解释为字符, 会产生更长的字符串!

【讨论】:

【参考方案2】:

用于对称密钥 base64url 的“oct”JWK 密钥类型将密钥值编码为“k”参数的值(请参阅https://www.rfc-editor.org/rfc/rfc7518#section-6.4)。虽然“5uP3r53cR37k3yPW”是 16 个字符,但它使用 base64url 字母表并在作为 JWK 键值处理时解码为 12 个字节(96 位)的原始数据。 k 值需要更长一点才能表示 16 字节/128 位。例如,String jwkJson = "\"kty\":\"oct\",\"k\":\"5uP3r53cR37k3yPWj_____\""; 之类的东西是一个 128 位对称 JWK,它适用于您正在做的事情。但是,加密密钥确实应该使用安全的随机数生成而不是看起来像密码的东西来创建。 FWIW,JsonWebKey jwk = OctJwkGenerator.generateJwk(128); 可能是生成 128 位对称 JWK 对象的一种便捷方式。

【讨论】:

以上是关于为啥我的 Jose4j JSON Web Key 会导致这个 InvalidKeyException?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 XML 仍然用于 Web 服务响应,即使 JSON 更好? [关闭]

如何更改 chrome 打包的应用程序 ID 或者为啥我们需要 manifest.json 中的 key 字段?

使用 jose4j 验证具有分离负载的 JWS 失败

为啥要使用环境变量对 JSON Web 令牌 (JWT) 进行签名?

为啥我的 JSON 发布请求以十六进制值结束?

为啥我的应用程序无法从我的 API 读取 JSON?