42
42
import java .util .Arrays ;
43
43
import java .util .HashMap ;
44
44
import java .util .Map ;
45
+ import java .util .stream .Stream ;
45
46
46
47
final class WebAuthnCodecs {
47
48
@@ -151,6 +152,33 @@ private static ECPublicKey importCoseP256PublicKey(CBORObject cose) throws CoseE
151
152
return (ECPublicKey ) new OneKey (cose ).AsPublicKey ();
152
153
}
153
154
155
+ private static ByteArray encodeDerLength (final int length ) {
156
+ if (length <= 127 ) {
157
+ return new ByteArray (new byte [] {(byte ) length });
158
+ } else if (length <= 0xffff ) {
159
+ if (length <= 255 ) {
160
+ return new ByteArray (new byte [] {-127 , (byte ) length });
161
+ } else {
162
+ return new ByteArray (new byte [] {-126 , (byte ) (length >> 8 ), (byte ) (length & 0x00ff )});
163
+ }
164
+ } else {
165
+ throw new UnsupportedOperationException ("Too long: " + length );
166
+ }
167
+ }
168
+
169
+ private static ByteArray encodeDerBitStringWithZeroUnused (final ByteArray content ) {
170
+ return new ByteArray (new byte [] {0x03 })
171
+ .concat (encodeDerLength (1 + content .size ()))
172
+ .concat (new ByteArray (new byte [] {0 }))
173
+ .concat (content );
174
+ }
175
+
176
+ private static ByteArray encodeDerSequence (final ByteArray ... items ) {
177
+ final ByteArray content =
178
+ Stream .of (items ).reduce (ByteArray ::concat ).orElseGet (() -> new ByteArray (new byte [0 ]));
179
+ return new ByteArray (new byte [] {0x30 }).concat (encodeDerLength (content .size ())).concat (content );
180
+ }
181
+
154
182
private static PublicKey importCoseEdDsaPublicKey (CBORObject cose )
155
183
throws InvalidKeySpecException , NoSuchAlgorithmException {
156
184
final int curveId = cose .get (CBORObject .FromObject (-1 )).AsInt32 ();
@@ -166,10 +194,7 @@ private static PublicKey importCoseEd25519PublicKey(CBORObject cose)
166
194
throws InvalidKeySpecException , NoSuchAlgorithmException {
167
195
final ByteArray rawKey = new ByteArray (cose .get (CBORObject .FromObject (-2 )).GetByteString ());
168
196
final ByteArray x509Key =
169
- new ByteArray (new byte [] {0x30 , (byte ) (ED25519_CURVE_OID .size () + 3 + rawKey .size ())})
170
- .concat (ED25519_CURVE_OID )
171
- .concat (new ByteArray (new byte [] {0x03 , (byte ) (rawKey .size () + 1 ), 0 }))
172
- .concat (rawKey );
197
+ encodeDerSequence (ED25519_CURVE_OID , encodeDerBitStringWithZeroUnused (rawKey ));
173
198
174
199
KeyFactory kFact = KeyFactory .getInstance ("EdDSA" );
175
200
return kFact .generatePublic (new X509EncodedKeySpec (x509Key .getBytes ()));
0 commit comments