2021-04-09 00:22:17 +00:00
use rsa ::{ Hash , PaddingScheme , PublicKey , RsaPrivateKey , RsaPublicKey } ;
use rsa ::pkcs8 ::{ FromPrivateKey , FromPublicKey , ToPrivateKey , ToPublicKey } ;
use sha2 ::{ Digest , Sha256 } ;
2022-11-13 18:43:57 +00:00
pub fn generate_rsa_key ( ) -> Result < RsaPrivateKey , rsa ::errors ::Error > {
2021-04-09 00:22:17 +00:00
let mut rng = rand ::rngs ::OsRng ;
let bits = 2048 ;
RsaPrivateKey ::new ( & mut rng , bits )
}
2023-02-18 22:25:49 +00:00
#[ cfg(feature = " test-utils " ) ]
2022-11-13 18:43:57 +00:00
pub fn generate_weak_rsa_key ( ) -> Result < RsaPrivateKey , rsa ::errors ::Error > {
2022-11-13 18:15:56 +00:00
use rand ::SeedableRng ;
2022-10-23 00:39:19 +00:00
let mut rng = rand ::rngs ::SmallRng ::seed_from_u64 ( 0 ) ;
2022-04-26 22:35:39 +00:00
let bits = 512 ;
RsaPrivateKey ::new ( & mut rng , bits )
}
2021-04-09 00:22:17 +00:00
pub fn serialize_private_key (
2022-04-30 19:26:09 +00:00
private_key : & RsaPrivateKey ,
2021-04-09 00:22:17 +00:00
) -> Result < String , rsa ::pkcs8 ::Error > {
private_key . to_pkcs8_pem ( ) . map ( | val | val . to_string ( ) )
}
pub fn deserialize_private_key (
private_key_pem : & str ,
) -> Result < RsaPrivateKey , rsa ::pkcs8 ::Error > {
2021-11-13 17:37:31 +00:00
RsaPrivateKey ::from_pkcs8_pem ( private_key_pem )
2021-04-09 00:22:17 +00:00
}
pub fn get_public_key_pem (
private_key : & RsaPrivateKey ,
) -> Result < String , rsa ::pkcs8 ::Error > {
let public_key = RsaPublicKey ::from ( private_key ) ;
public_key . to_public_key_pem ( )
}
pub fn deserialize_public_key (
public_key_pem : & str ,
) -> Result < RsaPublicKey , rsa ::pkcs8 ::Error > {
2022-02-13 13:10:09 +00:00
// rsa package can't decode PEM string with non-standard wrap width,
// so the input should be normalized first
let parsed_pem = pem ::parse ( public_key_pem . trim ( ) . as_bytes ( ) )
. map_err ( | _ | rsa ::pkcs8 ::Error ::Pem ) ? ;
let normalized_pem = pem ::encode ( & parsed_pem ) ;
RsaPublicKey ::from_public_key_pem ( & normalized_pem )
2021-04-09 00:22:17 +00:00
}
2022-10-23 00:39:19 +00:00
/// RSASSA-PKCS1-v1_5 signature
2023-04-21 20:13:14 +00:00
pub fn create_rsa_sha256_signature (
2021-04-09 00:22:17 +00:00
private_key : & RsaPrivateKey ,
message : & str ,
2022-11-18 23:22:24 +00:00
) -> Result < Vec < u8 > , rsa ::errors ::Error > {
2021-04-09 00:22:17 +00:00
let digest = Sha256 ::digest ( message . as_bytes ( ) ) ;
let padding = PaddingScheme ::new_pkcs1v15_sign ( Some ( Hash ::SHA2_256 ) ) ;
let signature = private_key . sign ( padding , & digest ) ? ;
2022-11-18 23:22:24 +00:00
Ok ( signature )
2021-04-09 00:22:17 +00:00
}
pub fn get_message_digest ( message : & str ) -> String {
let digest = Sha256 ::digest ( message . as_bytes ( ) ) ;
let digest_b64 = base64 ::encode ( digest ) ;
2022-10-23 16:04:02 +00:00
digest_b64
2021-04-09 00:22:17 +00:00
}
2023-04-21 20:13:14 +00:00
pub fn verify_rsa_sha256_signature (
2021-04-09 00:22:17 +00:00
public_key : & RsaPublicKey ,
message : & str ,
2022-11-18 23:22:24 +00:00
signature : & [ u8 ] ,
) -> bool {
2021-04-09 00:22:17 +00:00
let digest = Sha256 ::digest ( message . as_bytes ( ) ) ;
let padding = PaddingScheme ::new_pkcs1v15_sign ( Some ( Hash ::SHA2_256 ) ) ;
let is_valid = public_key . verify (
padding ,
& digest ,
2022-11-18 23:22:24 +00:00
signature ,
2021-04-09 00:22:17 +00:00
) . is_ok ( ) ;
2022-11-18 23:22:24 +00:00
is_valid
2021-04-09 00:22:17 +00:00
}
#[ cfg(test) ]
mod tests {
use super ::* ;
2022-02-13 13:10:09 +00:00
#[ test ]
fn test_deserialize_public_key_nowrap ( ) {
let public_key_pem = " -----BEGIN PUBLIC KEY----- \n MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8ehqQ7n6+pw19U8q2UtxE/9017STW3yRnnqV5nVk8LJ00ba+berqwekxDW+nw77GAu3TJ+hYeeSerUNPup7y3yO3V
YsFtrgWDQ / s8k86sNBU + Ce2GOL7seh46kyAWgJeohh4Rcrr23rftHbvxOcRM8VzYuCeb1DgVhPGtA0xULwIDAQAB \ n - - - - - END PUBLIC KEY - - - - - " ;
let result = deserialize_public_key ( & public_key_pem ) ;
assert_eq! ( result . is_ok ( ) , true ) ;
}
2021-04-09 00:22:17 +00:00
#[ test ]
fn test_public_key_serialization_deserialization ( ) {
2022-11-13 18:43:57 +00:00
let private_key = generate_weak_rsa_key ( ) . unwrap ( ) ;
2021-04-09 00:22:17 +00:00
let public_key_pem = get_public_key_pem ( & private_key ) . unwrap ( ) ;
let public_key = deserialize_public_key ( & public_key_pem ) . unwrap ( ) ;
assert_eq! ( public_key , RsaPublicKey ::from ( & private_key ) ) ;
}
#[ test ]
2022-11-13 18:43:57 +00:00
fn test_verify_rsa_signature ( ) {
let private_key = generate_weak_rsa_key ( ) . unwrap ( ) ;
2021-04-09 00:22:17 +00:00
let message = " test " . to_string ( ) ;
2023-04-21 20:13:14 +00:00
let signature = create_rsa_sha256_signature (
2022-11-18 23:22:24 +00:00
& private_key ,
& message ,
) . unwrap ( ) ;
2021-04-09 00:22:17 +00:00
let public_key = RsaPublicKey ::from ( & private_key ) ;
2023-04-21 20:13:14 +00:00
let is_valid = verify_rsa_sha256_signature (
2022-11-13 18:43:57 +00:00
& public_key ,
& message ,
& signature ,
2022-11-18 23:22:24 +00:00
) ;
2021-04-09 00:22:17 +00:00
assert_eq! ( is_valid , true ) ;
}
}