【问题标题】:JSON Web Signature (Ninbus-JOSE-JWT)JSON 网络签名 (Ninbus-JOSE-JWT)
【发布时间】:2017-08-24 07:04:56
【问题描述】:

我想使用 JSON Web 签名 (JWS) 做一个项目,并且我想发送用于签名的证书的公钥,以便在收到此公钥后验证消息。我正在使用 Ninbus JOS JWT 库。我可以对 JSON 对象进行签名,并且可以看到公钥,但我无法正确验证它。 这是代码:

// Create RSA-signer with the private key
JWSSigner signer = new RSASSASigner(_signatureKey_);                                                    // PrivateKey

com.nimbusds.jose.util.Base64 b64 = new com.nimbusds.jose.util.Base64(_x509certificate.toString());     // X509Certificate
ArrayList<com.nimbusds.jose.util.Base64> certificados = new ArrayList<com.nimbusds.jose.util.Base64>();
certificados.add(b64);

RSAPublicKey _rsaPublicKey = (RSAPublicKey)_x509certificate.getPublicKey();  // Get the public key of the X509Certificate
RSAKey jwk = new com.nimbusds.jose.jwk.RSAKey.Builder( new Base64URL( _rsaPublicKey.getModulus().toString()),  new Base64URL( _rsaPublicKey.getPublicExponent().toString()))
    .x509CertChain(certificados)
    .build();

JWSHeader _jwsHeader = new JWSHeader.Builder(JWSAlgorithm.RS256).
    x509CertChain(certificados).
    jwk(jwk).
    build();

// Prepare JWS object with simple string as payload
JWSObject jwsObject = new JWSObject(_jwsHeader, new Payload(_jsonObject));

// Compute the RSA signature
jwsObject.sign(signer);

// Validation OK : This validation works
JWSVerifier verifier = new RSASSAVerifier(_rsaPublicKey);
boolean signatureValid = jwsObject.verify(verifier);        // ---> True, OK


// Now I want to validate the JWSObject getting the public key from the same JWSObject. This validation Fails
JWK _jwk = jwsObject.getHeader().getJWK();
RSAKey _rsakey = (RSAKey)_jwk; 
RSAPublicKey _rsaPublicKey2 = _rsakey.toRSAPublicKey();

JWSVerifier verifier2 = new RSASSAVerifier(_rsakey.toRSAPublicKey());
boolean verificado2 = jwsObject.verify(verifier2);      // False!

// Another option, this fails too
RSAKey __rsaKey2 = new com.nimbusds.jose.jwk.RSAKey.Builder( _rsakey.toRSAPublicKey() ).x509CertChain(_jwk.getX509CertChain()).build();
JWSVerifier verifier3 = new RSASSAVerifier(__rsaKey2);
boolean verificado3 = jwsObject.verify(verifier3);      // False!

_rsaPublicKey 是:“Sun RSA 公钥,2048 位”,但是当我从 JWK (_rsaPublicKey2) 获取它时,我得到“Sun RSA 公钥,3696 位”,我不知道为什么。

谢谢!

【问题讨论】:

    标签: json jwt json-web-token


    【解决方案1】:

    在接收方,您是否在信任密钥之前验证 X.509 证书颁发者、主题和链?在收件人确定它可以信任 JWS 中包含的证书之前,不得尝试签名验证。

    另一个注意事项:不要在 JWS 标头中包含公共 JWK。这应该只用于 ECDH 中的临时公钥(用于 JWE 的不同算法)。在 JWS 标头中传递证书链就足够了,但在使用其公钥之前,您必须验证它/确定证书是否可以信任。

    图书馆不会验证/确定证书是否可以信任您!

    如果第二次签名验证失败,那么用于签署 JWS 的密钥可能与 X.509 证书附带的密钥不同(正如不同报告长度所暗示的那样 - 2048 位与 3696 位) .

    【讨论】:

    • 谢谢,我认为问题在于从 RSAKey 到 RSAPublicKey 的转换。从 RSAKey 到 RSAPublicKey(使用 _rsakey.toRSAPublicKey())我得到不同的模数和指数。
    • JWK _jwk = jwsObject.getHeader().getJWK(); 'RSAKey _rsakey = (RSAKey)_jwk;' //// --> 模数和指数 ok 'RSAPublicKey _rsaPublicKey2 = _rsakey.toRSAPublicKey();' /// --> 不同
    • 我想我的问题可以总结一下:一旦我有了 JWSObject 对象并且我可以访问它的头和 x509CertChain(它是 com.nimbusds.jose.util.Base64 对象的列表),怎么能我得到了那个 X509CertChain 的公钥?我可以看到它在调试,但我无法正确验证签名。
    • 您可以使用 X509CertUtils.parse(base64.decode)) 从 DER+Base64 编码的 x5c 参数中获取证书。数组中的第一个证书是包含公共 RSA 密钥的证书。 static.javadoc.io/com.nimbusds/nimbus-jose-jwt/5.0/com/nimbusds/…
    • 谢谢,我在眼前看到了,我没看到,你的回复表明我有问题。我错误地添加了证书,我已将其更改为使用它:com.nimbusds.jose.util.Base64 b64 = new com.nimbusds.jose.util.Base64 (DatatypeConverter.printBase64Binary (_x509certificate.getEncoded ()) );
    猜你喜欢
    • 2016-02-27
    • 2016-06-10
    • 2016-09-14
    • 2018-06-01
    • 2017-06-06
    • 2020-09-04
    • 2021-11-06
    • 2018-10-17
    • 1970-01-01
    相关资源
    最近更新 更多