p128pow5t3.rs: Test against reference input for Fq field modulus.

This commit is contained in:
therealyingtong 2021-08-30 12:54:19 +08:00
parent 4eb4c57827
commit f5775b6c6d
3 changed files with 127 additions and 84 deletions

View File

@ -1,3 +1,5 @@
//! https://github.com/daira/pasta-hadeshash
//!
//! $ sage generate_parameters_grain.sage 1 0 255 3 8 56 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001
use pasta_curves::pallas;

View File

@ -1,3 +1,5 @@
//! https://github.com/daira/pasta-hadeshash
//!
//! sage generate_parameters_grain.sage 1 0 255 3 8 56 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001
use pasta_curves::vesta;
@ -1295,7 +1297,7 @@ pub(crate) const ROUND_CONSTANTS: [[vesta::Base; 3]; 64] = [
// [True, None]
// Result Algorithm 3:
// [True, None]
// Prime number: 0x0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001
// Prime number: 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001
// MDS matrix:
pub(crate) const MDS: [[vesta::Base; 3]; 3] = [
[

View File

@ -1,18 +1,18 @@
use halo2::arithmetic::Field;
use pasta_curves::{pallas, vesta};
use pasta_curves::{pallas::Base as Fp, vesta::Base as Fq};
use super::{Mds, Spec};
/// Poseidon-128 using the $x^5$ S-box, with a width of 3 field elements, and the
/// standard number of rounds for 128-bit security "with margin".
///
/// The standard specification for this set of parameters uses $R_F = 8, R_P = 56$.
/// This is conveniently an even number of partial rounds, making it easier to
/// construct a Halo 2 circuit.
/// The standard specification for this set of parameters (on either of the Pasta
/// fields) uses $R_F = 8, R_P = 56$. This is conveniently an even number of
/// partial rounds, making it easier to construct a Halo 2 circuit.
#[derive(Debug)]
pub struct P128Pow5T3;
impl Spec<pallas::Base, 3, 2> for P128Pow5T3 {
impl Spec<Fp, 3, 2> for P128Pow5T3 {
fn full_rounds() -> usize {
8
}
@ -21,7 +21,7 @@ impl Spec<pallas::Base, 3, 2> for P128Pow5T3 {
56
}
fn sbox(val: pallas::Base) -> pallas::Base {
fn sbox(val: Fp) -> Fp {
val.pow_vartime(&[5])
}
@ -29,13 +29,7 @@ impl Spec<pallas::Base, 3, 2> for P128Pow5T3 {
unimplemented!()
}
fn constants(
&self,
) -> (
Vec<[pallas::Base; 3]>,
Mds<pallas::Base, 3>,
Mds<pallas::Base, 3>,
) {
fn constants(&self) -> (Vec<[Fp; 3]>, Mds<Fp, 3>, Mds<Fp, 3>) {
(
super::fp::ROUND_CONSTANTS[..].to_vec(),
super::fp::MDS,
@ -44,7 +38,7 @@ impl Spec<pallas::Base, 3, 2> for P128Pow5T3 {
}
}
impl Spec<vesta::Base, 3, 2> for P128Pow5T3 {
impl Spec<Fq, 3, 2> for P128Pow5T3 {
fn full_rounds() -> usize {
8
}
@ -53,7 +47,7 @@ impl Spec<vesta::Base, 3, 2> for P128Pow5T3 {
56
}
fn sbox(val: vesta::Base) -> vesta::Base {
fn sbox(val: Fq) -> Fq {
val.pow_vartime(&[5])
}
@ -61,13 +55,7 @@ impl Spec<vesta::Base, 3, 2> for P128Pow5T3 {
unimplemented!()
}
fn constants(
&self,
) -> (
Vec<[vesta::Base; 3]>,
Mds<vesta::Base, 3>,
Mds<vesta::Base, 3>,
) {
fn constants(&self) -> (Vec<[Fq; 3]>, Mds<Fq, 3>, Mds<Fq, 3>) {
(
super::fq::ROUND_CONSTANTS[..].to_vec(),
super::fq::MDS,
@ -78,13 +66,15 @@ impl Spec<vesta::Base, 3, 2> for P128Pow5T3 {
#[cfg(test)]
mod tests {
use ff::PrimeField;
use std::marker::PhantomData;
use ff::PrimeField;
use halo2::arithmetic::FieldExt;
use pasta_curves::{pallas, vesta};
use pasta_curves::arithmetic::FieldExt;
use super::super::{fp, fq};
use super::{
super::{fp, fq},
Fp, Fq,
};
use crate::primitives::poseidon::{permute, ConstantLength, Hash, Spec};
/// The same Poseidon specification as poseidon::P128Pow5T3, but constructed
@ -125,7 +115,7 @@ mod tests {
#[test]
fn verify_constants() {
{
let poseidon = P128Pow5T3Gen::<pallas::Base>::new(0);
let poseidon = P128Pow5T3Gen::<Fp>::new(0);
let (round_constants, mds, mds_inv) = poseidon.constants();
for (actual, expected) in round_constants
@ -146,7 +136,7 @@ mod tests {
}
{
let poseidon = P128Pow5T3Gen::<vesta::Base>::new(0);
let poseidon = P128Pow5T3Gen::<Fq>::new(0);
let (round_constants, mds, mds_inv) = poseidon.constants();
for (actual, expected) in round_constants
@ -169,58 +159,107 @@ mod tests {
#[test]
fn test_against_reference() {
// This is the test vector output by the reference code at
// <https://extgit.iaik.tugraz.at/krypto/hadeshash>, using parameters from
// `generate_parameters_grain.sage 1 0 255 3 8 56 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001`.
{
// <https://github.com/daira/pasta-hadeshash>, using parameters from
// `generate_parameters_grain.sage 1 0 255 3 8 56 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001`.
// The test vector is generated by `sage poseidonperm_x5_pallas_3.sage --rust`
let mut input = [
pallas::Base::from_raw([
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
]),
pallas::Base::from_raw([
0x0000_0000_0000_0001,
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
]),
pallas::Base::from_raw([
0x0000_0000_0000_0002,
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
]),
];
let mut input = [
Fp::from_raw([
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
]),
Fp::from_raw([
0x0000_0000_0000_0001,
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
]),
Fp::from_raw([
0x0000_0000_0000_0002,
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
]),
];
let expected_output = [
pallas::Base::from_raw([
0xaeb1_bc02_4aec_a456,
0xf7e6_9a71_d0b6_42a0,
0x94ef_b364_f966_240f,
0x2a52_6acd_0b64_b453,
]),
pallas::Base::from_raw([
0x012a_3e96_28e5_b82a,
0xdcd4_2e7f_bed9_dafe,
0x76ff_7dae_343d_5512,
0x13c5_d156_8b4a_a430,
]),
pallas::Base::from_raw([
0x3590_29a1_d34e_9ddd,
0xf7cf_dfe1_bda4_2c7b,
0x256f_cd59_7984_561a,
0x0a49_c868_c697_6544,
]),
];
let expected_output = [
Fp::from_raw([
0xaeb1_bc02_4aec_a456,
0xf7e6_9a71_d0b6_42a0,
0x94ef_b364_f966_240f,
0x2a52_6acd_0b64_b453,
]),
Fp::from_raw([
0x012a_3e96_28e5_b82a,
0xdcd4_2e7f_bed9_dafe,
0x76ff_7dae_343d_5512,
0x13c5_d156_8b4a_a430,
]),
Fp::from_raw([
0x3590_29a1_d34e_9ddd,
0xf7cf_dfe1_bda4_2c7b,
0x256f_cd59_7984_561a,
0x0a49_c868_c697_6544,
]),
];
permute::<pallas::Base, P128Pow5T3Gen<pallas::Base>, 3, 2>(
&mut input,
&fp::MDS,
&fp::ROUND_CONSTANTS,
);
assert_eq!(input, expected_output);
permute::<Fp, P128Pow5T3Gen<Fp>, 3, 2>(&mut input, &fp::MDS, &fp::ROUND_CONSTANTS);
assert_eq!(input, expected_output);
}
{
// <https://github.com/daira/pasta-hadeshash>, using parameters from
// `generate_parameters_grain.sage 1 0 255 3 8 56 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001`.
// The test vector is generated by `sage poseidonperm_x5_vesta_3.sage --rust`
let mut input = [
Fq::from_raw([
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
]),
Fq::from_raw([
0x0000_0000_0000_0001,
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
]),
Fq::from_raw([
0x0000_0000_0000_0002,
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
]),
];
let expected_output = [
Fq::from_raw([
0x0eb0_8ea8_13be_be59,
0x4d43_d197_3dd3_36c6,
0xeddd_74f2_2f8f_2ff7,
0x315a_1f4c_db94_2f7c,
]),
Fq::from_raw([
0xf9f1_26e6_1ea1_65f1,
0x413e_e0eb_7bbd_2198,
0x642a_dee0_dd13_aa48,
0x3be4_75f2_d764_2bde,
]),
Fq::from_raw([
0x14d5_4237_2a7b_a0d9,
0x5019_bfd4_e042_3fa0,
0x117f_db24_20d8_ea60,
0x25ab_8aec_e953_7168,
]),
];
permute::<Fq, P128Pow5T3Gen<Fq>, 3, 2>(&mut input, &fq::MDS, &fq::ROUND_CONSTANTS);
assert_eq!(input, expected_output);
}
}
#[test]
@ -229,12 +268,12 @@ mod tests {
for tv in crate::primitives::poseidon::test_vectors::permute() {
let mut state = [
pallas::Base::from_repr(tv.initial_state[0]).unwrap(),
pallas::Base::from_repr(tv.initial_state[1]).unwrap(),
pallas::Base::from_repr(tv.initial_state[2]).unwrap(),
Fp::from_repr(tv.initial_state[0]).unwrap(),
Fp::from_repr(tv.initial_state[1]).unwrap(),
Fp::from_repr(tv.initial_state[2]).unwrap(),
];
permute::<pallas::Base, super::P128Pow5T3, 3, 2>(&mut state, &mds, &round_constants);
permute::<Fp, super::P128Pow5T3, 3, 2>(&mut state, &mds, &round_constants);
for (expected, actual) in tv.final_state.iter().zip(state.iter()) {
assert_eq!(&actual.to_repr(), expected);
@ -246,8 +285,8 @@ mod tests {
fn hash_test_vectors() {
for tv in crate::primitives::poseidon::test_vectors::hash() {
let message = [
pallas::Base::from_repr(tv.input[0]).unwrap(),
pallas::Base::from_repr(tv.input[1]).unwrap(),
Fp::from_repr(tv.input[0]).unwrap(),
Fp::from_repr(tv.input[1]).unwrap(),
];
let result = Hash::init(super::P128Pow5T3, ConstantLength).hash(message);