Skip to content

Commit 2d8569f

Browse files
committed
initial support for PEM read/write with EC (ECDSA) keys
1 parent 10a1cfc commit 2d8569f

File tree

1 file changed

+97
-6
lines changed

1 file changed

+97
-6
lines changed

src/main/java/org/jruby/ext/openssl/x509store/PEMInputOutput.java

Lines changed: 97 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,11 @@
5454
import java.security.cert.X509CRL;
5555
import java.security.interfaces.DSAPublicKey;
5656
import java.security.interfaces.DSAPrivateKey;
57+
import java.security.interfaces.ECPrivateKey;
58+
import java.security.interfaces.ECPublicKey;
5759
import java.security.interfaces.RSAPublicKey;
5860
import java.security.interfaces.RSAPrivateCrtKey;
61+
import java.security.spec.ECParameterSpec;
5962
import java.security.spec.InvalidKeySpecException;
6063
import java.security.spec.KeySpec;
6164
import java.security.spec.PKCS8EncodedKeySpec;
@@ -335,8 +338,13 @@ else if ( line.indexOf(BEG_STRING_DSA) != -1 ) {
335338
throw mapReadException("problem creating DSA private key: ", e);
336339
}
337340
}
338-
else if ( line.indexOf(BEG_STRING_ECPRIVATEKEY) != -1) { // TODO EC!
339-
throw new UnsupportedOperationException("EC private key not supported");
341+
else if ( line.indexOf(BEG_STRING_ECPRIVATEKEY) != -1) {
342+
try {
343+
return readKeyPair(reader, passwd, "ECDSA", BEF_E + PEM_STRING_ECPRIVATEKEY);
344+
}
345+
catch (Exception e) {
346+
throw mapReadException("problem creating DSA private key: ", e);
347+
}
340348
}
341349
else if ( line.indexOf(BEG_STRING_PKCS8INF) != -1) {
342350
try {
@@ -448,9 +456,8 @@ private static CipherParameters extractPBES2CipherParams(char[] password, PBES2P
448456
// PEM_read_bio_PUBKEY
449457
public static PublicKey readPubKey(Reader in) throws IOException {
450458
PublicKey pubKey = readRSAPubKey(in);
451-
if (pubKey == null) {
452-
pubKey = readDSAPubKey(in);
453-
}
459+
if (pubKey == null) pubKey = readDSAPubKey(in);
460+
if (pubKey == null) pubKey = readECPubKey(in);
454461
return pubKey;
455462
}
456463

@@ -584,6 +591,55 @@ public static KeyPair readRSAPrivateKey(Reader in, char[] f)
584591
return null;
585592
}
586593

594+
public static ECPublicKey readECPubKey(Reader in) throws IOException {
595+
final String BEG_STRING_EC_PUBLIC = BEF_G + "EC PUBLIC KEY";
596+
final BufferedReader reader = makeBuffered(in); String line;
597+
while ( ( line = reader.readLine() ) != null ) {
598+
if ( line.indexOf(BEG_STRING_EC_PUBLIC) != -1 ) {
599+
try {
600+
return (ECPublicKey) readPublicKey(reader, "ECDSA", BEF_E + "EC PUBLIC KEY");
601+
}
602+
catch (Exception e) {
603+
throw mapReadException("problem creating ECDSA public key: ", e);
604+
}
605+
}
606+
}
607+
return null;
608+
}
609+
610+
public static ECPublicKey readECPublicKey(final Reader in, final char[] passwd) throws IOException {
611+
// final String BEG_STRING_EC = BEF_G + "EC PUBLIC KEY";
612+
final BufferedReader reader = makeBuffered(in); String line;
613+
while ( ( line = reader.readLine() ) != null ) {
614+
if ( line.indexOf(BEG_STRING_PUBLIC) != -1 ) {
615+
try {
616+
return (ECPublicKey) readPublicKey(reader, "ECDSA", BEF_E + PEM_STRING_PUBLIC);
617+
}
618+
catch (Exception e) {
619+
throw mapReadException("problem creating ECDSA public key: ", e);
620+
}
621+
}
622+
}
623+
return null;
624+
}
625+
626+
public static KeyPair readECPrivateKey(final Reader in, final char[] passwd)
627+
throws PasswordRequiredException, IOException {
628+
final String BEG_STRING_EC = BEF_G + "EC PRIVATE KEY";
629+
final BufferedReader reader = makeBuffered(in); String line;
630+
while ( ( line = reader.readLine() ) != null ) {
631+
if ( line.indexOf(BEG_STRING_EC) != -1 ) {
632+
try {
633+
return readKeyPair(reader, passwd, "ECDSA", BEF_E + "EC PRIVATE KEY");
634+
}
635+
catch (Exception e) {
636+
throw mapReadException("problem creating ECDSA private key: ", e);
637+
}
638+
}
639+
}
640+
return null;
641+
}
642+
587643
public static CMSSignedData readPKCS7(Reader in, char[] f) throws IOException {
588644
final String BEG_STRING_PKCS7 = BEF_G + PEM_STRING_PKCS7;
589645
final BufferedReader reader = makeBuffered(in); String line;
@@ -810,6 +866,18 @@ public static void writeRSAPublicKey(Writer _out, RSAPublicKey obj) throws IOExc
810866
out.newLine();
811867
out.flush();
812868
}
869+
870+
public static void writeECPublicKey(Writer _out, ECPublicKey obj) throws IOException {
871+
BufferedWriter out = makeBuffered(_out);
872+
byte[] encoding = getEncoded(obj);
873+
out.write(BEF_G); out.write(PEM_STRING_PUBLIC); out.write(AFT);
874+
out.newLine();
875+
writeEncoded(out, encoding);
876+
out.write(BEF_E); out.write(PEM_STRING_PUBLIC); out.write(AFT);
877+
out.newLine();
878+
out.flush();
879+
}
880+
813881
public static void writePKCS7(Writer _out, ContentInfo obj) throws IOException {
814882
BufferedWriter out = makeBuffered(_out);
815883
byte[] encoding = getEncoded(obj);
@@ -966,6 +1034,29 @@ public static void writeRSAPrivateKey(Writer _out, RSAPrivateCrtKey obj, CipherS
9661034
}
9671035
}
9681036

1037+
public static void writeECPrivateKey(Writer _out, ECPrivateKey obj, CipherSpec cipher, char[] passwd) throws IOException {
1038+
assert (obj != null);
1039+
final String PEM_STRING_EC = "EC PRIVATE KEY";
1040+
BufferedWriter out = makeBuffered(_out);
1041+
org.bouncycastle.asn1.sec.ECPrivateKey keyStruct = new org.bouncycastle.asn1.sec.ECPrivateKey(obj.getS());
1042+
if (cipher != null && passwd != null) {
1043+
writePemEncrypted(out, PEM_STRING_EC, keyStruct.getEncoded(), cipher, passwd);
1044+
} else {
1045+
writePemPlain(out, PEM_STRING_EC, keyStruct.getEncoded());
1046+
}
1047+
}
1048+
1049+
public static void writeECParameters(Writer _out, ASN1ObjectIdentifier obj, CipherSpec cipher, char[] passwd) throws IOException {
1050+
assert (obj != null);
1051+
final String PEM_STRING_EC = "EC PARAMETERS";
1052+
BufferedWriter out = makeBuffered(_out);
1053+
if (cipher != null && passwd != null) {
1054+
writePemEncrypted(out, PEM_STRING_EC, obj.getEncoded(), cipher, passwd);
1055+
} else {
1056+
writePemPlain(out, PEM_STRING_EC, obj.getEncoded());
1057+
}
1058+
}
1059+
9691060
private static void writePemPlain(final BufferedWriter out,
9701061
final String PEM_ID, final byte[] encoding) throws IOException {
9711062
out.write(BEF_G); out.write(PEM_ID); out.write(AFT);
@@ -1099,7 +1190,7 @@ private static PublicKey readPublicKey(BufferedReader in, String alg, String end
10991190

11001191
private static PublicKey readPublicKey(BufferedReader in, String endMarker) throws IOException {
11011192
byte[] input = readBase64Bytes(in, endMarker);
1102-
String[] algs = { "RSA", "DSA" };
1193+
String[] algs = { "RSA", "DSA", "ECDSA" };
11031194
for (int i = 0; i < algs.length; i++) {
11041195
PublicKey key = readPublicKey(input, algs[i], endMarker);
11051196
if (key != null) {

0 commit comments

Comments
 (0)