1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use lamport_sigs::{PrivateKey, PublicKey};
use merkle::{Hashable, MerkleTree, Proof};
use ring::digest::{Algorithm, Context};
use std::io;
use std::io::{Error, ErrorKind};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
/// A wrapper struct around a Lamport public key that implements Hashable.
pub struct MerklePublicKey {
    /// The wrapped Lamport public key.
    pub key: PublicKey,
}

impl MerklePublicKey {
    /// Convenience method to wrap a Lamport `PublicKey` into a `MerklePublicKey`
    pub fn new(pk: PublicKey) -> MerklePublicKey {
        MerklePublicKey { key: pk }
    }
}

impl Hashable for MerklePublicKey {
    fn update_context(&self, context: &mut Context) {
        context.update(&self.key.to_bytes());
    }
}

impl Into<Vec<u8>> for MerklePublicKey {
    fn into(self) -> Vec<u8> {
        self.key.to_bytes()
    }
}

/// A type alias defining a Merkle signature. That includes both the Lamport leaf signature and inclusion proof.
pub type MerkleSignature = (Vec<Vec<u8>>, Proof<MerklePublicKey>);

/// A type alias defining Merkle signed data. That includes the data being signed along with the signature.
pub type MerkleSignedData<T> = (Vec<T>, MerkleSignature);

fn signing_error(reason: &str) -> Error {
    Error::new(
        ErrorKind::Other,
        format!("A signature could not be produced because {}", reason),
    )
}

/// Signs the entries of the data vector
pub fn sign_data_vec<T>(
    data: &[T],
    algorithm: &'static Algorithm,
) -> io::Result<Vec<MerkleSignature>>
where
    T: AsRef<[u8]>,
{
    let mut leaf_keys = (0..data.len())
        .map(|_| PrivateKey::new(algorithm))
        .collect::<Vec<_>>();

    debug_assert!(data.len() == leaf_keys.len());

    let leaf_pub_keys = leaf_keys
        .iter()
        .map(|priv_key| priv_key.public_key())
        .collect::<Vec<_>>();

    let wrapped_leafs = leaf_pub_keys
        .clone()
        .into_iter()
        .map(MerklePublicKey::new)
        .collect::<Vec<_>>();

    let tree = MerkleTree::from_vec(algorithm, wrapped_leafs);

    let proofs_opt = leaf_pub_keys
        .into_iter()
        .map(|pub_key| tree.gen_proof(MerklePublicKey::new(pub_key)))
        .collect::<Option<Vec<_>>>();

    let signatures_opt = leaf_keys
        .iter_mut()
        .zip(data.iter())
        .map(|(priv_key, data)| priv_key.sign(data.as_ref()))
        .collect::<Result<Vec<_>, _>>();

    match (signatures_opt, proofs_opt) {
        (_, None) => Err(signing_error(
            "an issue occured while generating the inclusion proofs.",
        )),

        (Err(err), _) => Err(signing_error(&format!(
            "an issue occured while signing the data: {}",
            err
        ))),

        (Ok(signatures), Some(proofs)) => Ok(signatures.into_iter().zip(proofs).collect()),
    }
}

fn verif_error(reason: &str) -> Error {
    Error::new(ErrorKind::Other, reason)
}

/// Verifies the signature of the data. Returns an error if data couldn't be verified.
pub fn verify_data_vec_signature<T>(
    data: T,
    signature: &MerkleSignature,
    root_hash: &[u8],
) -> io::Result<()>
where
    T: Into<Vec<u8>>,
{
    let (ref sig, ref proof) = *signature;

    let valid_root = proof.validate(root_hash);
    let data_vec = data.into();

    let valid_sig = proof.value.key.verify_signature(sig, data_vec.as_slice());

    if !valid_root {
        return Err(verif_error("The inclusion proof failed to validate."));
    }

    if !valid_sig {
        return Err(verif_error("The signature could not be properly verified."));
    }

    Ok(())
}