2017-08-24 176 views
0

我想用JSON Web簽名(JWS)做一個項目,並且我想發送用於簽名的證書的公鑰,以便一旦收到消息就可以驗證消息用這個公鑰。我正在使用Ninbus JOS JWT庫。我可以簽署JSON對象,我可以看到公鑰,但我無法正確驗證它。 這是代碼:JSON Web簽名(Ninbus-JOSE-JWT)

// 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是:「孫RSA公共密鑰,2048位」,但是當我從JWK(_rsaPublicKey2)得到它,我得到「孫RSA公共密鑰,3696位」我不知道爲什麼。

謝謝!

回答

1

在接受方,您是否在信任密鑰之前驗證X.509證書頒發者,主體和鏈?在收件人確信它可以信任JWS中包含的證書之前,不得嘗試簽名驗證。

另一個注意事項:請勿在JWS標頭中包含公共JWK。這應該只用於ECDH中的短暫公鑰(用於JWE的另一個alg)。在JWS頭中傳遞證書鏈就足夠了,但是在使用公鑰之前,您必須驗證它/找出證書是否可信。

圖書館不會驗證/發現證書是否可以爲您信任!

如果第二次簽名驗證失敗,那麼用於簽名JWS的密鑰和X.509證書附帶的密鑰可能不一樣(正如不同的報告長度所暗示的那樣 - 2048位與3696位)。

+0

謝謝,我認爲問題在於從RSAKey到RSAPublicKey的轉換。從RSAKey到RSAPublicKey(帶有_rsakey.toRSAPublicKey()),我得到了不同的模數和指數。 – jandres

+0

JWK _jwk = jwsObject.getHeader()。getJWK(); 'RSAKey _rsakey =(RSAKey)_jwk;' //// - >模數和指數ok 'RSAPublicKey _rsaPublicKey2 = _rsakey.toRSAPublicKey();' /// - > – jandres

+0

我認爲我的問題可以概括:一旦我有了JWSObject對象,並且我可以訪問它的頭文件和x509CertChain(它是一個com.nimbusds.jose.util.Base64對象列表),那麼怎麼能我得到了X509CertChain的公鑰?我可以看到它的調試,但我無法正確驗證簽名。 – jandres