OpenSSL key generation
How to generate keys in PEM format using the OpenSSL command line tools?
RSA keys
The JOSE standard recommends a minimum RSA key size of 2048 bits.
To generate a 2048-bit RSA private + public key pair for use in RSxxx and PSxxx signatures:
openssl genrsa 2048 -out rsa-2048bit-key-pair.pem
Elliptic Curve keys
To generate an EC key pair the curve designation must be specified. Note that JOSE ESxxx signatures require P-256, P-384 and P-521 curves (see their corresponding OpenSSL identifiers below).
Elliptic Curve private + public key pair for use with ES256 signatures:
openssl ecparam -genkey -name prime256v1 -noout -out ec256-key-pair.pem
Elliptic Curve private + public key pair for use with ES384 signatures:
openssl ecparam -genkey -name secp384r1 -noout -out ec384-key-pair.pem
Elliptic Curve private + public key pair for use with ES512 signatures:
openssl ecparam -genkey -name secp521r1 -noout -out ec512-key-pair.pem
PEM key parsing in Java
The BouncyCastle library provides a simple utility to parse PEM-encoded keys in Java, to use them for JWS or JWE later.
For Maven you should include the following BouncyCastle dependencies (where 1.52 is the latest stable version as of May 2015):
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.52</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.52</version>
</dependency>
Example parsing of an PEM-encoded EC key in Java:
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.security.KeyPair;
import java.security.Security;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import com.nimbusds.jose.*;
// Load BouncyCastle as JCA provider
Security.addProvider(new BouncyCastleProvider());
// Parse the EC key pair
PEMParser pemParser = new PEMParser(new InputStreamReader(new FileInputStream("ec512-key-pair.pem")));
PEMKeyPair pemKeyPair = (PEMKeyPair)pemParser.readObject();
// Convert to Java (JCA) format
JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
KeyPair keyPair = converter.getKeyPair(pemKeyPair);
pemParser.close();
// Get private + public EC key
ECPrivateKey privateKey = (ECPrivateKey)keyPair.getPrivate();
ECPublicKey publicKey = (ECPublicKey)keyPair.getPublic();
// Sign test
JWSObject jwsObject = new JWSObject(new JWSHeader(JWSAlgorithm.ES512), new Payload("Hello world!"));
jwsObject.sign(new ECDSASigner(privateKey));
// Serialise
String compactJWS = jwsObject.serialize();
// Verify test
jwsObject = JWSObject.parse(compactJWS);
assertTrue(jwsObject.verify(new ECDSAVerifier(publicKey)));