Add utility method to generate ECDSA key pairs

pull/17/merge
Richard Körber 2016-01-31 14:53:36 +01:00
parent f84c2cfe57
commit 6735d3b3f7
2 changed files with 79 additions and 0 deletions

View File

@ -16,10 +16,15 @@ package org.shredzone.acme4j.util;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.openssl.PEMException;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
@ -56,6 +61,26 @@ public class KeyPairUtils {
}
}
/**
* Creates a new elliptic curve {@link KeyPair}.
*
* @param name
* ECDSA curve name (e.g. "secp256r1")
* @return Generated {@link KeyPair}
*/
public static KeyPair createECKeyPair(String name) {
try {
ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(name);
KeyPairGenerator g = KeyPairGenerator.getInstance("ECDSA", "BC");
g.initialize(ecSpec, new SecureRandom());
return g.generateKeyPair();
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException ex) {
throw new IllegalArgumentException("Invalid curve name " + name, ex);
} catch (NoSuchProviderException ex) {
throw new IllegalStateException(ex);
}
}
/**
* Reads a {@link KeyPair} from a PEM file.
*

View File

@ -20,8 +20,12 @@ import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.security.KeyPair;
import java.security.Security;
import java.security.interfaces.ECPublicKey;
import java.security.interfaces.RSAPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.BeforeClass;
import org.junit.Test;
import com.jcabi.matchers.RegexMatchers;
@ -33,6 +37,12 @@ import com.jcabi.matchers.RegexMatchers;
*/
public class KeyPairUtilsTest {
private static final int KEY_SIZE = 2048;
private static final String EC_CURVE = "secp256r1";
@BeforeClass
public static void setup() {
Security.addProvider(new BouncyCastleProvider());
}
/**
* Test that RSA keypairs of the correct size are generated.
@ -76,6 +86,50 @@ public class KeyPairUtilsTest {
// Verify that both keypairs are the same
assertThat(pair, not(sameInstance(readPair)));
assertThat(pair.getPublic().getEncoded(), is(equalTo(readPair.getPublic().getEncoded())));
assertThat(pair.getPrivate().getEncoded(), is(equalTo(readPair.getPrivate().getEncoded())));
}
/**
* Test that ECDSA keypairs are generated.
*/
@Test
public void testCreateECCKeyPair() {
KeyPair pair = KeyPairUtils.createECKeyPair(EC_CURVE);
assertThat(pair, is(notNullValue()));
assertThat(pair.getPublic(), is(instanceOf(ECPublicKey.class)));
}
/**
* Test that reading and writing ECDSA keypairs work correctly.
*/
@Test
public void testWriteAndReadEC() throws IOException {
// Generate a test keypair
KeyPair pair = KeyPairUtils.createECKeyPair(EC_CURVE);
// Write keypair to PEM
String pem;
try (StringWriter out = new StringWriter()) {
KeyPairUtils.writeKeyPair(pair, out);
pem = out.toString();
}
// Make sure PEM file is properly formatted
assertThat(pem, RegexMatchers.matchesPattern(
"-----BEGIN EC PRIVATE KEY-----[\\r\\n]+"
+ "([a-zA-Z0-9/+=]+[\\r\\n]+)+"
+ "-----END EC PRIVATE KEY-----[\\r\\n]*"));
// Read keypair from PEM
KeyPair readPair;
try (StringReader in = new StringReader(pem)) {
readPair = KeyPairUtils.readKeyPair(in);
}
// Verify that both keypairs are the same
assertThat(pair, not(sameInstance(readPair)));
assertThat(pair.getPublic().getEncoded(), is(equalTo(readPair.getPublic().getEncoded())));
assertThat(pair.getPrivate().getEncoded(), is(equalTo(readPair.getPrivate().getEncoded())));
}