26
26
27
27
import com .google .common .primitives .Bytes ;
28
28
import com .upokecenter .cbor .CBORObject ;
29
+ import com .yubico .internal .util .BinaryUtil ;
29
30
import com .yubico .webauthn .data .ByteArray ;
30
31
import com .yubico .webauthn .data .COSEAlgorithmIdentifier ;
31
32
import java .io .IOException ;
40
41
import java .util .Arrays ;
41
42
import java .util .HashMap ;
42
43
import java .util .Map ;
43
- import java .util .stream .Stream ;
44
44
import lombok .AllArgsConstructor ;
45
45
import lombok .NonNull ;
46
46
@@ -175,69 +175,70 @@ private static PublicKey importCoseRsaPublicKey(CBORObject cose)
175
175
private static PublicKey importCoseEcdsaPublicKey (CBORObject cose )
176
176
throws NoSuchAlgorithmException , InvalidKeySpecException {
177
177
final int crv = cose .get (CBORObject .FromObject (-1 )).AsInt32Value ();
178
- final ByteArray x = new ByteArray ( cose .get (CBORObject .FromObject (-2 )).GetByteString () );
179
- final ByteArray y = new ByteArray ( cose .get (CBORObject .FromObject (-3 )).GetByteString () );
178
+ final byte [] x = cose .get (CBORObject .FromObject (-2 )).GetByteString ();
179
+ final byte [] y = cose .get (CBORObject .FromObject (-3 )).GetByteString ();
180
180
181
- final ByteArray curveOid ;
181
+ final byte [] curveOid ;
182
182
switch (crv ) {
183
183
case 1 :
184
- curveOid = P256_CURVE_OID ;
184
+ curveOid = P256_CURVE_OID . getBytes () ;
185
185
break ;
186
186
187
187
case 2 :
188
- curveOid = P384_CURVE_OID ;
188
+ curveOid = P384_CURVE_OID . getBytes () ;
189
189
break ;
190
190
191
191
case 3 :
192
- curveOid = P512_CURVE_OID ;
192
+ curveOid = P512_CURVE_OID . getBytes () ;
193
193
break ;
194
194
195
195
default :
196
196
throw new IllegalArgumentException ("Unknown COSE EC2 curve: " + crv );
197
197
}
198
198
199
- final ByteArray algId =
200
- encodeDerSequence (encodeDerObjectId (EC_PUBLIC_KEY_OID ), encodeDerObjectId (curveOid ));
199
+ final byte [] algId =
200
+ encodeDerSequence (
201
+ encodeDerObjectId (EC_PUBLIC_KEY_OID .getBytes ()), encodeDerObjectId (curveOid ));
201
202
202
- final ByteArray rawKey =
203
+ final byte [] rawKey =
203
204
encodeDerBitStringWithZeroUnused (
204
- new ByteArray (new byte [] {0x04 }) // Raw EC public key with x and y
205
- .concat (x )
206
- .concat (y ));
205
+ BinaryUtil .concat (
206
+ new byte [] {0x04 }, // Raw EC public key with x and y
207
+ x ,
208
+ y ));
207
209
208
- final ByteArray x509Key = encodeDerSequence (algId , rawKey );
210
+ final byte [] x509Key = encodeDerSequence (algId , rawKey );
209
211
210
212
KeyFactory kFact = KeyFactory .getInstance ("EC" );
211
- return kFact .generatePublic (new X509EncodedKeySpec (x509Key . getBytes () ));
213
+ return kFact .generatePublic (new X509EncodedKeySpec (x509Key ));
212
214
}
213
215
214
- static ByteArray encodeDerLength (final int length ) {
216
+ static byte [] encodeDerLength (final int length ) {
215
217
if (length < 0 ) {
216
218
throw new IllegalArgumentException ("Length is negative: " + length );
217
219
} else if (length <= 0x7f ) {
218
- return new ByteArray ( new byte [] {(byte ) (length & 0xff )}) ;
220
+ return new byte [] {(byte ) (length & 0xff )};
219
221
} else if (length <= 0xff ) {
220
- return new ByteArray ( new byte [] {(byte ) (0x80 | 0x01 ), (byte ) (length & 0xff )}) ;
222
+ return new byte [] {(byte ) (0x80 | 0x01 ), (byte ) (length & 0xff )};
221
223
} else if (length <= 0xffff ) {
222
- return new ByteArray (
223
- new byte [] {(byte ) (0x80 | 0x02 ), (byte ) ((length >> 8 ) & 0xff ), (byte ) (length & 0xff )});
224
+ return new byte [] {
225
+ (byte ) (0x80 | 0x02 ), (byte ) ((length >> 8 ) & 0xff ), (byte ) (length & 0xff )
226
+ };
224
227
} else if (length <= 0xffffff ) {
225
- return new ByteArray (
226
- new byte [] {
227
- (byte ) (0x80 | 0x03 ),
228
- (byte ) ((length >> 16 ) & 0xff ),
229
- (byte ) ((length >> 8 ) & 0xff ),
230
- (byte ) (length & 0xff )
231
- });
228
+ return new byte [] {
229
+ (byte ) (0x80 | 0x03 ),
230
+ (byte ) ((length >> 16 ) & 0xff ),
231
+ (byte ) ((length >> 8 ) & 0xff ),
232
+ (byte ) (length & 0xff )
233
+ };
232
234
} else {
233
- return new ByteArray (
234
- new byte [] {
235
- (byte ) (0x80 | 0x04 ),
236
- (byte ) ((length >> 24 ) & 0xff ),
237
- (byte ) ((length >> 16 ) & 0xff ),
238
- (byte ) ((length >> 8 ) & 0xff ),
239
- (byte ) (length & 0xff )
240
- });
235
+ return new byte [] {
236
+ (byte ) (0x80 | 0x04 ),
237
+ (byte ) ((length >> 24 ) & 0xff ),
238
+ (byte ) ((length >> 16 ) & 0xff ),
239
+ (byte ) ((length >> 8 ) & 0xff ),
240
+ (byte ) (length & 0xff )
241
+ };
241
242
}
242
243
}
243
244
@@ -260,7 +261,7 @@ static ParseDerResult<Integer> parseDerLength(@NonNull byte[] der, int offset) {
260
261
case 0 :
261
262
throw new IllegalArgumentException (
262
263
String .format (
263
- "Empty length encoding at offset %d: %s" , offset , new ByteArray (der )));
264
+ "Empty length encoding at offset %d: 0x %s" , offset , BinaryUtil . toHex (der )));
264
265
case 1 :
265
266
return new ParseDerResult <>(der [offset + 1 ] & 0xff , offset + 2 );
266
267
case 2 :
@@ -293,36 +294,36 @@ static ParseDerResult<Integer> parseDerLength(@NonNull byte[] der, int offset) {
293
294
} else {
294
295
throw new IllegalArgumentException (
295
296
String .format (
296
- "Length encoding needs %d octets but only %s remain at index %d: %s" ,
297
- longLen , len - (offset + 1 ), offset + 1 , new ByteArray (der )));
297
+ "Length encoding needs %d octets but only %s remain at index %d: 0x %s" ,
298
+ longLen , len - (offset + 1 ), offset + 1 , BinaryUtil . toHex (der )));
298
299
}
299
300
}
300
301
}
301
302
302
- private static ParseDerResult <ByteArray > parseDerTagged (
303
+ private static ParseDerResult <byte [] > parseDerTagged (
303
304
@ NonNull byte [] der , int offset , byte expectTag ) {
304
305
final int len = der .length - offset ;
305
306
if (len == 0 ) {
306
307
throw new IllegalArgumentException (
307
- String .format ("Empty input at offset %d: %s" , offset , new ByteArray (der )));
308
+ String .format ("Empty input at offset %d: 0x %s" , offset , BinaryUtil . toHex (der )));
308
309
} else {
309
310
final byte tag = der [offset ];
310
311
if (tag == expectTag ) {
311
312
final ParseDerResult <Integer > contentLen = parseDerLength (der , offset + 1 );
312
313
final int contentEnd = contentLen .nextOffset + contentLen .result ;
313
314
return new ParseDerResult <>(
314
- new ByteArray ( Arrays .copyOfRange (der , contentLen .nextOffset , contentEnd ) ), contentEnd );
315
+ Arrays .copyOfRange (der , contentLen .nextOffset , contentEnd ), contentEnd );
315
316
} else {
316
317
throw new IllegalArgumentException (
317
318
String .format (
318
- "Incorrect tag: 0x%02x (expected 0x%02x) at offset %d: %s" ,
319
- tag , expectTag , offset , new ByteArray (der )));
319
+ "Incorrect tag: 0x%02x (expected 0x%02x) at offset %d: 0x %s" ,
320
+ tag , expectTag , offset , BinaryUtil . toHex (der )));
320
321
}
321
322
}
322
323
}
323
324
324
325
/** Parse a SEQUENCE and return a copy of the content octets. */
325
- static ParseDerResult <ByteArray > parseDerSequence (@ NonNull byte [] der , int offset ) {
326
+ static ParseDerResult <byte [] > parseDerSequence (@ NonNull byte [] der , int offset ) {
326
327
return parseDerTagged (der , offset , (byte ) 0x30 );
327
328
}
328
329
@@ -331,7 +332,7 @@ static ParseDerResult<ByteArray> parseDerSequence(@NonNull byte[] der, int offse
331
332
* "constructed" encoding (bit 6 is 1), with a prescribed tag value, and return a copy of the
332
333
* content octets.
333
334
*/
334
- static ParseDerResult <ByteArray > parseDerExplicitlyTaggedContextSpecificConstructed (
335
+ static ParseDerResult <byte [] > parseDerExplicitlyTaggedContextSpecificConstructed (
335
336
@ NonNull byte [] der , int offset , byte tagNumber ) {
336
337
if (tagNumber <= 30 && tagNumber >= 0 ) {
337
338
return parseDerTagged (der , offset , (byte ) ((tagNumber & 0x1f ) | 0xa0 ));
@@ -341,21 +342,21 @@ static ParseDerResult<ByteArray> parseDerExplicitlyTaggedContextSpecificConstruc
341
342
}
342
343
}
343
344
344
- private static ByteArray encodeDerObjectId (final ByteArray oid ) {
345
- return new ByteArray (new byte [] {0x06 , (byte ) oid .size ()}).concat (oid );
345
+ private static byte [] encodeDerObjectId (@ NonNull byte [] oid ) {
346
+ byte [] result = new byte [2 + oid .length ];
347
+ result [0 ] = 0x06 ;
348
+ result [1 ] = (byte ) oid .length ;
349
+ return BinaryUtil .copyInto (oid , result , 2 );
346
350
}
347
351
348
- private static ByteArray encodeDerBitStringWithZeroUnused (final ByteArray content ) {
349
- return new ByteArray (new byte [] {0x03 })
350
- .concat (encodeDerLength (1 + content .size ()))
351
- .concat (new ByteArray (new byte [] {0 }))
352
- .concat (content );
352
+ private static byte [] encodeDerBitStringWithZeroUnused (@ NonNull byte [] content ) {
353
+ return BinaryUtil .concat (
354
+ new byte [] {0x03 }, encodeDerLength (1 + content .length ), new byte [] {0 }, content );
353
355
}
354
356
355
- static ByteArray encodeDerSequence (final ByteArray ... items ) {
356
- final ByteArray content =
357
- Stream .of (items ).reduce (ByteArray ::concat ).orElseGet (() -> new ByteArray (new byte [0 ]));
358
- return new ByteArray (new byte [] {0x30 }).concat (encodeDerLength (content .size ())).concat (content );
357
+ static byte [] encodeDerSequence (final byte []... items ) {
358
+ byte [] content = BinaryUtil .concat (items );
359
+ return BinaryUtil .concat (new byte [] {0x30 }, encodeDerLength (content .length ), content );
359
360
}
360
361
361
362
private static PublicKey importCoseEdDsaPublicKey (CBORObject cose )
@@ -371,12 +372,12 @@ private static PublicKey importCoseEdDsaPublicKey(CBORObject cose)
371
372
372
373
private static PublicKey importCoseEd25519PublicKey (CBORObject cose )
373
374
throws InvalidKeySpecException , NoSuchAlgorithmException {
374
- final ByteArray rawKey = new ByteArray ( cose .get (CBORObject .FromObject (-2 )).GetByteString () );
375
- final ByteArray x509Key =
376
- encodeDerSequence (ED25519_ALG_ID , encodeDerBitStringWithZeroUnused (rawKey ));
375
+ final byte [] rawKey = cose .get (CBORObject .FromObject (-2 )).GetByteString ();
376
+ final byte [] x509Key =
377
+ encodeDerSequence (ED25519_ALG_ID . getBytes () , encodeDerBitStringWithZeroUnused (rawKey ));
377
378
378
379
KeyFactory kFact = KeyFactory .getInstance ("EdDSA" );
379
- return kFact .generatePublic (new X509EncodedKeySpec (x509Key . getBytes () ));
380
+ return kFact .generatePublic (new X509EncodedKeySpec (x509Key ));
380
381
}
381
382
382
383
static String getJavaAlgorithmName (COSEAlgorithmIdentifier alg ) {
0 commit comments