Reputation: 71
I am trying to generate a JWS (using nimbusds library) to be used as a request payload for a POST API. I have a private key and set of PEM certificates to generate this JWS, I am trying using following steps :
For generating JWS, I am using PS256 algorithm, but getting the error Unsupported JWS algorithm PS256, must be RS256, RS384, RS512, PS256, PS384 or PS512 .
Please find the code piece :
/* generating JWK from my certificate starts */
RSAKey jwk1 = null;
try {
jwk1 = (RSAKey) JWK.parseFromPEMEncodedX509Cert(myCertificateString);
Map<String, Object> jwkMap = jwk1.toJSONObject();
jwkMap.put("use", "enc");
jwkMap.put("alg", "RSA-OAEP-256");
jwk1 = (RSAKey) JWK.parse(jwkMap);
} catch (JOSEException ex) {
log.error("Exception while creating JWK from myCertificate : {}", ex.getMessage());
}
log.info("JWK from my certi : {}", jwk1);
/* generating JWK from my certificate ends */
/* generating JWK with RSA key pair starts */
byte[] decoded = Base64.decodeBase64(privateKeyString);
PrivateKey privateKey =
KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
KeyFactory kf = KeyFactory.getInstance("RSA");
RSAPrivateKeySpec privKeySpec = kf.getKeySpec(privateKey, RSAPrivateKeySpec.class);
RSAPublicKeySpec pubKeySpec =
new RSAPublicKeySpec(privKeySpec.getModulus(), privKeySpec.getPrivateExponent());
RSAPublicKey pubKey = (RSAPublicKey) kf.generatePublic(pubKeySpec);
RSAKey jwkp = new RSAKey.Builder(pubKey).privateKey(privateKey).build();
log.info("jwkp from private key :: {}", jwkp);
/* generating JWK with RSA key pair ends */
/* generating JWK from tp certificate starts */
RSAKey jwk = null;
try {
jwk = (RSAKey) JWK.parseFromPEMEncodedX509Cert(tpCertificateString);
Map<String, Object> jwkMap = jwk.toJSONObject();
jwkMap.put("use", "enc");
jwkMap.put("alg", "RSA-OAEP-256");
jwk = (RSAKey) JWK.parse(jwkMap);
} catch (JOSEException ex) {
log.error("Exception while creating JWK from tpCertificate : {}", ex.getMessage());
}
log.info("jwk from tp certi ", jwk);
/* generating JWK from tp certificate ends */
/* generating serialized JWE with payload and JWK generated from tp certificate starts */
Map<String, Object> customParams = new HashMap<String, Object>();
customParams.put("clientId", clientId);
customParams.put("x5t#256", jwk.getX509CertSHA256Thumbprint());
JWEHeader jweHeader = new JWEHeader(JWEAlgorithm.RSA_OAEP_256, EncryptionMethod.A128GCM);
Map<String, Object> jweHeaderMap = jweHeader.toJSONObject();
jweHeaderMap.put("clientId", clientId);
jweHeaderMap.put("x5t#256", jwk.getX509CertSHA256Thumbprint());
jweHeader = JWEHeader.parse(jweHeaderMap);
JWEObject object = new JWEObject(jweHeader, new Payload(request));
JWEEncrypter encrypter = new RSAEncrypter(jwk);
object.encrypt(encrypter);
String jweString = object.serialize();
log.info("JWE :: {}", jweString);
/* generating serialized JWE with payload and JWK generated from tp certificate ends */
/*
* generating serialized JWS with JWE as payload, JWK generated from my certificate and
* using JWK generated with RSA key pair for signing starts
*/
JWSSigner signer = new RSASSASigner(privateKey);
JWSHeader jwsHeader = new JWSHeader(JWSAlgorithm.PS256);
Map<String, Object> jwsHeaderMap = jwsHeader.toJSONObject();
jwsHeaderMap.put("clientId", clientId);
jwsHeaderMap.put("x5t#256", jwk1.getX509CertSHA256Thumbprint());
jwsHeader = JWSHeader.parse(jwsHeaderMap);
JWSObject jwsTest = new JWSObject(jwsHeader, new Payload(jweString));
jwsTest.sign(signer);
log.info("JWS is :: {}", jwsTest.serialize());
/*
* generating serialized JWS with JWE as payload, JWK generated from my certificate and
* using JWK generated with RSA key pair for signing starts
*/
return jwsTest.serialize();
}
PS : I am using Java 8 and algorithm used for generating JWKs is RSA.
Upvotes: 1
Views: 3382
Reputation: 71
After spending considerable time on this issue, I finally reached a solution.
From various posts/articles, I got an idea that this can be due to Java version not supporting PS256 algorithm.
In nimbusds jose+jwt library documentation, it is mentioned that PS256 is being supported Java8 onwards, but if the case arises that Java runtime doesn't support a JOSE algorithm, we need to install JCA provider explicitly (BouncyCastle being preferred choice).
I added BouncyCastle as JCA in my class:
Security.addProvider(BouncyCastleProviderSingleton.getInstance());
Now it is working fine.
Please update in comments, if someone finds an alternate solution as well.
Upvotes: 2