penis 0.1.1

A Rust implementation of the Penis Protocol
Documentation
use crate::{
    consts::INITIAL_STATE,
    hashfns::{execute_from_rounds, execute_until_rounds},
    structs::{PenisBlock, SecsParam, State},
    Penis,
};

/// Penis Verifier
///
/// Validates and completes the hash computation from Partially Executed Nth-round Intermediate
/// State (PENIS). The verifier can compute the final hash without access to the confidential
/// data portions, ensuring both verifiability and privacy.
///
/// # Security Considerations
///
/// - Must use the same security parameter n as the generator
/// - Verify integrity of received intermediate states
/// - Consider implementing additional validation for security-critical applications
/// - Be aware of potential timing attacks in the verification process
///
/// # Examples
///
/// ```ignore
/// use penis::{PenisVerifier, SecsParam, Penis};
///
/// // Initialize with same security parameter as generator (n=40)
/// let verifier = PenisVerifier(SecsParam::new(40));
///
/// // Decode received intermediate state
/// let decoded = Penis::decode_sparse(&received_data);
///
/// // Complete hash computation
/// let final_state = verifier.resume(decoded);
/// let hash = final_state.finalize();
/// ```
#[derive(Debug)]
pub struct PenisVerifier(pub SecsParam);

impl PenisVerifier {
    /// Resumes the hash computation from intermediate state with a custom initial state.
    ///
    /// This method completes the SHA-256 hash computation from the provided intermediate
    /// state (PENIS), using a specified initial state. It processes both public and private
    /// blocks to produce the final hash state.
    ///
    /// # Arguments
    ///
    /// * `penis` - The intermediate state to resume from
    /// * `initial_state` - The initial state to use for hash computation
    ///
    /// # Returns
    ///
    /// The final State containing the completed hash computation
    ///
    /// # Security Notes
    ///
    /// - The verifier cannot access the original confidential data
    /// - The final hash will match the original if the data is unchanged
    /// - Timing attacks should be considered in security-critical applications
    pub fn resume_with_initial_state(&self, penis: Penis, initial_state: &State) -> State {
        let mut current_state = initial_state.clone();
        let n = self.0.n as usize;
        for block in penis.0 {
            current_state = match block {
                PenisBlock::Private(priv_block) => {
                    execute_from_rounds(&priv_block, current_state, n)
                }
                PenisBlock::Public(pub_block) => {
                    let tmpenis = execute_until_rounds(&pub_block, &current_state, n);
                    execute_from_rounds(&tmpenis, current_state, n)
                }
            };
        }
        current_state
    }

    #[inline]
    /// Resumes the hash computation from intermediate state using the default initial state.
    ///
    /// This is a convenience method that uses the standard SHA-256 initial state values.
    ///
    /// # Arguments
    ///
    /// * `penis` - The intermediate state to resume from
    ///
    /// # Returns
    ///
    /// The final State containing the completed hash computation
    pub fn resume(&self, penis: Penis) -> State {
        self.resume_with_initial_state(penis, &INITIAL_STATE)
    }
}