11/*
2- * Copyright 2012-2023 the original author or authors.
2+ * Copyright 2012-2024 the original author or authors.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
3030import java .util .Arrays ;
3131import java .util .Base64 ;
3232import java .util .Collections ;
33+ import java .util .HashMap ;
34+ import java .util .HexFormat ;
3335import java .util .List ;
36+ import java .util .Map ;
3437import java .util .function .BiFunction ;
3538import java .util .regex .Matcher ;
3639import java .util .regex .Pattern ;
@@ -74,6 +77,26 @@ final class PemPrivateKeyParser {
7477
7578 public static final int BASE64_TEXT_GROUP = 1 ;
7679
80+ private static final EncodedOid RSA_ALGORITHM = EncodedOid .OID_1_2_840_113549_1_1_1 ;
81+
82+ private static final EncodedOid ELLIPTIC_CURVE_ALGORITHM = EncodedOid .OID_1_2_840_10045_2_1 ;
83+
84+ private static final EncodedOid ELLIPTIC_CURVE_384_BIT = EncodedOid .OID_1_3_132_0_34 ;
85+
86+ private static final Map <EncodedOid , String > ALGORITHMS ;
87+ static {
88+ Map <EncodedOid , String > algorithms = new HashMap <>();
89+ algorithms .put (EncodedOid .OID_1_2_840_113549_1_1_1 , "RSA" );
90+ algorithms .put (EncodedOid .OID_1_2_840_113549_1_1_10 , "RSA" );
91+ algorithms .put (EncodedOid .OID_1_2_840_10040_4_1 , "DSA" );
92+ algorithms .put (EncodedOid .OID_1_3_101_110 , "XDH" );
93+ algorithms .put (EncodedOid .OID_1_3_101_111 , "XDH" );
94+ algorithms .put (EncodedOid .OID_1_3_101_112 , "EdDSA" );
95+ algorithms .put (EncodedOid .OID_1_3_101_113 , "EdDSA" );
96+ algorithms .put (EncodedOid .OID_1_2_840_10045_2_1 , "EC" );
97+ ALGORITHMS = Collections .unmodifiableMap (algorithms );
98+ }
99+
77100 private static final List <PemParser > PEM_PARSERS ;
78101 static {
79102 List <PemParser > parsers = new ArrayList <>();
@@ -87,51 +110,6 @@ final class PemPrivateKeyParser {
87110 PEM_PARSERS = Collections .unmodifiableList (parsers );
88111 }
89112
90- /**
91- * ASN.1 encoded object identifier {@literal 1.2.840.113549.1.1.1}.
92- */
93- private static final int [] RSA_ALGORITHM = { 0x2A , 0x86 , 0x48 , 0x86 , 0xF7 , 0x0D , 0x01 , 0x01 , 0x01 };
94-
95- /**
96- * ASN.1 encoded object identifier {@literal 1.2.840.113549.1.1.10}.
97- */
98- private static final int [] RSASSA_PSS_ALGORITHM = { 0x2a , 0x86 , 0x48 , 0x86 , 0xf7 , 0x0d , 0x01 , 0x01 , 0x0a };
99-
100- /**
101- * ASN.1 encoded object identifier {@literal 1.2.840.10040.4.1}.
102- */
103- private static final int [] DSA_ALGORITHM = { 0x2a , 0x86 , 0x48 , 0xce , 0x38 , 0x04 , 0x01 };
104-
105- /**
106- * ASN.1 encoded object identifier {@literal 1.3.101.110}.
107- */
108- private static final int [] X25519_ALGORITHM = { 0x2b , 0x65 , 0x6e };
109-
110- /**
111- * ASN.1 encoded object identifier {@literal 1.3.101.111}.
112- */
113- private static final int [] X448_ALGORITHM = { 0x2b , 0x65 , 0x6f };
114-
115- /**
116- * ASN.1 encoded object identifier {@literal 1.3.101.112}.
117- */
118- private static final int [] ED448_ALGORITHM = { 0x2b , 0x65 , 0x70 };
119-
120- /**
121- * ASN.1 encoded object identifier {@literal 1.3.101.113}.
122- */
123- private static final int [] ED25519_ALGORITHM = { 0x2b , 0x65 , 0x71 };
124-
125- /**
126- * ASN.1 encoded object identifier {@literal 1.2.840.10045.2.1}.
127- */
128- private static final int [] EC_ALGORITHM = { 0x2a , 0x86 , 0x48 , 0xce , 0x3d , 0x02 , 0x01 };
129-
130- /**
131- * ASN.1 encoded object identifier {@literal 1.3.132.0.34}.
132- */
133- private static final int [] EC_PARAMETERS = { 0x2b , 0x81 , 0x04 , 0x00 , 0x22 };
134-
135113 private PemPrivateKeyParser () {
136114 }
137115
@@ -152,29 +130,22 @@ private static PKCS8EncodedKeySpec createKeySpecForSec1Ec(byte[] bytes, String p
152130 Assert .state (privateKey != null && privateKey .isType (ValueType .PRIMITIVE , TagType .OCTET_STRING ),
153131 "Key spec should contain private key" );
154132 DerElement parameters = DerElement .of (ecPrivateKey .getContents ());
155- return createKeySpecForAlgorithm (bytes , EC_ALGORITHM , getEcParameters (parameters ));
133+ return createKeySpecForAlgorithm (bytes , ELLIPTIC_CURVE_ALGORITHM , getEcParameters (parameters ));
156134 }
157135
158- private static int [] getEcParameters (DerElement parameters ) {
136+ private static EncodedOid getEcParameters (DerElement parameters ) {
159137 if (parameters == null ) {
160- return EC_PARAMETERS ;
138+ return ELLIPTIC_CURVE_384_BIT ;
161139 }
162140 Assert .state (parameters .isType (ValueType .ENCODED ), "Key spec should contain encoded parameters" );
163141 DerElement contents = DerElement .of (parameters .getContents ());
164142 Assert .state (contents .isType (ValueType .PRIMITIVE , TagType .OBJECT_IDENTIFIER ),
165143 "Key spec parameters should contain object identifier" );
166- return getOid ( contents . getContents () );
144+ return EncodedOid . of ( contents );
167145 }
168146
169- private static int [] getOid (ByteBuffer bytes ) {
170- int [] result = new int [bytes .remaining ()];
171- for (int i = 0 ; i < result .length ; i ++) {
172- result [i ] = bytes .get () & 0xFF ;
173- }
174- return result ;
175- }
176-
177- private static PKCS8EncodedKeySpec createKeySpecForAlgorithm (byte [] bytes , int [] algorithm , int [] parameters ) {
147+ private static PKCS8EncodedKeySpec createKeySpecForAlgorithm (byte [] bytes , EncodedOid algorithm ,
148+ EncodedOid parameters ) {
178149 try {
179150 DerEncoder encoder = new DerEncoder ();
180151 encoder .integer (0x00 ); // Version 0
@@ -200,46 +171,11 @@ private static PKCS8EncodedKeySpec createKeySpecForPkcs8(byte[] bytes, String pa
200171 DerElement sequence = DerElement .of (ecPrivateKey .getContents ());
201172 Assert .state (sequence != null && sequence .isType (ValueType .ENCODED , TagType .SEQUENCE ),
202173 "Key spec should contain private key" );
203- DerElement algorithmIdentifier = DerElement .of (sequence .getContents ());
204- Assert .state (
205- algorithmIdentifier != null
206- && algorithmIdentifier .isType (ValueType .PRIMITIVE , TagType .OBJECT_IDENTIFIER ),
174+ DerElement algorithmId = DerElement .of (sequence .getContents ());
175+ Assert .state (algorithmId != null && algorithmId .isType (ValueType .PRIMITIVE , TagType .OBJECT_IDENTIFIER ),
207176 "Key spec container object identifier" );
208- int [] oid = getOid (algorithmIdentifier .getContents ());
209- String algorithmName = getAlgorithm (oid );
210- if (algorithmName != null ) {
211- return new PKCS8EncodedKeySpec (bytes , algorithmName );
212- }
213- else {
214- return new PKCS8EncodedKeySpec (bytes );
215- }
216- }
217-
218- private static String getAlgorithm (int [] oid ) {
219- if (oid == null ) {
220- return null ;
221- }
222- if (Arrays .equals (RSA_ALGORITHM , oid )) {
223- return "RSA" ;
224- }
225- else if (Arrays .equals (RSASSA_PSS_ALGORITHM , oid )) {
226- return "RSASSA-PSS" ;
227- }
228- else if (Arrays .equals (DSA_ALGORITHM , oid )) {
229- return "DSA" ;
230- }
231- else if (Arrays .equals (ED448_ALGORITHM , oid ) || Arrays .equals (ED25519_ALGORITHM , oid )) {
232- return "EdDSA" ;
233- }
234- else if (Arrays .equals (X448_ALGORITHM , oid ) || Arrays .equals (X25519_ALGORITHM , oid )) {
235- return "XDH" ;
236- }
237- else if (Arrays .equals (EC_ALGORITHM , oid )) {
238- return "EC" ;
239- }
240- else {
241- return null ;
242- }
177+ String algorithmName = ALGORITHMS .get (EncodedOid .of (algorithmId ));
178+ return (algorithmName != null ) ? new PKCS8EncodedKeySpec (bytes , algorithmName ) : new PKCS8EncodedKeySpec (bytes );
243179 }
244180
245181 private static PKCS8EncodedKeySpec createKeySpecForPkcs8Encrypted (byte [] bytes , String password ) {
@@ -339,9 +275,9 @@ static class DerEncoder {
339275
340276 private final ByteArrayOutputStream stream = new ByteArrayOutputStream ();
341277
342- void objectIdentifier (int ... encodedObjectIdentifier ) throws IOException {
343- int code = (encodedObjectIdentifier != null ) ? 0x06 : 0x05 ;
344- codeLengthBytes (code , bytes ( encodedObjectIdentifier ) );
278+ void objectIdentifier (EncodedOid encodedOid ) throws IOException {
279+ int code = (encodedOid != null ) ? 0x06 : 0x05 ;
280+ codeLengthBytes (code , ( encodedOid != null ) ? encodedOid . toByteArray () : null );
345281 }
346282
347283 void integer (int ... encodedInteger ) throws IOException {
@@ -537,4 +473,69 @@ private static String getEncryptionAlgorithm(AlgorithmParameters algParameters,
537473
538474 }
539475
476+ /**
477+ * ANS.1 encoded object identifier.
478+ */
479+ static final class EncodedOid {
480+
481+ static final EncodedOid OID_1_2_840_10040_4_1 = EncodedOid .of ("2a8648ce380401" );
482+ static final EncodedOid OID_1_2_840_113549_1_1_1 = EncodedOid .of ("2A864886F70D010101" );
483+ static final EncodedOid OID_1_2_840_113549_1_1_10 = EncodedOid .of ("2a864886f70d01010a" );
484+ static final EncodedOid OID_1_3_101_110 = EncodedOid .of ("2b656e" );
485+ static final EncodedOid OID_1_3_101_111 = EncodedOid .of ("2b656f" );
486+ static final EncodedOid OID_1_3_101_112 = EncodedOid .of ("2b6570" );
487+ static final EncodedOid OID_1_3_101_113 = EncodedOid .of ("2b6571" );
488+ static final EncodedOid OID_1_2_840_10045_2_1 = EncodedOid .of ("2a8648ce3d0201" );
489+ static final EncodedOid OID_1_3_132_0_34 = EncodedOid .of ("2b81040022" );
490+
491+ private final byte [] value ;
492+
493+ private EncodedOid (byte [] value ) {
494+ this .value = value ;
495+ }
496+
497+ byte [] toByteArray () {
498+ return this .value .clone ();
499+ }
500+
501+ @ Override
502+ public boolean equals (Object obj ) {
503+ if (this == obj ) {
504+ return true ;
505+ }
506+ if (obj == null || getClass () != obj .getClass ()) {
507+ return false ;
508+ }
509+ return Arrays .equals (this .value , ((EncodedOid ) obj ).value );
510+ }
511+
512+ @ Override
513+ public int hashCode () {
514+ return Arrays .hashCode (this .value );
515+ }
516+
517+ static EncodedOid of (String hexString ) {
518+ return of (HexFormat .of ().parseHex (hexString ));
519+ }
520+
521+ static EncodedOid of (DerElement derElement ) {
522+ return of (derElement .getContents ());
523+ }
524+
525+ static EncodedOid of (ByteBuffer byteBuffer ) {
526+ return of (byteBuffer .array (), byteBuffer .arrayOffset () + byteBuffer .position (), byteBuffer .remaining ());
527+ }
528+
529+ static EncodedOid of (byte [] bytes ) {
530+ return of (bytes , 0 , bytes .length );
531+ }
532+
533+ static EncodedOid of (byte [] bytes , int off , int len ) {
534+ byte [] value = new byte [len ];
535+ System .arraycopy (bytes , off , value , 0 , len );
536+ return new EncodedOid (value );
537+ }
538+
539+ }
540+
540541}
0 commit comments