use std::thread;
use cylinder::{Context, PrivateKey, PublicKey, Signature, Signer};
type TestResult = Result<(), Box<dyn std::error::Error>>;
fn test_signing<C: Context + 'static>(
context: C,
private_key: PrivateKey,
message: &[u8],
expected_signature: Signature,
) -> TestResult {
assert_eq!(
context.new_signer(private_key).sign(message)?,
expected_signature
);
Ok(())
}
fn test_verification<C: Context + 'static>(
context: C,
message: &[u8],
signature: Signature,
public_key: PublicKey,
) -> TestResult {
assert!(context
.new_verifier()
.verify(message, &signature, &public_key)?);
Ok(())
}
fn test_verification_failure<C: Context + 'static>(
context: C,
message: &[u8],
signature: Signature,
public_key: PublicKey,
) -> TestResult {
assert!(!context
.new_verifier()
.verify(message, &signature, &public_key)?);
Ok(())
}
fn test_signing_and_verification<C: Context + 'static>(
context: C,
private_key: PrivateKey,
) -> TestResult {
let signer = context.new_signer(private_key);
let signature = signer.sign(b"Hello")?;
let public_key = signer.public_key()?;
let verifier = context.new_verifier();
assert!(verifier.verify(b"Hello", &signature, &public_key)?);
Ok(())
}
fn test_multiple_key_signing_and_verification<C: Context + 'static>(
context: C,
private_key1: PrivateKey,
private_key2: PrivateKey,
) -> TestResult {
let signer1 = context.new_signer(private_key1);
let signature1 = signer1.sign(b"Hello")?;
let signer2 = context.new_signer(private_key2);
let signature2 = signer2.sign(b"Hello")?;
let public_key1 = signer1.public_key()?;
let public_key2 = signer2.public_key()?;
let verifier = context.new_verifier();
assert!(verifier.verify(b"Hello", &signature1, &public_key1)?);
assert!(verifier.verify(b"Hello", &signature2, &public_key2)?);
Ok(())
}
fn test_get_public_key<C: Context + 'static>(
context: C,
private_key: &PrivateKey,
expected_public_key: PublicKey,
) -> TestResult {
assert_eq!(context.get_public_key(&private_key)?, expected_public_key);
Ok(())
}
fn test_signer_public_key<C: Context + 'static>(
context: C,
private_key: PrivateKey,
expected_public_key: PublicKey,
) -> TestResult {
let signer = context.new_signer(private_key);
assert_eq!(signer.public_key()?, expected_public_key);
Ok(())
}
fn test_signer_return_from_fn<F: FnOnce(PrivateKey) -> Box<dyn Signer>>(
private_key: PrivateKey,
function: F,
) -> TestResult {
function(private_key);
Ok(())
}
fn test_multithreaded_signing<C: Context + 'static>(
context: C,
private_key: PrivateKey,
) -> TestResult {
let signer = context.new_signer(private_key);
let signer1 = signer.clone();
let jh1: thread::JoinHandle<Signature> =
thread::spawn(move || signer1.sign(b"Hello").expect("Unable to sign bytes"));
let signer2 = signer.clone();
let jh2: thread::JoinHandle<Signature> =
thread::spawn(move || signer2.sign(b"Hello").expect("Unable to sign bytes"));
let sig1 = jh1.join().expect("child thread 1 panicked");
let sig2 = jh2.join().expect("child thread 2 panicked");
assert_eq!(sig1, sig2);
let public_key = signer.public_key()?;
let verifier = context.new_verifier();
assert!(verifier.verify(b"Hello", &sig1, &public_key)?);
assert!(verifier.verify(b"Hello", &sig2, &public_key)?);
Ok(())
}
#[cfg(feature = "hash")]
mod hash {
use super::*;
use cylinder::hash::HashContext;
#[test]
fn signing_and_verification() -> TestResult {
let private_key = PrivateKey::new(vec![]);
test_signing_and_verification(HashContext, private_key)
}
#[test]
fn signer_return_from_fn() -> TestResult {
let private_key = PrivateKey::new(vec![]);
test_signer_return_from_fn(private_key, |key| HashContext.new_signer(key))
}
#[test]
fn multithreaded_signing() -> TestResult {
let private_key = PrivateKey::new(vec![]);
test_multithreaded_signing(HashContext, private_key)
}
}
mod secp256k1 {
use super::*;
use cylinder::secp256k1::Secp256k1Context;
const PRIV_KEY1: &str = "2f1e7b7a130d7ba9da0068b3bb0ba1d79e7e77110302c9f746c3c2a63fe40088";
const PUB_KEY1: &str = "026a2c795a9776f75464aa3bda3534c3154a6e91b357b1181d3f515110f84b67c5";
const PRIV_KEY2: &str = "51b845c2cdde22fe646148f0b51eaf5feec8c82ee921d5e0cbe7619f3bb9c62d";
const MSG: &str = "test";
const MSG_KEY1_SIG: &str = "5195115d9be2547b720ee74c23dd841842875db6eae1f5da8605b050a49e702b4aa83be72ab7e3cb20f17c657011b49f4c8632be2745ba4de79e6aa05da57b35";
const INVALID_SIG: &str = "d589c7b1fa5f8a4c5a389de80ae9582c2f7f2a5e21bab5450b670214e5b1c1235e9eb8102fd0ca690a8b42e2c406a682bd57f6daf6e142e5fa4b2c26ef40a490";
#[test]
fn signing() -> TestResult {
let private_key = PrivateKey::new_from_hex(PRIV_KEY1)?;
let message = String::from(MSG).into_bytes();
let expected_signature = Signature::from_hex(MSG_KEY1_SIG)?;
test_signing(
Secp256k1Context::new(),
private_key,
&message,
expected_signature,
)
}
#[test]
fn verification() -> TestResult {
let message = String::from(MSG).into_bytes();
let signature = Signature::from_hex(MSG_KEY1_SIG)?;
let public_key = PublicKey::new_from_hex(PUB_KEY1)?;
test_verification(Secp256k1Context::new(), &message, signature, public_key)
}
#[test]
fn verification_failure() -> TestResult {
let message = String::from(MSG).into_bytes();
let signature = Signature::from_hex(INVALID_SIG)?;
let public_key = PublicKey::new_from_hex(PUB_KEY1)?;
test_verification_failure(Secp256k1Context::new(), &message, signature, public_key)
}
#[test]
fn signing_and_verification() -> TestResult {
let private_key = PrivateKey::new_from_hex(PRIV_KEY1)?;
test_signing_and_verification(Secp256k1Context::new(), private_key)
}
#[test]
fn multiple_key_signing_and_verification() -> TestResult {
let private_key1 = PrivateKey::new_from_hex(PRIV_KEY1)?;
let private_key2 = PrivateKey::new_from_hex(PRIV_KEY2)?;
test_multiple_key_signing_and_verification(
Secp256k1Context::new(),
private_key1,
private_key2,
)
}
#[test]
fn get_public_key() -> TestResult {
let private_key = PrivateKey::new_from_hex(PRIV_KEY1)?;
let public_key = PublicKey::new_from_hex(PUB_KEY1)?;
test_get_public_key(Secp256k1Context::new(), &private_key, public_key)
}
#[test]
fn signer_public_key() -> TestResult {
let private_key = PrivateKey::new_from_hex(PRIV_KEY1)?;
let public_key = PublicKey::new_from_hex(PUB_KEY1)?;
test_signer_public_key(Secp256k1Context::new(), private_key, public_key)
}
#[test]
fn signer_return_from_fn() -> TestResult {
let private_key = PrivateKey::new_from_hex(PRIV_KEY1)?;
test_signer_return_from_fn(private_key, |key| Secp256k1Context::new().new_signer(key))
}
#[test]
fn multithreaded_signing() -> TestResult {
let private_key = PrivateKey::new_from_hex(PRIV_KEY1)?;
test_multithreaded_signing(Secp256k1Context::new(), private_key)
}
}