Prakhar
Prakhar

Reputation: 71

Unsupported JWS algorithm PS256, must be RS256, RS384, RS512, PS256, PS384 or PS512

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 :

  1. generated JWKs using RSA key pair and certificates
  2. generated JWE with payload and JWK generated from one of the certificates
  3. generated JWS with serialized JWE object as payload and used JWK generated from key pair for signing the JWS

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

Answers (1)

Prakhar
Prakhar

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

Related Questions