JSON Web签名(Ninbus JOSE JWT)

JSON Web签名(Ninbus JOSE JWT),json,jwt,json-web-token,Json,Jwt,Json Web Token,我想用JSON Web签名(JWS)做一个项目,并且我想发送用于签名的证书的公钥,以便在收到该公钥后可以验证消息。我正在使用Ninbus JOS JWT库。我可以对JSON对象进行签名,并且可以看到公钥,但是我无法正确验证它。 代码如下: // Create RSA-signer with the private key JWSSigner signer = new RSASSASigner(_signatureKey_);

我想用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!
//使用私钥创建RSA签名者
JWSSigner signer=新的rsassassigner(_signatureKey);//私钥
com.nimbusds.jose.util.Base64 b64=新的com.nimbusds.jose.util.Base64(_x509certificate.toString());//X509证书
ArrayList certificados=新的ArrayList();
证书添加(b64);
RSAPublicKey _RSAPublicKey=(RSAPublicKey)_x509certificate.getPublicKey();//获取X509证书的公钥
RSAKey jwk=new com.nimbusds.jose.jwk.RSAKey.Builder(new Base64URL(_rsaPublicKey.getmodule().toString()),new Base64URL(_rsaPublicKey.getPublicExponent().toString())
.x509CertChain(certificados)
.build();
JWSHeader _JWSHeader=新的JWSHeader.Builder(JWSAlgorithm.RS256)。
x509CertChain(certificados)。
jwk(jwk)。
build();
//使用简单字符串作为有效负载准备JWS对象
JWSObject JWSObject=新JWSObject(_jwsHeader,新有效负载(_jsonObject));
//计算RSA签名
jwsObject.sign(signer);
//验证确定:此验证有效
JWSVerifier verifier=新的RSASSAVerifier(_rsaPublicKey);
布尔signatureValid=jwsObject.verify(验证器);//-->是的,好的
//现在我想验证从同一JWSObject获取公钥的JWSObject。此验证失败

JWK _JWK=jwsObject.getHeader().getJWK(); RSAKey _RSAKey=(RSAKey)_jwk; RSAPublicKey _rsaPublicKey2=_rsakey.toRSAPublicKey(); JWSVerifier verifier2=新的RSASSAVerifier(_rsakey.toRSAPublicKey()); 布尔值verificado2=jwsObject.verify(verifier2);//假的! //另一种选择也是失败的 RSAKey uursakey2=new com.nimbusds.jose.jwk.RSAKey.Builder(RSAKey.torsaPublicey()).x509CertChain(jwk.getX509CertChain()).build(); JWSVerifier verifier3=新的RSASSAVerifier(u rsaKey2); 布尔值verificado3=jwsObject.verify(verifier3);//假的!
公钥是:“Sun RSA公钥,2048位”,但当我从JWK(_RSA公钥2)获得它时,我得到了“Sun RSA公钥,3696位”,我不知道为什么


谢谢

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

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

库将不会验证/确定您是否可以信任该证书


如果第二次签名验证失败,那么用于签名JWS的密钥可能与X.509证书附带的密钥不一样(根据不同的报告长度——2048位与3696位)。谢谢,我认为问题在于从RSAKey到RSACublicKey的转换。从RSAKey到RSAPublicKey(使用_RSAKey.toRSAPublicKey())我得到不同的模数和指数.JWK _JWK=jwsObject.getHeader().getJWK();'RSAKey=(RSAKey)\u jwk;'//-->模数和指数正常'RSAPublicKey rsaPublicKey2=\u rsakey.toRSAPublicKey();'//-->不同之处我认为我的问题可以归结为:一旦我有了JWSObject对象,并且我可以访问它的头和x509CertChain(它是com.nimbusds.jose.util.Base64对象的列表),我如何获得x509CertChain的公钥?我可以看到它正在调试,但无法正确验证签名。可以使用X509CertUtils.parse(base64.decode))从DER+base64编码的x5c参数获取证书。阵列中的第一个证书是包含公钥RSA的证书。谢谢你,我把它放在眼前,但我没有看到,你的回答告诉了我这个问题。我添加了错误的证书,我已将其更改为使用:com.nimbusds.jose.util.Base64 b64=new com.nimbusds.jose.util.Base64(DatatypeConverter.printBase64Binary(x509certificate.getEncoded());