Skip to content
Merged
18 changes: 11 additions & 7 deletions src/inc_encoding/target_sum.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
use crate::{MESSAGE_LENGTH, symmetric::message_hash::MessageHash};

use super::IncomparableEncoding;
use crate::{MESSAGE_LENGTH, symmetric::message_hash::MessageHash};
use std::fmt::Debug;
use thiserror::Error;

/// Specific errors that can occur during target sum encoding.
#[derive(Debug, Error)]
pub enum TargetSumError {
pub enum TargetSumError<E> {
/// Returned when the generated chunks do not sum to the required target.
#[error("Target sum mismatch: expected {expected}, but got {actual}.")]
Mismatch { expected: usize, actual: usize },

/// Returned when the underlying message hash fails.
#[error("Hash error: {0:?}")]
HashError(E),
}

/// Incomparable Encoding Scheme based on Target Sums,
Expand Down Expand Up @@ -36,7 +40,7 @@ impl<MH: MessageHash, const TARGET_SUM: usize> IncomparableEncoding

type Randomness = MH::Randomness;

type Error = TargetSumError;
type Error = TargetSumError<MH::Error>;

const DIMENSION: usize = MH::DIMENSION;

Expand All @@ -58,7 +62,8 @@ impl<MH: MessageHash, const TARGET_SUM: usize> IncomparableEncoding
epoch: u32,
) -> Result<Vec<u8>, Self::Error> {
// apply the message hash first to get chunks
let chunks = MH::apply(parameter, epoch, randomness, message);
let chunks =
MH::apply(parameter, epoch, randomness, message).map_err(TargetSumError::HashError)?;
let sum: u32 = chunks.iter().map(|&x| x as u32).sum();
// only output something if the chunks sum to the target sum
if sum as usize == TARGET_SUM {
Expand Down Expand Up @@ -93,7 +98,6 @@ mod tests {
use super::*;
use crate::F;
use crate::array::FieldArray;
use crate::symmetric::message_hash::MessageHash;
use crate::symmetric::message_hash::poseidon::PoseidonMessageHash445;
use p3_field::PrimeField32;
use proptest::prelude::*;
Expand Down Expand Up @@ -199,7 +203,7 @@ mod tests {
let parameter = FieldArray(parameter_arr);

// compute expected sum from underlying message hash
let hash_chunks = PoseidonMessageHash445::apply(&parameter, epoch, &randomness, &message);
let hash_chunks = PoseidonMessageHash445::apply(&parameter, epoch, &randomness, &message).unwrap();
let hash_sum: usize = hash_chunks.iter().map(|&x| x as usize).sum();

// call encode twice to check determinism
Expand Down
23 changes: 23 additions & 0 deletions src/signature/generalized_xmss.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,9 @@ impl<PRF: Pseudorandom, IE: IncomparableEncoding, TH: TweakableHash, const LOG_L
{
}

/// Instantiations of the generalized XMSS signature scheme based on the
/// aborting hypercube message hash (rejection sampling)
pub mod instantiations_aborting;
/// Instantiations of the generalized XMSS signature scheme based on Poseidon2
pub mod instantiations_poseidon;
/// Instantiations of the generalized XMSS signature scheme based on the
Expand All @@ -1023,6 +1026,7 @@ mod tests {
symmetric::{
message_hash::{
MessageHash,
aborting::AbortingHypercubeMessageHash,
poseidon::{PoseidonMessageHash, PoseidonMessageHashW1},
},
prf::shake_to_field::ShakePRFtoF,
Expand Down Expand Up @@ -1141,6 +1145,25 @@ mod tests {
test_signature_scheme_correctness::<Sig>(19, 0, Sig::LIFETIME as usize);
}

#[test]
pub fn test_aborting_target_sum() {
// KoalaBear: p = 127 * 8^8 + 1, so w=8, z=8, Q=127
type PRF = ShakePRFtoF<7, 5>;
type TH = PoseidonTweakHash<5, 7, 2, 9, 64>;
type MH = AbortingHypercubeMessageHash<5, 5, 8, 64, 8, 8, 127, 2, 9>;
const TARGET_SUM: usize = MH::DIMENSION * (MH::BASE - 1) / 2; // 224
type IE = TargetSumEncoding<MH, TARGET_SUM>;
const LOG_LIFETIME: usize = 6;
type Sig = GeneralizedXMSSSignatureScheme<PRF, IE, TH, LOG_LIFETIME>;

Sig::internal_consistency_check();

test_signature_scheme_correctness::<Sig>(2, 0, Sig::LIFETIME as usize);
test_signature_scheme_correctness::<Sig>(19, 0, Sig::LIFETIME as usize);
test_signature_scheme_correctness::<Sig>(0, 0, Sig::LIFETIME as usize);
test_signature_scheme_correctness::<Sig>(11, 0, Sig::LIFETIME as usize);
}

#[test]
pub fn test_expand_activation_time() {
const LOG_LIFETIME: usize = 4;
Expand Down
83 changes: 83 additions & 0 deletions src/signature/generalized_xmss/instantiations_aborting.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/// Instantiations with Lifetime 2^6. This is for testing purposes only.
///
/// Warning: Should not be used in production environments.
///
/// !!! TODO: compute properly each parameter. !!!
pub mod lifetime_2_to_the_6 {
use crate::{
inc_encoding::target_sum::TargetSumEncoding,
signature::generalized_xmss::GeneralizedXMSSSignatureScheme,
symmetric::{
message_hash::aborting::AbortingHypercubeMessageHash, prf::shake_to_field::ShakePRFtoF,
tweak_hash::poseidon::PoseidonTweakHash,
},
};

const LOG_LIFETIME: usize = 6;

// KoalaBear: p = 2^31 - 2^24 + 1 = 127 * 8^8 + 1
// w=8, z=8, Q=127, alpha=1
const DIMENSION: usize = 64;
const BASE: usize = 8;
const Z: usize = 8;
const Q: usize = 127;

// TODO
const PARAMETER_LEN: usize = 5;
const TWEAK_LEN_FE: usize = 2;
const MSG_LEN_FE: usize = 9;
const RAND_LEN_FE: usize = 7;
const MH_HASH_LEN_FE: usize = 8;

const TH_HASH_LEN_FE: usize = 8;
const CAPACITY: usize = 9;

type MH = AbortingHypercubeMessageHash<
PARAMETER_LEN,
RAND_LEN_FE,
MH_HASH_LEN_FE,
DIMENSION,
BASE,
Z,
Q,
TWEAK_LEN_FE,
MSG_LEN_FE,
>;

const TARGET_SUM: usize = 230; // TODO

type TH = PoseidonTweakHash<PARAMETER_LEN, TH_HASH_LEN_FE, TWEAK_LEN_FE, CAPACITY, DIMENSION>;
type PRF = ShakePRFtoF<TH_HASH_LEN_FE, RAND_LEN_FE>;
type IE = TargetSumEncoding<MH, TARGET_SUM>;

pub type SIGAbortingLifetime6Dim64Base8 =
GeneralizedXMSSSignatureScheme<PRF, IE, TH, LOG_LIFETIME>;

#[cfg(test)]
mod test {
use crate::signature::{
SignatureScheme, test_templates::test_signature_scheme_correctness,
};

use super::SIGAbortingLifetime6Dim64Base8;

#[test]
pub fn test_internal_consistency() {
SIGAbortingLifetime6Dim64Base8::internal_consistency_check();
}

#[test]
pub fn test_correctness() {
test_signature_scheme_correctness::<SIGAbortingLifetime6Dim64Base8>(
2,
0,
SIGAbortingLifetime6Dim64Base8::LIFETIME as usize,
);
test_signature_scheme_correctness::<SIGAbortingLifetime6Dim64Base8>(
11,
0,
SIGAbortingLifetime6Dim64Base8::LIFETIME as usize,
);
}
}
}
6 changes: 5 additions & 1 deletion src/symmetric/message_hash.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::fmt::Debug;

use rand::Rng;

use crate::MESSAGE_LENGTH;
Expand All @@ -14,6 +16,7 @@ use crate::serialization::Serializable;
pub trait MessageHash {
type Parameter: Clone + Serializable;
type Randomness: Serializable;
type Error: Debug;

/// number of entries in a hash
const DIMENSION: usize;
Expand All @@ -33,13 +36,14 @@ pub trait MessageHash {
epoch: u32,
randomness: &Self::Randomness,
message: &[u8; MESSAGE_LENGTH],
) -> Vec<u8>;
) -> Result<Vec<u8>, Self::Error>;

/// Function to check internal consistency of any given parameters
/// For testing only, and expected to panic if something is wrong.
#[cfg(test)]
fn internal_consistency_check();
}

pub mod aborting;
pub mod poseidon;
pub mod top_level_poseidon;
Loading
Loading