JSON Web Signature (JWS) with RSA

This is an example how to create and verify a JSON Web Signature (JWS) based on RSA public / private key cryptography (RFC 3447). The payload is a simple string but can also be a JSON string or BASE64URL encoded data.

The minimum recommended RSA key size is 2048 bits.

The Nimbus JOSE+JWT supports all standard RSA digital signature algorithms:

  • RS256 - RSA PKCS#1 signature with SHA-256
  • RS384 - RSA PKCS#1 signature with SHA-384
  • RS512 - RSA PKCS#1 signature with SHA-512
  • PS256 - RSA PSS signature with SHA-256
  • PS384 - RSA PSS signature with SHA-384
  • PS512 - RSA PSS signature with SHA-512

The PKCS#1 type of RSA signatures is the most widely used and supported.

The example uses the key ID ("kid") parameter of the JWS header to indicate the signing key and simplify key roll-over. The exact method by which the recipient establishes the public RSA key candidate(s) to check the signature must be specified by the application's security protocol.

Example code:

import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.*;
import com.nimbusds.jose.jwk.*;
import com.nimbusds.jose.jwk.gen.*;


// RSA signatures require a public and private RSA key pair,
// the public key must be made known to the JWS recipient to
// allow the signatures to be verified
RSAKey rsaJWK = new RSAKeyGenerator(2048)
    .keyID("123")
    .generate();
RSAKey rsaPublicJWK = rsaJWK.toPublicJWK();

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

// Prepare JWS object with simple string as payload
JWSObject jwsObject = new JWSObject(
    new JWSHeader.Builder(JWSAlgorithm.RS256).keyID(rsaJWK.getKeyID()).build(),
    new Payload("In RSA we trust!"));

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

// To serialize to compact form, produces something like
// eyJhbGciOiJSUzI1NiJ9.SW4gUlNBIHdlIHRydXN0IQ.IRMQENi4nJyp4er2L
// mZq3ivwoAjqa1uUkSBKFIX7ATndFF5ivnt-m8uApHO4kfIFOrW7w2Ezmlg3Qd
// maXlS9DhN0nUk_hGI3amEjkKd0BWYCB8vfUbUv0XGjQip78AI4z1PrFRNidm7
// -jPDm5Iq0SZnjKjCNS5Q15fokXZc8u0A
String s = jwsObject.serialize();

// To parse the JWS and verify it, e.g. on client-side
jwsObject = JWSObject.parse(s);

JWSVerifier verifier = new RSASSAVerifier(rsaPublicJWK);

assertTrue(jwsObject.verify(verifier));

assertEquals("In RSA we trust!", jwsObject.getPayload().toString());