1
1
/*
2
- * Copyright 2012-2023 the original author or authors.
2
+ * Copyright 2012-2024 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
30
30
import java .util .Arrays ;
31
31
import java .util .Base64 ;
32
32
import java .util .Collections ;
33
+ import java .util .HashMap ;
34
+ import java .util .HexFormat ;
33
35
import java .util .List ;
36
+ import java .util .Map ;
34
37
import java .util .function .BiFunction ;
35
38
import java .util .regex .Matcher ;
36
39
import java .util .regex .Pattern ;
@@ -74,6 +77,26 @@ final class PemPrivateKeyParser {
74
77
75
78
public static final int BASE64_TEXT_GROUP = 1 ;
76
79
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
+
77
100
private static final List <PemParser > PEM_PARSERS ;
78
101
static {
79
102
List <PemParser > parsers = new ArrayList <>();
@@ -87,51 +110,6 @@ final class PemPrivateKeyParser {
87
110
PEM_PARSERS = Collections .unmodifiableList (parsers );
88
111
}
89
112
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
-
135
113
private PemPrivateKeyParser () {
136
114
}
137
115
@@ -152,29 +130,22 @@ private static PKCS8EncodedKeySpec createKeySpecForSec1Ec(byte[] bytes, String p
152
130
Assert .state (privateKey != null && privateKey .isType (ValueType .PRIMITIVE , TagType .OCTET_STRING ),
153
131
"Key spec should contain private key" );
154
132
DerElement parameters = DerElement .of (ecPrivateKey .getContents ());
155
- return createKeySpecForAlgorithm (bytes , EC_ALGORITHM , getEcParameters (parameters ));
133
+ return createKeySpecForAlgorithm (bytes , ELLIPTIC_CURVE_ALGORITHM , getEcParameters (parameters ));
156
134
}
157
135
158
- private static int [] getEcParameters (DerElement parameters ) {
136
+ private static EncodedOid getEcParameters (DerElement parameters ) {
159
137
if (parameters == null ) {
160
- return EC_PARAMETERS ;
138
+ return ELLIPTIC_CURVE_384_BIT ;
161
139
}
162
140
Assert .state (parameters .isType (ValueType .ENCODED ), "Key spec should contain encoded parameters" );
163
141
DerElement contents = DerElement .of (parameters .getContents ());
164
142
Assert .state (contents .isType (ValueType .PRIMITIVE , TagType .OBJECT_IDENTIFIER ),
165
143
"Key spec parameters should contain object identifier" );
166
- return getOid ( contents . getContents () );
144
+ return EncodedOid . of ( contents );
167
145
}
168
146
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 ) {
178
149
try {
179
150
DerEncoder encoder = new DerEncoder ();
180
151
encoder .integer (0x00 ); // Version 0
@@ -200,46 +171,11 @@ private static PKCS8EncodedKeySpec createKeySpecForPkcs8(byte[] bytes, String pa
200
171
DerElement sequence = DerElement .of (ecPrivateKey .getContents ());
201
172
Assert .state (sequence != null && sequence .isType (ValueType .ENCODED , TagType .SEQUENCE ),
202
173
"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 ),
207
176
"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 );
243
179
}
244
180
245
181
private static PKCS8EncodedKeySpec createKeySpecForPkcs8Encrypted (byte [] bytes , String password ) {
@@ -339,9 +275,9 @@ static class DerEncoder {
339
275
340
276
private final ByteArrayOutputStream stream = new ByteArrayOutputStream ();
341
277
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 );
345
281
}
346
282
347
283
void integer (int ... encodedInteger ) throws IOException {
@@ -537,4 +473,69 @@ private static String getEncryptionAlgorithm(AlgorithmParameters algParameters,
537
473
538
474
}
539
475
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
+
540
541
}
0 commit comments