RustCrypto / RSA

RSA implementation in pure Rust
Apache License 2.0
536 stars 146 forks source link

Non intuitive behavior of From<RsaPublicKey> for VeryfyingKey<D> #431

Closed dyatelok closed 3 months ago

dyatelok commented 3 months ago

I had a problem with signature verification. I narrowed problem down to the following test:

#[test]
fn test_signing_verifying() {
    use rsa::{
        pkcs1v15::{Signature, SigningKey, VerifyingKey},
        sha2::Sha256,
        signature::{RandomizedSigner, SignatureEncoding, Verifier},
        RsaPrivateKey,
    };

    const BIT_SIZE: usize = 2048;

    let mut rng = rand::thread_rng();
    let private_key = RsaPrivateKey::new(&mut rng, BIT_SIZE).expect("failed to generate a key");

    let signing_key = SigningKey::<Sha256>::new(private_key.clone());
    let public_key = private_key.to_public_key();
    let verifying_key: VerifyingKey<Sha256> = public_key.into();

    let data = vec![123u8; 255];
    let signature = signing_key.sign_with_rng(&mut rng, &data).to_bytes();
    let signature = signature.as_ref();
    let Ok(signature) = Signature::try_from(signature) else {
        panic!("Failed to convert back to signature")
    };

    let is_valid = verifying_key.verify(&data, &signature).is_ok();

    assert!(is_valid);
}

It fails. However if I change lines

    let signing_key = SigningKey::<Sha256>::new(private_key.clone());
    let public_key = private_key.to_public_key();
    let verifying_key: VerifyingKey<Sha256> = public_key.into();

to

    let signing_key = SigningKey::<Sha256>::new(private_key.clone());
    let verifying_key: VerifyingKey<Sha256> = signing_key.verifying_key();

It works. Very unintuitive. Reason for this From trait implementation which uses new_unprefixed instead of new. https://docs.rs/rsa/latest/src/rsa/pkcs1v15/verifying_key.rs.html#163-170

In the docs to new_unprefixed it even says that you most likely wanna use new. So I consider this being a bug.

tarcieri commented 3 months ago

Dup of #341