fuel-crypto icon indicating copy to clipboard operation
fuel-crypto copied to clipboard

Add fuzzy tests to signature

Open vlopes11 opened this issue 2 years ago • 0 comments

This seems quite costly to exhaustively fuzz the entire search space every test run. Using prop-tests we could randomly sample the distribution on each test run and easily track which input params cause a failure:


use proptest::prelude::{
    prop::test_runner::{RngAlgorithm, TestRng}, *,
};
prop_compose! {
    fn arb_rng()(
        bytes: [u8; 32],
    ) -> TestRng {
        TestRng::from_seed(RngAlgorithm::ChaCha, &bytes)
    }
}

proptest! {
    #![proptest_config(ProptestConfig::with_cases(50))]
    #[test]
    fn corrupted_signature(
        mut rng in arb_rng(),
        position in 0..Signature::LEN,
        bit in 0..7,
    ) {
        let message = b"When life itself seems lunatic, who knows where madness lies?";
        let message = Message::new(message);

        let secret = SecretKey::random(&mut rng);
        let public = secret.public_key();

        let signature = Signature::sign(&secret, &message);

        // Tamper a random bit of the signature
        //
        // The recover and verify operations should fail in all cases.

        let mut s = signature;
        let m = 1u8 << bit;
        s.as_mut()[position] ^= m;

        // check recover
        match s.recover(&message) {
            Ok(pk) => assert_ne!(public, pk),
            Err(Error::InvalidSignature) => (),
            Err(e) => panic!("Unexpected error: {}", e),
        }

        // check verify
        assert!(s.verify(&public, &message).is_err());
    }

    #[test]
    fn corrupted_public_key(
        mut rng in arb_rng(),
        position in 0..PublicKey::LEN,
        bit in 0..7,
    ) {
        let message = b"When life itself seems lunatic, who knows where madness lies?";
        let message = Message::new(message);

        let secret = SecretKey::random(&mut rng);
        let mut public = secret.public_key();

        let signature = Signature::sign(&secret, &message);

        // Tamper a random bit of the public key.
        //
        // The verify operations should fail in all cases.
        let m = 1u8 << bit;
        public.as_mut()[position] ^= m;
        assert!(signature.verify(&public, &message).is_err());
    }
}

Originally posted by @Voxelot in https://github.com/FuelLabs/fuel-crypto/pull/2#discussion_r801197967

vlopes11 avatar Feb 09 '22 10:02 vlopes11