pub use crate::common::sign_hashed as sign;
pub use crate::common::verify_hashed as verify;
use fdh::Digest;
use num_bigint::BigUint;
use rand::Rng;
use rsa::internals;
use rsa::PublicKey;
pub fn hash_message<H: Digest + Clone, P: PublicKey>(
signer_public_key: &P,
message: &[u8],
) -> Result<Vec<u8>, crate::Error>
where
H::OutputSize: Clone,
{
let (result, _iv) = crate::common::hash_message::<H, P>(signer_public_key, message)?;
Ok(result)
}
pub fn blind<R: Rng, P: PublicKey>(rng: &mut R, pub_key: P, digest: &[u8]) -> (Vec<u8>, Vec<u8>) {
let c = BigUint::from_bytes_be(digest);
let (c, unblinder) = internals::blind::<R, P>(rng, &pub_key, &c);
(c.to_bytes_be(), unblinder.to_bytes_be())
}
pub fn unblind(pub_key: impl PublicKey, blinded_sig: &[u8], unblinder: &[u8]) -> Vec<u8> {
let blinded_sig = BigUint::from_bytes_be(blinded_sig);
let unblinder = BigUint::from_bytes_be(unblinder);
let unblinded = internals::unblind(pub_key, &blinded_sig, &unblinder);
unblinded.to_bytes_be()
}
#[cfg(test)]
mod tests {
use crate::blind;
use crate::Error;
use rsa::PublicKeyParts;
use rsa::{RSAPrivateKey, RSAPublicKey};
use sha2::Sha256;
#[test]
fn blind_test() -> Result<(), Error> {
let mut rng = rand::thread_rng();
let message = b"NEVER GOING TO GIVE YOU UP";
let signer_priv_key = RSAPrivateKey::new(&mut rng, 256).unwrap();
let signer_pub_key =
RSAPublicKey::new(signer_priv_key.n().clone(), signer_priv_key.e().clone()).unwrap();
for _ in 0..500 {
let digest = blind::hash_message::<Sha256, _>(&signer_pub_key, message)?;
let (blinded_digest, unblinder) = blind::blind(&mut rng, &signer_pub_key, &digest);
let blind_signature = blind::sign(&mut rng, &signer_priv_key, &blinded_digest)?;
assert!(blind::verify(&signer_pub_key, &digest, &blind_signature).is_err());
let signature = blind::unblind(&signer_pub_key, &blind_signature, &unblinder);
let check_digest = blind::hash_message::<Sha256, _>(&signer_pub_key, message)?;
blind::verify(&signer_pub_key, &check_digest, &signature)?;
}
Ok(())
}
#[test]
fn error_test() -> Result<(), Error> {
let mut rng = rand::thread_rng();
let message = b"NEVER GOING TO GIVE YOU UP";
let key_1 = RSAPrivateKey::new(&mut rng, 256).unwrap();
let public_1 = key_1.to_public_key();
let digest_1 = blind::hash_message::<Sha256, _>(&public_1, message)?;
let (blinded_digest_1, unblinder_1) = blind::blind(&mut rng, &public_1, &digest_1);
let blind_signature_1 = blind::sign(&mut rng, &key_1, &blinded_digest_1)?;
let signature_1 = blind::unblind(&public_1, &blind_signature_1, &unblinder_1);
let key_2 = RSAPrivateKey::new(&mut rng, 512).unwrap();
let public_2 = key_2.to_public_key();
let digest_2 = blind::hash_message::<Sha256, _>(&public_2, message)?;
let (blinded_digest_2, unblinder_2) = blind::blind(&mut rng, &public_2, &digest_2);
let blind_signature_2 = blind::sign(&mut rng, &key_2, &blinded_digest_2)?;
let signature_2 = blind::unblind(&public_2, &blind_signature_2, &unblinder_2);
assert!(digest_1 != digest_2);
assert!(blinded_digest_1 != blinded_digest_2);
assert!(unblinder_1 != unblinder_2);
assert!(blind_signature_1 != blind_signature_2);
assert!(signature_1 != signature_2);
assert!(blind::sign(&mut rng, &key_1, &blinded_digest_2).is_err());
assert!(blind::verify(&public_1, &digest_1, &signature_2).is_err());
assert!(blind::verify(&public_1, &digest_2, &signature_1).is_err());
assert!(blind::verify(&public_1, &digest_2, &signature_2).is_err());
assert!(blind::verify(&public_2, &digest_1, &signature_1).is_err());
assert!(blind::verify(&public_2, &digest_1, &signature_2).is_err());
assert!(blind::verify(&public_2, &digest_2, &signature_1).is_err());
Ok(())
}
}