Skip to content

Commit

Permalink
First implementation of ball sampling.
Browse files Browse the repository at this point in the history
  • Loading branch information
xvzcf committed Jun 11, 2024
1 parent d2b30c8 commit 382c403
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 2 deletions.
2 changes: 1 addition & 1 deletion libcrux-ml-dsa/src/ml_dsa_44.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const ROWS_IN_A: usize = 4;
const COLUMNS_IN_A: usize = 4;

const ETA: usize = 2;
const BITS_PER_ERROR_COEFFICIENT: usize = 3; // ⌊log_2(2 * 2)⌋ + 1
const BITS_PER_ERROR_COEFFICIENT: usize = 3;

const BYTES_FOR_ERROR_RING_ELEMENT: usize =
(BITS_PER_ERROR_COEFFICIENT * COEFFICIENTS_IN_RING_ELEMENT) / 8;
Expand Down
2 changes: 1 addition & 1 deletion libcrux-ml-dsa/src/ml_dsa_87.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const ROWS_IN_A: usize = 8;
const COLUMNS_IN_A: usize = 7;

const ETA: usize = 2;
const BITS_PER_ERROR_COEFFICIENT: usize = 3; // ⌊log_2(2 * 2)⌋ + 1
const BITS_PER_ERROR_COEFFICIENT: usize = 3;

const BYTES_FOR_ERROR_RING_ELEMENT: usize =
(BITS_PER_ERROR_COEFFICIENT * COEFFICIENTS_IN_RING_ELEMENT) / 8;
Expand Down
113 changes: 113 additions & 0 deletions libcrux-ml-dsa/src/sample.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,41 @@ pub(crate) fn sample_mask_ring_element<const GAMMA1_EXPONENT: usize>(
}
}

pub(crate) fn sample_challenge_ring_element<const TAU: usize>(
seed: [u8; 32],
) -> PolynomialRingElement {
// TODO: Use incremental API to squeeze one block at a time.
let mut randomness = H::<544>(&seed).into_iter();

let mut signs: u64 = 0;
for i in 0..8 {
signs |= (randomness.next().unwrap() as u64) << (8 * i);
}

let mut out = PolynomialRingElement::ZERO;

for index in (out.coefficients.len() - TAU)..out.coefficients.len() {
let sample_at = loop {
let i = match randomness.next() {
Some(byte) => byte as usize,

// TODO: We need to re-sample here instead of panicking.
None => panic!("Insufficient randomness to sample challenge ring element."),
};

if i <= index {
break i;
}
};

out.coefficients[index] = out.coefficients[sample_at];
out.coefficients[sample_at] = 1 - 2 * ((signs & 1) as i32);
signs >>= 1;
}

out
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -267,4 +302,82 @@ mod tests {
expected_coefficients
);
}

#[test]
fn test_sample_challenge_ring_element_when_tau_is_39() {
let seed: [u8; 32] = [
3, 9, 159, 119, 236, 6, 207, 7, 103, 108, 187, 137, 222, 35, 37, 30, 79, 224, 204, 186,
41, 38, 148, 188, 201, 50, 105, 155, 129, 217, 124, 57,
];

let expected_coefficients: [i32; COEFFICIENTS_IN_RING_ELEMENT] = [
0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1,
-1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1,
-1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, -1, 0, 0, -1, 1, 0, 0, 1,
0, 0, 0, 1, 0, 0, -1, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1,
0,
];

assert_eq!(
sample_challenge_ring_element::<39>(seed).coefficients,
expected_coefficients
);
}

#[test]
fn test_sample_challenge_ring_element_when_tau_is_49() {
let seed: [u8; 32] = [
147, 7, 165, 152, 200, 20, 4, 38, 107, 110, 111, 176, 108, 84, 109, 201, 232, 125, 52,
83, 160, 120, 106, 44, 76, 41, 76, 144, 8, 184, 4, 74,
];

let expected_coefficients: [i32; COEFFICIENTS_IN_RING_ELEMENT] = [
0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1, -1, 0,
1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0,
-1, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-1, 0, 0, 1, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0,
0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0,
-1, 0, -1, 0, 0, -1, 0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0,
0, -1, 0, 0, 0,
];

assert_eq!(
sample_challenge_ring_element::<49>(seed).coefficients,
expected_coefficients
);
}

#[test]
fn test_sample_challenge_ring_element_when_tau_is_60() {
let seed: [u8; 32] = [
188, 193, 17, 175, 172, 179, 13, 23, 90, 238, 237, 230, 143, 113, 24, 65, 250, 86, 234,
229, 251, 57, 199, 158, 9, 4, 102, 249, 11, 68, 140, 107,
];

let expected_coefficients: [i32; COEFFICIENTS_IN_RING_ELEMENT] = [
0, 0, 0, 0, -1, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0,
0, 0, 1, 1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, -1, 0, 0, -1,
0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0,
0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, -1, 0, 1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 1, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0,
0, 1, 0, -1, 1, 0, 0, 0, 0, 0, 1, 1, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 1, 0, 0, 1, 1, -1, 0,
0, 0, 0, 1, -1, 0,
];

assert_eq!(
sample_challenge_ring_element::<60>(seed).coefficients,
expected_coefficients
);
}
}

0 comments on commit 382c403

Please sign in to comment.