1+ use aws_lc_rs:: encoding:: { AsDer , Pkcs8V1Der } ;
2+ use aws_lc_rs:: rsa:: KeySize ;
3+ use aws_lc_rs:: signature:: { RsaEncoding , RsaKeyPair , RsaParameters } ;
14use aws_lc_rs:: {
25 digest:: { Digest , SHA256 , digest} ,
36 pkcs8:: Document ,
@@ -156,7 +159,51 @@ impl JWK {
156159 & self ,
157160 ) -> Result < signature:: UnparsedPublicKey < Vec < u8 > > , OpaqueError > {
158161 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 = Vec :: new ( ) ;
173+ rsa_public_key_sequence. extend_from_slice ( & n_der_encoded) ;
174+ rsa_public_key_sequence. extend_from_slice ( & e_der_encoded) ;
175+
176+ let rsa_key_len = utils:: encode_der_length ( rsa_public_key_sequence. len ( ) ) ;
177+ let mut rsa_key_der = vec ! [ 0x30 ] ;
178+ rsa_key_der. extend_from_slice ( & rsa_key_len) ;
179+ rsa_key_der. extend_from_slice ( & rsa_public_key_sequence) ;
180+
181+ let mut bit_string_payload = vec ! [ 0x00 ] ;
182+ bit_string_payload. extend_from_slice ( & rsa_key_der) ;
183+ let bit_string_len = utils:: encode_der_length ( bit_string_payload. len ( ) ) ;
184+ let mut bit_string = vec ! [ 0x03 ] ;
185+ bit_string. extend_from_slice ( & bit_string_len) ;
186+ bit_string. extend_from_slice ( & bit_string_payload) ;
187+
188+ let algorithm_identifier = [
189+ 0x30 , 0x0d , 0x06 , 0x09 , 0x2a , 0x86 , 0x48 , 0x86 , 0xf7 , 0x0d , 0x01 , 0x01 , 0x01 ,
190+ 0x05 , 0x00 ,
191+ ] ;
192+
193+ let mut final_sequence = Vec :: new ( ) ;
194+ final_sequence. extend_from_slice ( & algorithm_identifier) ;
195+ final_sequence. extend_from_slice ( & bit_string) ;
196+
197+ let final_len = utils:: encode_der_length ( final_sequence. len ( ) ) ;
198+ let mut result = vec ! [ 0x30 ] ;
199+ result. extend_from_slice ( & final_len) ;
200+ result. extend_from_slice ( & final_sequence) ;
201+
202+ Ok ( signature:: UnparsedPublicKey :: new (
203+ self . alg . try_into ( ) ?,
204+ result,
205+ ) )
206+ }
160207 JWKType :: OCT { .. } => Err ( OpaqueError :: from_display (
161208 "Symmetric key cannot be converted to public key" ,
162209 ) ) ,
@@ -180,6 +227,27 @@ impl JWK {
180227 }
181228 }
182229 }
230+
231+ /// Creates a new [`JWK`] from a given [`RSAKeyPair`]
232+ pub fn new_from_rsa_key_pair ( rsa_key_pair : & RsaKeyPair , alg : JWA ) -> Result < Self , OpaqueError > {
233+ let n = rsa_key_pair. public_key ( ) . modulus ( ) ;
234+ let e = rsa_key_pair. public_key ( ) . exponent ( ) ;
235+ Ok ( Self {
236+ alg,
237+ key_type : JWKType :: RSA {
238+ n : String :: try_from ( n. big_endian_without_leading_zero ( ) . to_vec ( ) )
239+ . map_err ( |e| OpaqueError :: from_display ( format ! ( "{:?}" , e) ) ) ?,
240+ e : String :: try_from ( e. big_endian_without_leading_zero ( ) . to_vec ( ) )
241+ . map_err ( |e| OpaqueError :: from_display ( format ! ( "{:?}" , e) ) ) ?,
242+ } ,
243+
244+ r#use : Some ( JWKUse :: Signature ) ,
245+ key_ops : None ,
246+ x5c : None ,
247+ x5t : None ,
248+ x5t_sha256 : None ,
249+ } )
250+ }
183251}
184252
185253/// [`EcdsaKey`] which is used to identify and authenticate our requests
@@ -252,7 +320,7 @@ impl EcdsaKey {
252320}
253321
254322#[ derive( Serialize ) ]
255- struct EcdsaKeySigningHeaders < ' a > {
323+ struct SigningHeaders < ' a > {
256324 alg : JWA ,
257325 jwk : & ' a JWK ,
258326}
@@ -267,7 +335,7 @@ impl Signer for EcdsaKey {
267335 _unprotected_headers : & mut super :: jws:: Headers ,
268336 ) -> Result < ( ) , Self :: Error > {
269337 let jwk = self . create_jwk ( ) ;
270- protected_headers. try_set_headers ( EcdsaKeySigningHeaders {
338+ protected_headers. try_set_headers ( SigningHeaders {
271339 alg : jwk. alg ,
272340 jwk : & jwk,
273341 } ) ?;
@@ -284,6 +352,120 @@ impl Signer for EcdsaKey {
284352 }
285353}
286354
355+ pub struct RsaKey {
356+ rng : SystemRandom ,
357+ alg : JWA ,
358+ inner : RsaKeyPair ,
359+ }
360+
361+ impl RsaKey {
362+ /// Create a new [`RsaKey`] from the given [`RsaKeyPairK`]
363+ pub fn new ( key_pair : RsaKeyPair , alg : JWA , rng : SystemRandom ) -> Result < Self , OpaqueError > {
364+ Ok ( Self {
365+ rng,
366+ alg,
367+ inner : key_pair,
368+ } )
369+ }
370+
371+ /// Generate a new [`RsaKey`] from a newly generated [`RsaKeyPair`]
372+ pub fn generate ( key_size : KeySize ) -> Result < Self , OpaqueError > {
373+ let key_pair = RsaKeyPair :: generate ( key_size) . context ( "error generating rsa key pair" ) ?;
374+
375+ Self :: new ( key_pair, JWA :: RS256 , SystemRandom :: new ( ) )
376+ }
377+
378+ /// Generate a new [`RsaKey`] from the given pkcs8 der
379+ pub fn from_pkcs8_der (
380+ pkcs8_der : & [ u8 ] ,
381+ alg : JWA ,
382+ rng : SystemRandom ,
383+ ) -> Result < Self , OpaqueError > {
384+ let key_pair = RsaKeyPair :: from_pkcs8 ( pkcs8_der) . context ( "create RSAKeyPair from pkcs8" ) ?;
385+
386+ Self :: new ( key_pair, alg, rng)
387+ }
388+
389+ /// Create pkcs8 der for the current [`RsaKeyPair`]
390+ pub fn pkcs8_der ( & self ) -> Result < ( JWA , Pkcs8V1Der < ' _ > ) , OpaqueError > {
391+ let doc = self
392+ . inner
393+ . as_der ( )
394+ . context ( "error creating pkcs8 der from rsa keypair" ) ?;
395+ Ok ( ( self . alg , doc) )
396+ }
397+
398+ /// Create a [`JWK`] for this [`RsaKey`]
399+ #[ must_use]
400+ pub fn create_jwk ( & self ) -> JWK {
401+ JWK :: new_from_rsa_key_pair ( & self . inner , self . alg )
402+ . expect ( "error creating jwa from rsa keypair" )
403+ }
404+
405+ #[ must_use]
406+ pub fn rng ( & self ) -> & SystemRandom {
407+ & self . rng
408+ }
409+ }
410+
411+ impl Signer for RsaKey {
412+ type Signature = Vec < u8 > ;
413+ type Error = OpaqueError ;
414+
415+ fn set_headers (
416+ & self ,
417+ protected_headers : & mut super :: jws:: Headers ,
418+ _unprotected_headers : & mut super :: jws:: Headers ,
419+ ) -> Result < ( ) , Self :: Error > {
420+ let jwk = self . create_jwk ( ) ;
421+ protected_headers. try_set_headers ( SigningHeaders {
422+ alg : jwk. alg ,
423+ jwk : & jwk,
424+ } ) ?;
425+ Ok ( ( ) )
426+ }
427+
428+ fn sign ( & self , data : & str ) -> Result < Self :: Signature , Self :: Error > {
429+ let mut sig: Vec < u8 > = Vec :: new ( ) ;
430+ let alg = <& ' static dyn RsaEncoding as TryFrom < JWA > >:: try_from ( self . alg ) ?;
431+ self . inner
432+ . sign ( alg, self . rng ( ) , data. as_bytes ( ) , & mut sig)
433+ . context ( "sign protected data" ) ?;
434+ Ok ( sig)
435+ }
436+ }
437+
438+ mod utils {
439+ pub ( super ) fn encode_der_length ( len : usize ) -> Vec < u8 > {
440+ if len < 128 {
441+ vec ! [ len as u8 ]
442+ } else {
443+ let mut len_bytes = len. to_be_bytes ( ) . to_vec ( ) ;
444+ while len_bytes[ 0 ] == 0 {
445+ len_bytes. remove ( 0 ) ;
446+ }
447+ let first_byte = 0x80 | len_bytes. len ( ) as u8 ;
448+ let mut result = vec ! [ first_byte] ;
449+ result. extend_from_slice ( & len_bytes) ;
450+ result
451+ }
452+ }
453+
454+ pub ( super ) fn encode_integer ( mut bytes : Vec < u8 > ) -> Vec < u8 > {
455+ let needs_leading_zero = bytes[ 0 ] & 0x80 != 0 ;
456+ let value_len = bytes. len ( ) + needs_leading_zero as usize ;
457+ let len_bytes = encode_der_length ( value_len) ;
458+ let mut result = Vec :: with_capacity ( 1 + len_bytes. len ( ) + value_len) ;
459+ result. push ( 0x02 ) ;
460+ result. extend_from_slice ( & len_bytes) ;
461+ if needs_leading_zero {
462+ result. push ( 0 ) ;
463+ }
464+ result. extend ( bytes. into_iter ( ) ) ;
465+ result
466+ }
467+ }
468+
287469#[ cfg( test) ]
288470mod tests {
289471 use super :: * ;
0 commit comments