use errors::IndyCryptoError;
use pair::{GroupOrderElement, PointG2, PointG1, Pair};
use sha2::{Sha256, Digest};
#[derive(Debug)]
pub struct Generator {
point: PointG2,
bytes: Vec<u8>
}
impl Generator {
pub fn new() -> Result<Generator, IndyCryptoError> {
let point = PointG2::new()?;
Ok(Generator {
point: point,
bytes: point.to_bytes()?
})
}
pub fn as_bytes(&self) -> &[u8] {
self.bytes.as_slice()
}
pub fn from_bytes(bytes: &[u8]) -> Result<Generator, IndyCryptoError> {
Ok(
Generator {
point: PointG2::from_bytes(bytes)?,
bytes: bytes.to_vec()
}
)
}
}
#[derive(Debug)]
pub struct SignKey {
group_order_element: GroupOrderElement,
bytes: Vec<u8>
}
impl SignKey {
pub fn new(seed: Option<&[u8]>) -> Result<SignKey, IndyCryptoError> {
let group_order_element = match seed {
Some(seed) => GroupOrderElement::new_from_seed(seed)?,
_ => GroupOrderElement::new()?
};
Ok(SignKey {
group_order_element: group_order_element,
bytes: group_order_element.to_bytes()?
})
}
pub fn as_bytes(&self) -> &[u8] {
self.bytes.as_slice()
}
pub fn from_bytes(bytes: &[u8]) -> Result<SignKey, IndyCryptoError> {
Ok(
SignKey {
group_order_element: GroupOrderElement::from_bytes(bytes)?,
bytes: bytes.to_vec()
}
)
}
}
#[derive(Debug)]
pub struct VerKey {
point: PointG2,
bytes: Vec<u8>
}
impl VerKey {
pub fn new(gen: &Generator, sign_key: &SignKey) -> Result<VerKey, IndyCryptoError> {
let point = gen.point.mul(&sign_key.group_order_element)?;
Ok(VerKey {
point: point,
bytes: point.to_bytes()?
})
}
pub fn as_bytes(&self) -> &[u8] {
self.bytes.as_slice()
}
pub fn from_bytes(bytes: &[u8]) -> Result<VerKey, IndyCryptoError> {
let point = PointG2::from_bytes(bytes)?;
Ok(
VerKey {
point,
bytes: bytes.to_vec()
}
)
}
}
#[derive(Debug)]
pub struct Signature {
point: PointG1,
bytes: Vec<u8>,
}
impl Signature {
pub fn as_bytes(&self) -> &[u8] {
self.bytes.as_slice()
}
pub fn from_bytes(bytes: &[u8]) -> Result<Signature, IndyCryptoError> {
let point = PointG1::from_bytes(bytes)?;
Ok(
Signature {
point,
bytes: bytes.to_vec()
}
)
}
}
#[derive(Debug)]
pub struct MultiSignature {
point: PointG1,
bytes: Vec<u8>,
}
impl MultiSignature {
pub fn new(signatures: &[&Signature]) -> Result<MultiSignature, IndyCryptoError> {
let mut point = PointG1::new_inf()?;
for signature in signatures {
point = point.add(&signature.point)?;
}
Ok(MultiSignature {
point,
bytes: point.to_bytes()?
})
}
pub fn as_bytes(&self) -> &[u8] {
self.bytes.as_slice()
}
pub fn from_bytes(bytes: &[u8]) -> Result<MultiSignature, IndyCryptoError> {
let point = PointG1::from_bytes(bytes)?;
Ok(
MultiSignature {
point: point,
bytes: bytes.to_vec()
}
)
}
}
pub struct Bls {}
impl Bls {
pub fn sign(message: &[u8], sign_key: &SignKey) -> Result<Signature, IndyCryptoError> {
let point = Bls::_hash(message)?.mul(&sign_key.group_order_element)?;
Ok(Signature {
point,
bytes: point.to_bytes()?
})
}
pub fn verify(signature: &Signature, message: &[u8], ver_key: &VerKey, gen: &Generator) -> Result<bool, IndyCryptoError> {
let h = Bls::_hash(message)?;
Ok(Pair::pair(&signature.point, &gen.point)?.eq(&Pair::pair(&h, &ver_key.point)?))
}
pub fn verify_multi_sig(multi_sig: &MultiSignature, message: &[u8], ver_keys: &[&VerKey], gen: &Generator) -> Result<bool, IndyCryptoError> {
let mut multi_sig_e_list: Vec<Pair> = Vec::new();
for ver_key in ver_keys {
let h = Bls::_hash(message)?;
multi_sig_e_list.push(Pair::pair(&h, &ver_key.point)?);
}
let mut multi_sig_e = multi_sig_e_list.get(0).ok_or(IndyCryptoError::InvalidStructure(format!("Element not found")))?.clone();
for e in multi_sig_e_list[1..].to_vec() {
multi_sig_e = multi_sig_e.mul(&e)?;
}
Ok(Pair::pair(&multi_sig.point, &gen.point)?.eq(&multi_sig_e))
}
fn _hash(message: &[u8]) -> Result<PointG1, IndyCryptoError> {
let mut hasher = Sha256::default();
hasher.input(message);
Ok(PointG1::from_hash(hasher.result().as_slice())?)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn generator_new_works() {
Generator::new().unwrap();
}
#[test]
fn sign_key_new_works() {
SignKey::new(None).unwrap();
}
#[test]
fn sign_key_new_works_for_seed() {
let seed = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 21, 2, 3, 4, 5, 6, 7, 8, 9, 10, 31, 32];
SignKey::new(Some(&seed)).unwrap();
}
#[test]
fn ver_key_new_works() {
let gen = Generator::new().unwrap();
let sign_key = SignKey::new(None).unwrap();
VerKey::new(&gen, &sign_key).unwrap();
}
#[test]
fn bls_sign_works() {
let sign_key = SignKey::new(None).unwrap();
let message = vec![1, 2, 3, 4, 5];
Bls::sign(&message, &sign_key).unwrap();
}
#[test]
fn multi_signature_new_works() {
let message = vec![1, 2, 3, 4, 5];
let sign_key1 = SignKey::new(None).unwrap();
let sign_key2 = SignKey::new(None).unwrap();
let signature1 = Bls::sign(&message, &sign_key1).unwrap();
let signature2 = Bls::sign(&message, &sign_key2).unwrap();
let signatures = vec![
&signature1,
&signature2
];
MultiSignature::new(&signatures).unwrap();
}
#[test]
fn verify_works() {
let message = vec![1, 2, 3, 4, 5];
let gen = Generator::new().unwrap();
let sign_key = SignKey::new(None).unwrap();
let ver_key = VerKey::new(&gen, &sign_key).unwrap();
let signature = Bls::sign(&message, &sign_key).unwrap();
let valid = Bls::verify(&signature, &message, &ver_key, &gen).unwrap();
assert!(valid)
}
#[test]
fn verify_works_for_invalid_message() {
let message = vec![1, 2, 3, 4, 5];
let message_invalid = vec![1, 2, 3, 4, 5, 6];
let gen = Generator::new().unwrap();
let sign_key = SignKey::new(None).unwrap();
let ver_key = VerKey::new(&gen, &sign_key).unwrap();
let signature = Bls::sign(&message, &sign_key).unwrap();
let valid = Bls::verify(&signature, &message_invalid, &ver_key, &gen).unwrap();
assert!(!valid)
}
#[test]
fn verify_works_for_invalid_signature() {
let message = vec![1, 2, 3, 4, 5];
let gen = Generator::new().unwrap();
let sign_key = SignKey::new(None).unwrap();
let ver_key = VerKey::new(&gen, &SignKey::new(None).unwrap()).unwrap();
let signature_invalid = Bls::sign(&message, &sign_key).unwrap();
let valid = Bls::verify(&signature_invalid, &message, &ver_key, &gen).unwrap();
assert!(!valid)
}
#[test]
fn verify_multi_sig_works() {
let message = vec![1, 2, 3, 4, 5];
let gen = Generator::new().unwrap();
let sign_key1 = SignKey::new(None).unwrap();
let ver_key1 = VerKey::new(&gen, &sign_key1).unwrap();
let sign_key2 = SignKey::new(None).unwrap();
let ver_key2 = VerKey::new(&gen, &sign_key2).unwrap();
let ver_keys = vec![
&ver_key1,
&ver_key2
];
let signature1 = Bls::sign(&message, &sign_key1).unwrap();
let signature2 = Bls::sign(&message, &sign_key2).unwrap();
let signatures = vec![
&signature1,
&signature2
];
let multi_signature = MultiSignature::new(&signatures).unwrap();
let valid = Bls::verify_multi_sig(&multi_signature, &message, &ver_keys, &gen).unwrap();
assert!(valid)
}
#[test]
fn verify_multi_sig_works_for_invalid_message() {
let message = vec![1, 2, 3, 4, 5];
let message_invalid = vec![1, 2, 3, 4, 5, 6];
let gen = Generator::new().unwrap();
let sign_key1 = SignKey::new(None).unwrap();
let ver_key1 = VerKey::new(&gen, &sign_key1).unwrap();
let sign_key2 = SignKey::new(None).unwrap();
let ver_key2 = VerKey::new(&gen, &sign_key2).unwrap();
let ver_keys = vec![
&ver_key1,
&ver_key2
];
let signature1 = Bls::sign(&message, &sign_key1).unwrap();
let signature2 = Bls::sign(&message, &sign_key2).unwrap();
let signatures = vec![
&signature1,
&signature2
];
let multi_signature = MultiSignature::new(&signatures).unwrap();
let valid = Bls::verify_multi_sig(&multi_signature, &message_invalid, &ver_keys, &gen).unwrap();
assert!(!valid)
}
#[test]
fn verify_multi_sig_works_for_invalid_signature() {
let message = vec![1, 2, 3, 4, 5];
let gen = Generator::new().unwrap();
let sign_key1 = SignKey::new(None).unwrap();
let ver_key1 = VerKey::new(&gen, &sign_key1).unwrap();
let sign_key2 = SignKey::new(None).unwrap();
let ver_key2 = VerKey::new(&gen, &SignKey::new(None).unwrap()).unwrap();
let ver_keys = vec![
&ver_key1,
&ver_key2
];
let signature1 = Bls::sign(&message, &sign_key1).unwrap();
let signature2 = Bls::sign(&message, &sign_key2).unwrap();
let signatures = vec![
&signature1,
&signature2
];
let multi_signature_invalud = MultiSignature::new(&signatures).unwrap();
let valid = Bls::verify_multi_sig(&multi_signature_invalud, &message, &ver_keys, &gen).unwrap();
assert!(!valid)
}
}