i0 0.1.4

thei.rs/i0 reference implementation written in rust
Documentation
use blake3::Hasher;
use curve25519_dalek::digest::{
    FixedOutput, HashMarker, Output, OutputSizeUser, Update, consts::U64,
};

/// Wrapper around BLAKE3 to force 512-bit hash size for use in ed25519_blake3
/// This is needed to generate an [i0:3](https://thei.rs/i0:3) and should NOT be used standalone
#[derive(Clone)]
pub struct Blake3_512 {
    h: Hasher,
}

impl Blake3_512 {
    /// Creates a new BLAKE3 hasher with empty state
    #[inline]
    pub fn new() -> Self {
        Self { h: Hasher::new() }
    }

    /// Adds input bytes to the hash state
    #[inline]
    pub fn update(&mut self, data: &[u8]) {
        self.h.update(data.as_ref());
    }

    /// Uses BLAKE3's `derive_key` to expand a secret key into private key and domain separator
    #[inline]
    pub fn expand_sk(secret_key: &[u8; 32], context: &str) -> [u8; 64] {
        let mut hash: [u8; 64] = [0u8; 64];
        let mut h = Hasher::new_derive_key(context);

        h.update(secret_key);
        h.finalize_xof().fill(&mut hash);

        hash
    }
}

impl OutputSizeUser for Blake3_512 {
    type OutputSize = U64;
}

impl Update for Blake3_512 {
    #[inline]
    fn update(&mut self, data: &[u8]) {
        self.update(data);
    }
}

impl Default for Blake3_512 {
    #[inline]
    fn default() -> Self {
        Self::new()
    }
}

impl FixedOutput for Blake3_512 {
    #[inline]
    fn finalize_into(self, out: &mut Output<Self>) {
        self.h.finalize_xof().fill(out);
    }
}

impl HashMarker for Blake3_512 {}