hbs-lms 0.1.1

Pure Rust implementation of the Leighton Micali Signature scheme with support for key generation, signature generation and verification.
Documentation
use super::definitions::*;
use super::parameters::LmotsParameter;
use crate::constants::*;
use crate::constants::{D_PBLC, MAX_HASH_CHAIN_COUNT, MAX_HASH_SIZE};
use crate::hasher::HashChain;
use crate::Seed;
use tinyvec::ArrayVec;

pub fn generate_private_key<H: HashChain>(
    lms_tree_identifier: LmsTreeIdentifier,
    lms_leaf_identifier: LmsLeafIdentifier,
    seed: Seed<H>,
    lmots_parameter: LmotsParameter<H>,
) -> LmotsPrivateKey<H> {
    let mut key = ArrayVec::new();

    let mut hasher = lmots_parameter.get_hasher();

    for index in 0..lmots_parameter.get_hash_chain_count() {
        hasher.update(&lms_tree_identifier);
        hasher.update(&lms_leaf_identifier);
        hasher.update(&index.to_be_bytes());
        hasher.update(&[0xff]);
        hasher.update(seed.as_slice());

        key.push(hasher.finalize_reset());
    }

    LmotsPrivateKey::new(
        lms_tree_identifier,
        lms_leaf_identifier,
        key,
        lmots_parameter,
    )
}

pub fn generate_public_key<H: HashChain>(private_key: &LmotsPrivateKey<H>) -> LmotsPublicKey<H> {
    let lmots_parameter = &private_key.lmots_parameter;
    let mut hasher = lmots_parameter.get_hasher();

    let hash_chain_count: usize = 2_usize.pow(lmots_parameter.get_winternitz() as u32) - 1;
    let key = &private_key.key;

    let mut public_key_data: ArrayVec<[ArrayVec<[u8; MAX_HASH_SIZE]>; MAX_HASH_CHAIN_COUNT]> =
        ArrayVec::new();

    for i in 0..lmots_parameter.get_hash_chain_count() as usize {
        let mut hash_chain_data = H::prepare_hash_chain_data(
            &private_key.lms_tree_identifier,
            &private_key.lms_leaf_identifier,
        );
        let result = hasher.do_hash_chain(
            &mut hash_chain_data,
            i as u16,
            key[i].as_slice(),
            0,
            hash_chain_count,
        );

        public_key_data.push(result);
    }

    hasher.update(&private_key.lms_tree_identifier);
    hasher.update(&private_key.lms_leaf_identifier);
    hasher.update(&D_PBLC);

    for item in public_key_data.into_iter() {
        hasher.update(item.as_slice());
    }

    let public_key = hasher.finalize();

    LmotsPublicKey::new(
        private_key.lms_tree_identifier,
        private_key.lms_leaf_identifier,
        public_key,
        *lmots_parameter,
    )
}