1
+ use aws_lc_rs:: encoding:: { AsDer , Pkcs8V1Der } ;
2
+ use aws_lc_rs:: rsa:: KeySize ;
3
+ use aws_lc_rs:: signature:: RsaKeyPair ;
1
4
use aws_lc_rs:: {
2
5
digest:: { Digest , SHA256 , digest} ,
3
6
pkcs8:: Document ,
@@ -156,7 +159,60 @@ impl JWK {
156
159
& self ,
157
160
) -> Result < signature:: UnparsedPublicKey < Vec < u8 > > , OpaqueError > {
158
161
match & self . key_type {
159
- JWKType :: RSA { .. } => Err ( OpaqueError :: from_display ( "currently not supported" ) ) ,
162
+ JWKType :: RSA { n, e } => {
163
+ let n_bytes = BASE64_URL_SAFE_NO_PAD
164
+ . decode ( n)
165
+ . context ( "decode RSA modulus (n)" ) ?;
166
+ let e_bytes = BASE64_URL_SAFE_NO_PAD
167
+ . decode ( e)
168
+ . context ( "decode RSA exponent (e)" ) ?;
169
+ let n_der_encoded = utils:: encode_integer ( n_bytes) ;
170
+ let e_der_encoded = utils:: encode_integer ( e_bytes) ;
171
+
172
+ let mut rsa_public_key_sequence =
173
+ Vec :: with_capacity ( n_der_encoded. len ( ) + e_der_encoded. len ( ) ) ;
174
+ rsa_public_key_sequence. extend ( n_der_encoded) ;
175
+ rsa_public_key_sequence. extend ( e_der_encoded) ;
176
+
177
+ let rsa_key_len = utils:: encode_der_length ( rsa_public_key_sequence. len ( ) ) ;
178
+ let mut rsa_key_der =
179
+ Vec :: with_capacity ( 1 + rsa_key_len. len ( ) + rsa_public_key_sequence. len ( ) ) ;
180
+ rsa_key_der. push ( 0x30 ) ;
181
+ rsa_key_der. extend ( rsa_key_len) ;
182
+ rsa_key_der. extend ( rsa_public_key_sequence) ;
183
+
184
+ let mut bit_string_payload = Vec :: with_capacity ( 1 + rsa_key_der. len ( ) ) ;
185
+ bit_string_payload. push ( 0x00 ) ;
186
+ bit_string_payload. extend ( rsa_key_der) ;
187
+ let bit_string_len = utils:: encode_der_length ( bit_string_payload. len ( ) ) ;
188
+ let mut bit_string =
189
+ Vec :: with_capacity ( 1 + bit_string_len. len ( ) + bit_string_payload. len ( ) ) ;
190
+ bit_string. push ( 0x03 ) ;
191
+ bit_string. extend ( bit_string_len) ;
192
+ bit_string. extend ( bit_string_payload) ;
193
+
194
+ let algorithm_identifier = [
195
+ 0x30 , 0x0d , 0x06 , 0x09 , 0x2a , 0x86 , 0x48 , 0x86 , 0xf7 , 0x0d , 0x01 , 0x01 , 0x01 ,
196
+ 0x05 , 0x00 ,
197
+ ] ;
198
+
199
+ let mut final_sequence =
200
+ Vec :: with_capacity ( algorithm_identifier. len ( ) + bit_string. len ( ) ) ;
201
+ final_sequence. extend ( algorithm_identifier) ;
202
+ final_sequence. extend ( bit_string) ;
203
+
204
+ let final_sequence_len = utils:: encode_der_length ( final_sequence. len ( ) ) ;
205
+ let mut result =
206
+ Vec :: with_capacity ( final_sequence_len. len ( ) + final_sequence. len ( ) ) ;
207
+ result. push ( 0x30 ) ;
208
+ result. extend ( final_sequence_len) ;
209
+ result. extend ( final_sequence) ;
210
+
211
+ Ok ( signature:: UnparsedPublicKey :: new (
212
+ self . alg . try_into ( ) ?,
213
+ result,
214
+ ) )
215
+ }
160
216
JWKType :: OCT { .. } => Err ( OpaqueError :: from_display (
161
217
"Symmetric key cannot be converted to public key" ,
162
218
) ) ,
@@ -180,6 +236,25 @@ impl JWK {
180
236
}
181
237
}
182
238
}
239
+
240
+ /// Creates a new [`JWK`] from a given [`RSAKeyPair`]
241
+ pub fn new_from_rsa_key_pair ( rsa_key_pair : & RsaKeyPair , alg : JWA ) -> Result < Self , OpaqueError > {
242
+ let n = rsa_key_pair. public_key ( ) . modulus ( ) ;
243
+ let e = rsa_key_pair. public_key ( ) . exponent ( ) ;
244
+ Ok ( Self {
245
+ alg,
246
+ key_type : JWKType :: RSA {
247
+ n : BASE64_URL_SAFE_NO_PAD . encode ( n. big_endian_without_leading_zero ( ) ) ,
248
+ e : BASE64_URL_SAFE_NO_PAD . encode ( e. big_endian_without_leading_zero ( ) ) ,
249
+ } ,
250
+
251
+ r#use : Some ( JWKUse :: Signature ) ,
252
+ key_ops : None ,
253
+ x5c : None ,
254
+ x5t : None ,
255
+ x5t_sha256 : None ,
256
+ } )
257
+ }
183
258
}
184
259
185
260
/// [`EcdsaKey`] which is used to identify and authenticate our requests
@@ -252,7 +327,7 @@ impl EcdsaKey {
252
327
}
253
328
254
329
#[ derive( Serialize ) ]
255
- struct EcdsaKeySigningHeaders < ' a > {
330
+ struct SigningHeaders < ' a > {
256
331
alg : JWA ,
257
332
jwk : & ' a JWK ,
258
333
}
@@ -267,7 +342,7 @@ impl Signer for EcdsaKey {
267
342
_unprotected_headers : & mut super :: jws:: Headers ,
268
343
) -> Result < ( ) , Self :: Error > {
269
344
let jwk = self . create_jwk ( ) ;
270
- protected_headers. try_set_headers ( EcdsaKeySigningHeaders {
345
+ protected_headers. try_set_headers ( SigningHeaders {
271
346
alg : jwk. alg ,
272
347
jwk : & jwk,
273
348
} ) ?;
@@ -284,6 +359,123 @@ impl Signer for EcdsaKey {
284
359
}
285
360
}
286
361
362
+ pub struct RsaKey {
363
+ rng : SystemRandom ,
364
+ alg : JWA ,
365
+ inner : RsaKeyPair ,
366
+ }
367
+
368
+ impl RsaKey {
369
+ /// Create a new [`RsaKey`] from the given [`RsaKeyPairK`]
370
+ pub fn new ( key_pair : RsaKeyPair , alg : JWA , rng : SystemRandom ) -> Result < Self , OpaqueError > {
371
+ Ok ( Self {
372
+ rng,
373
+ alg,
374
+ inner : key_pair,
375
+ } )
376
+ }
377
+
378
+ /// Generate a new [`RsaKey`] from a newly generated [`RsaKeyPair`]
379
+ pub fn generate ( key_size : KeySize ) -> Result < Self , OpaqueError > {
380
+ let key_pair = RsaKeyPair :: generate ( key_size) . context ( "error generating rsa key pair" ) ?;
381
+
382
+ Self :: new ( key_pair, JWA :: RS256 , SystemRandom :: new ( ) )
383
+ }
384
+
385
+ /// Generate a new [`RsaKey`] from the given pkcs8 der
386
+ pub fn from_pkcs8_der (
387
+ pkcs8_der : & [ u8 ] ,
388
+ alg : JWA ,
389
+ rng : SystemRandom ,
390
+ ) -> Result < Self , OpaqueError > {
391
+ let key_pair = RsaKeyPair :: from_pkcs8 ( pkcs8_der) . context ( "create RSAKeyPair from pkcs8" ) ?;
392
+
393
+ Self :: new ( key_pair, alg, rng)
394
+ }
395
+
396
+ /// Create pkcs8 der for the current [`RsaKeyPair`]
397
+ pub fn pkcs8_der ( & self ) -> Result < ( JWA , Pkcs8V1Der < ' static > ) , OpaqueError > {
398
+ let doc = self
399
+ . inner
400
+ . as_der ( )
401
+ . context ( "error creating pkcs8 der from rsa keypair" ) ?;
402
+ Ok ( ( self . alg , doc) )
403
+ }
404
+
405
+ /// Create a [`JWK`] for this [`RsaKey`]
406
+ #[ must_use]
407
+ pub fn create_jwk ( & self ) -> JWK {
408
+ JWK :: new_from_rsa_key_pair ( & self . inner , self . alg )
409
+ . expect ( "error creating jwa from rsa keypair" )
410
+ }
411
+
412
+ #[ must_use]
413
+ pub fn rng ( & self ) -> & SystemRandom {
414
+ & self . rng
415
+ }
416
+ }
417
+
418
+ impl Signer for RsaKey {
419
+ type Signature = Vec < u8 > ;
420
+ type Error = OpaqueError ;
421
+
422
+ fn set_headers (
423
+ & self ,
424
+ protected_headers : & mut super :: jws:: Headers ,
425
+ _unprotected_headers : & mut super :: jws:: Headers ,
426
+ ) -> Result < ( ) , Self :: Error > {
427
+ let jwk = self . create_jwk ( ) ;
428
+ protected_headers. try_set_headers ( SigningHeaders {
429
+ alg : jwk. alg ,
430
+ jwk : & jwk,
431
+ } ) ?;
432
+ Ok ( ( ) )
433
+ }
434
+
435
+ fn sign ( & self , data : & str ) -> Result < Self :: Signature , Self :: Error > {
436
+ let mut sig: Vec < u8 > = Vec :: new ( ) ;
437
+ self . inner
438
+ . sign ( self . alg . try_into ( ) ?, self . rng ( ) , data. as_bytes ( ) , & mut sig)
439
+ . context ( "sign protected data" ) ?;
440
+ Ok ( sig)
441
+ }
442
+ }
443
+
444
+ mod utils {
445
+ pub ( super ) fn encode_der_length ( len : usize ) -> Vec < u8 > {
446
+ if len < 128 {
447
+ vec ! [ len as u8 ]
448
+ } else {
449
+ let mut len_bytes = len. to_be_bytes ( ) . to_vec ( ) ;
450
+ while len_bytes[ 0 ] == 0 {
451
+ len_bytes. remove ( 0 ) ;
452
+ }
453
+ let first_byte = 0x80 | len_bytes. len ( ) as u8 ;
454
+ let mut result = vec ! [ first_byte] ;
455
+ result. extend_from_slice ( & len_bytes) ;
456
+ result
457
+ }
458
+ }
459
+
460
+ /// This function should only be used for parsing JWK encoded RSA values.
461
+ /// The function should **not** be used for general ASN1 encoded values.
462
+ /// The function assumes the input is in minimal form, not empty and is a
463
+ /// positive integer.
464
+ pub ( super ) fn encode_integer ( bytes : Vec < u8 > ) -> Vec < u8 > {
465
+ let needs_leading_zero = bytes[ 0 ] & 0x80 != 0 ;
466
+ let value_len = bytes. len ( ) + needs_leading_zero as usize ;
467
+ let len_bytes = encode_der_length ( value_len) ;
468
+ let mut result = Vec :: with_capacity ( 1 + len_bytes. len ( ) + value_len) ;
469
+ result. push ( 0x02 ) ;
470
+ result. extend_from_slice ( & len_bytes) ;
471
+ if needs_leading_zero {
472
+ result. push ( 0 ) ;
473
+ }
474
+ result. extend ( bytes) ;
475
+ result
476
+ }
477
+ }
478
+
287
479
#[ cfg( test) ]
288
480
mod tests {
289
481
use super :: * ;
@@ -322,4 +514,16 @@ mod tests {
322
514
323
515
assert_eq ! ( key. create_jwk( ) , recreated_key. create_jwk( ) )
324
516
}
517
+
518
+ #[ test]
519
+ fn generate_jwk_from_rsa_key_pair ( ) {
520
+ let rsa_key_pair = RsaKey :: generate ( KeySize :: Rsa4096 ) . unwrap ( ) ;
521
+ let jwk = JWK :: new_from_rsa_key_pair ( & rsa_key_pair. inner , JWA :: PS512 ) . unwrap ( ) ;
522
+ let ( n, e) = match jwk. key_type {
523
+ JWKType :: RSA { n, e } => ( n, e) ,
524
+ _ => panic ! ( "JWK type not RSA" ) ,
525
+ } ;
526
+ assert ! ( BASE64_URL_SAFE_NO_PAD . decode( n) . is_ok( ) ) ;
527
+ assert ! ( BASE64_URL_SAFE_NO_PAD . decode( e) . is_ok( ) ) ;
528
+ }
325
529
}
0 commit comments