@@ -33,6 +33,41 @@ public TagValue(int tagIn, ArrayList<TagValue> listIn) {
3333 tag = tagIn ;
3434 list = listIn ;
3535 }
36+
37+ @ Override
38+ public String toString () {
39+ String t = tagToString (tag );
40+ if (list != null ) {
41+ return "TagValue{tag=" + t + ", size = " + list .size () + "}" ;
42+ } else {
43+ return "TagValue{tag=" + t + ", value=" + bytesToHex (value ) + '}' ;
44+ }
45+ }
46+
47+ private static String bytesToHex (byte [] bytes ) {
48+ StringBuilder sb = new StringBuilder (bytes .length * 2 );
49+ for (byte b : bytes )
50+ sb .append (String .format ("%02x" , b & 0xff ));
51+ return sb .toString ();
52+ }
53+ private static String tagToString (int tag ) {
54+ switch (tag ) {
55+ case 0x2 :
56+ return "INTEGER" ;
57+ case 0x3 :
58+ return "BITSTRING" ;
59+ case 0x4 :
60+ return "OCTETSTRING" ;
61+ case 0x5 :
62+ return "NULL" ;
63+ case 0x6 :
64+ return "OBJECTIDENTIFIER" ;
65+ case 0x30 :
66+ return "SEQUENCE" ;
67+ default :
68+ return Integer .toString (tag );
69+ }
70+ }
3671 }
3772
3873 // 1.2.840.10045.3.1.7
@@ -52,11 +87,15 @@ public TagValue(int tagIn, ArrayList<TagValue> listIn) {
5287 public static final byte [] Oid_Ed25519 = new byte []{0x6 , 0x3 , 0x2b , 101 , 112 };
5388 // 1.3.101.113
5489 public static final byte [] Oid_Ed448 = new byte []{0x6 , 0x3 , 0x2b , 101 , 113 };
90+
91+ // 1.2.840.113549.1.1.1
92+ public static final byte [] Oid_rsaEncryption = new byte []{0x06 , 0x09 , 0x2A , (byte ) 0x86 , 0x48 , (byte ) 0x86 , (byte ) 0xF7 , 0x0D , 0x01 , 0x01 , 0x01 };
5593
5694 private static final byte [] SequenceTag = new byte []{0x30 };
5795 private static final byte [] OctetStringTag = new byte []{0x4 };
5896 private static final byte [] BitStringTag = new byte []{0x3 };
59-
97+ private static final int IntegerTag = 2 ;
98+
6099 /**
61100 * Encode a subject public key info structure from an OID and the data bytes
62101 * for the key
@@ -252,13 +291,13 @@ public static byte[] EncodePKCS8(byte[] algorithm, byte[] keyBytes, byte[] spki)
252291 }
253292
254293 /**
255- * Decode an EC PKCS#8 private key structure
256294 *
295+ * Decode a PKCS#8 private key structure, leaving the private key as an octetstring.
257296 * @param encodedData bytes containing the private key
258297 * @return tag/value from the decoded object
259298 * @throws CoseException - ASN.1 encoding errors
260299 */
261- public static ArrayList <TagValue > DecodePKCS8 (byte [] encodedData ) throws CoseException
300+ public static ArrayList <TagValue > DecodePKCS8Structure (byte [] encodedData ) throws CoseException
262301 {
263302 TagValue pkcs8 = DecodeCompound (0 , encodedData );
264303 if (pkcs8 .tag != 0x30 ) throw new CoseException ("Invalid PKCS8 structure" );
@@ -268,7 +307,7 @@ public static ArrayList<TagValue> DecodePKCS8(byte[] encodedData) throws CoseExc
268307 }
269308
270309 // Version number - we currently only support one version
271- if (retValue .get (0 ).tag != 2 && (( byte []) retValue .get (0 ).value ) [0 ] != 0 ) {
310+ if (retValue .get (0 ).tag != IntegerTag && retValue .get (0 ).value [0 ] != 0 ) {
272311 throw new CoseException ("Invalid PKCS8 structure" );
273312 }
274313
@@ -286,37 +325,78 @@ public static ArrayList<TagValue> DecodePKCS8(byte[] encodedData) throws CoseExc
286325 if (retValue .size () == 4 && retValue .get (3 ).tag != 0xa0 ) {
287326 throw new CoseException ("Invalid PKCS8 structure" );
288327 }
289-
328+
329+ return retValue ;
330+ }
331+
332+
333+
334+ /**
335+ * Decode a RSA PKCS#8 private key octet string
336+ *
337+ * @param pkcs8 The decoded PKCS#8 structure
338+ * @return tag/value from the decoded object
339+ * @throws CoseException - ASN.1 encoding errors
340+ */
341+ public static ArrayList <TagValue > DecodePKCS8RSA (ArrayList <TagValue > pkcs8 ) throws CoseException {
290342 // Decode the contents of the octet string PrivateKey
291-
292- byte [] pk = (byte []) retValue .get (2 ).value ;
343+
344+ byte [] pk = pkcs8 .get (2 ).value ;
345+
346+ TagValue pkd = DecodeCompound (0 , pk );
347+ ArrayList <TagValue > pkdl = pkd .list ;
348+ if (pkd .tag != 0x30 ) throw new CoseException ("Invalid RSAPrivateKey" );
349+ if (pkdl .size () < 8 || pkdl .size () > 11 ) throw new CoseException ("Invalid RSAPrivateKey" );
350+
351+ // We don't support multi-prime decoding (version 1), but we do support single prime (version 0)
352+ if (pkdl .get (0 ).tag != IntegerTag && pkcs8 .get (0 ).value [0 ] != 1 ) {
353+ throw new CoseException ("Invalid RSAPrivateKey" );
354+ }
355+
356+ for (TagValue tagValue : pkd .list ) {
357+ if (tagValue .tag != IntegerTag ) throw new CoseException ("Invalid RSAPrivateKey" );
358+ }
359+
360+ return pkdl ;
361+ }
362+
363+ /**
364+ * Decode an EC PKCS#8 private key octet string
365+ *
366+ * @param pkcs8 The decoded PKCS#8 structure
367+ * @return tag/value from the decoded object
368+ * @throws CoseException - ASN.1 encoding errors
369+ */
370+ public static ArrayList <TagValue > DecodePKCS8EC (ArrayList <TagValue > pkcs8 ) throws CoseException {
371+ // Decode the contents of the octet string PrivateKey
372+
373+ byte [] pk = pkcs8 .get (2 ).value ;
374+
293375 TagValue pkd = DecodeCompound (0 , pk );
294376 ArrayList <TagValue > pkdl = pkd .list ;
295377 if (pkd .tag != 0x30 ) throw new CoseException ("Invalid ECPrivateKey" );
296378 if (pkdl .size () < 2 || pkdl .size () > 4 ) throw new CoseException ("Invalid ECPrivateKey" );
297-
298- if (pkdl .get (0 ).tag != 2 && (( byte []) retValue .get (0 ).value ) [0 ] != 1 ) {
379+
380+ if (pkdl .get (0 ).tag != 2 && pkcs8 .get (0 ).value [0 ] != 1 ) {
299381 throw new CoseException ("Invalid ECPrivateKey" );
300382 }
301-
383+
302384 if (pkdl .get (1 ).tag != 4 ) throw new CoseException ("Invalid ECPrivateKey" );
303-
385+
304386 if (pkdl .size () > 2 ) {
305387 if ((pkdl .get (2 ).tag & 0xff ) != 0xA0 ) {
306388 if (pkdl .size () != 3 || (pkdl .get (2 ).tag & 0xff ) != 0xa1 ) {
307389 throw new CoseException ("Invalid ECPrivateKey" );
308390 }
309391 } else {
310- if (pkdl .size () == 4 && (pkdl .get (3 ).tag & 0xff ) != 0xa1 ) throw new CoseException ("Invalid ECPrivateKey" );
392+ if (pkdl .size () == 4 && (pkdl .get (3 ).tag & 0xff ) != 0xa1 ) throw new CoseException ("Invalid ECPrivateKey" );
311393 }
312394 }
313-
314- retValue .get (2 ).list = pkdl ;
315- retValue .get (2 ).value = null ;
316- retValue .get (2 ).tag = 0x30 ;
317-
318- return retValue ;
395+
396+ return pkdl ;
319397 }
398+
399+
320400
321401 public static byte [] EncodeSignature (byte [] r , byte [] s ) throws CoseException {
322402 ArrayList <byte []> x = new ArrayList <byte []>();
0 commit comments