diff --git a/core/src/main/java/io/grpc/util/CertificateUtils.java b/core/src/main/java/io/grpc/util/CertificateUtils.java index 980862d383..a886ff1f6e 100644 --- a/core/src/main/java/io/grpc/util/CertificateUtils.java +++ b/core/src/main/java/io/grpc/util/CertificateUtils.java @@ -56,7 +56,8 @@ public final class CertificateUtils { /** * Generates a {@link PrivateKey} from a PEM file. - * The key should be PKCS #8 formatted. + * The key should be PKCS #8 formatted. The key algorithm should be "RSA", "DiffieHellman", + * "DSA", or "EC". * The PEM file should contain one item in Base64 encoding, with plain-text headers and footers * (e.g. -----BEGIN PRIVATE KEY----- and -----END PRIVATE KEY-----). * @@ -80,9 +81,20 @@ public final class CertificateUtils { keyContent.append(line); } byte[] decodedKeyBytes = BaseEncoding.base64().decode(keyContent.toString()); - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKeyBytes); - return keyFactory.generatePrivate(keySpec); + try { + return KeyFactory.getInstance("RSA").generatePrivate(keySpec); + } catch (InvalidKeySpecException ignore) { + try { + return KeyFactory.getInstance("DSA").generatePrivate(keySpec); + } catch (InvalidKeySpecException ignore2) { + try { + return KeyFactory.getInstance("EC").generatePrivate(keySpec); + } catch (InvalidKeySpecException e) { + throw new InvalidKeySpecException("Neither RSA, DSA nor EC worked", e); + } + } + } } } diff --git a/core/src/test/java/io/grpc/util/CertificateUtilsTest.java b/core/src/test/java/io/grpc/util/CertificateUtilsTest.java index 5fa93d5b85..3592399448 100644 --- a/core/src/test/java/io/grpc/util/CertificateUtilsTest.java +++ b/core/src/test/java/io/grpc/util/CertificateUtilsTest.java @@ -43,6 +43,7 @@ public class CertificateUtilsTest { public static final String BAD_PEM_CONTENT = "----BEGIN PRIVATE KEY-----\n" + "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDvdzKDTYvRgjBO\n" + "-----END PRIVATE KEY-----"; + public static final String ECDSA_KEY_FILE = "ecdsa.key"; @Test public void readPemCertFile() throws CertificateException, IOException { @@ -101,4 +102,13 @@ public class CertificateUtilsTest { } } + @Test + public void readEcdsaKeyFile() throws Exception { + InputStream in = TestUtils.class.getResourceAsStream("/certs/" + ECDSA_KEY_FILE); + PrivateKey key = CertificateUtils.getPrivateKey(in); + // Checks some information on the test key. + assertThat(key.getAlgorithm()).isEqualTo("EC"); + assertThat(key.getFormat()).isEqualTo("PKCS#8"); + } + } diff --git a/testing/src/main/resources/certs/README b/testing/src/main/resources/certs/README index ab0d851a18..1fa6b73395 100644 --- a/testing/src/main/resources/certs/README +++ b/testing/src/main/resources/certs/README @@ -62,6 +62,11 @@ common name which is set to *.test.google.com. $ openssl x509 -req -CA ca.pem -CAkey ca.key -CAcreateserial -in server1.csr \ -out server1.pem -extensions req_ext -extfile server1-openssl.cnf -days 3650 +ecdsa.key is used to test keys with algorithm other than RSA: +---------------------------------------------------------------------------- +$ openssl ecparam -name secp256k1 -genkey -noout -out ecdsa.pem +$ openssl pkcs8 -topk8 -in ecdsa.pem -out ecdsa.key -nocrypt + Clean up: --------- $ rm *.rsa diff --git a/testing/src/main/resources/certs/ecdsa.key b/testing/src/main/resources/certs/ecdsa.key new file mode 100644 index 0000000000..62b42fd038 --- /dev/null +++ b/testing/src/main/resources/certs/ecdsa.key @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgS0hDYghCuDnBobsToMW6 +vGqwulbAGUX8Oku4ysWMa4qhRANCAAThAMij1tkl4/7RQpZg3w7z1McGSS9q01+4 +3bDcF/Ge2gATx/SNYT5TqaSx7Rka/sJAGaX47ExWLca4gz9KGHih +-----END PRIVATE KEY-----