wip mayo: its going
This commit is contained in:
parent
1f51923832
commit
e6e39c04f0
10
Cargo.toml
10
Cargo.toml
|
@ -7,10 +7,6 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
tiny-keccak = { version = "2.0", features = ["shake"] }
|
||||
aes = { version = "0.8.2" }
|
||||
rand = { version = "0.8.5" }
|
||||
nalgebra = { version = "0.32.2", optional = true }
|
||||
|
||||
[features]
|
||||
default = ["naive"]
|
||||
naive = ["dep:nalgebra"]
|
||||
rand = "0.8.5"
|
||||
rust-crypto = "0.2.36"
|
||||
rayon = "1.8.0"
|
||||
|
|
13
src/lib.rs
13
src/lib.rs
|
@ -1,4 +1,11 @@
|
|||
#[cfg(feature = "naive")]
|
||||
pub mod naive;
|
||||
#![feature(adt_const_params)]
|
||||
#![feature(generic_arg_infer)]
|
||||
#![feature(generic_const_exprs)]
|
||||
#![feature(portable_simd)]
|
||||
|
||||
pub(crate) mod sig;
|
||||
mod math;
|
||||
mod params;
|
||||
mod sig;
|
||||
mod sym;
|
||||
|
||||
pub mod mayo;
|
||||
|
|
322
src/math.rs
Normal file
322
src/math.rs
Normal file
|
@ -0,0 +1,322 @@
|
|||
use crate::params::{o_bytes, Level};
|
||||
use std::ops::{Add, Neg};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Mat<const R: usize, const C: usize>(pub [[u8; C]; R]);
|
||||
|
||||
// TODO: Bitslicing (not u8's) (see below) (fix this so KATs verify)
|
||||
// TODO: Finish Simd optimization
|
||||
// TODO: convert these to Rayon: put loops over things into mp
|
||||
// TODO: Optimize matrix Mul: Strassen or smth
|
||||
|
||||
const MUL_LOOKUP: [[u8; 16]; 16] = [
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||
[0, 2, 4, 6, 8, 10, 12, 14, 3, 1, 7, 5, 11, 9, 15, 13],
|
||||
[0, 3, 6, 5, 12, 15, 10, 9, 11, 8, 13, 14, 7, 4, 1, 2],
|
||||
[0, 4, 8, 12, 3, 7, 11, 15, 6, 2, 14, 10, 5, 1, 13, 9],
|
||||
[0, 5, 10, 15, 7, 2, 13, 8, 14, 11, 4, 1, 9, 12, 3, 6],
|
||||
[0, 6, 12, 10, 11, 13, 7, 1, 5, 3, 9, 15, 14, 8, 2, 4],
|
||||
[0, 7, 14, 9, 15, 8, 1, 6, 13, 10, 3, 4, 2, 5, 12, 11],
|
||||
[0, 8, 3, 11, 6, 14, 5, 13, 12, 4, 15, 7, 10, 2, 9, 1],
|
||||
[0, 9, 1, 8, 2, 11, 3, 10, 4, 13, 5, 12, 6, 15, 7, 14],
|
||||
[0, 10, 7, 13, 14, 4, 9, 3, 15, 5, 8, 2, 1, 11, 6, 12],
|
||||
[0, 11, 5, 14, 10, 1, 15, 4, 7, 12, 2, 9, 13, 6, 8, 3],
|
||||
[0, 12, 11, 7, 5, 9, 14, 2, 10, 6, 1, 13, 15, 3, 4, 8],
|
||||
[0, 13, 9, 4, 1, 12, 8, 5, 2, 15, 11, 6, 3, 14, 10, 7],
|
||||
[0, 14, 15, 1, 13, 3, 2, 12, 9, 7, 6, 8, 4, 10, 11, 5],
|
||||
[0, 15, 13, 2, 9, 6, 4, 11, 1, 14, 12, 3, 8, 7, 5, 10],
|
||||
];
|
||||
|
||||
#[inline]
|
||||
pub fn mul(f16_1: u8, f16_2: u8) -> u8 {
|
||||
MUL_LOOKUP[f16_1 as usize][f16_2 as usize]
|
||||
}
|
||||
|
||||
pub fn upper<const N: usize>(mat: Mat<N, N>) -> Mat<N, N> {
|
||||
let mut up = Mat([[0; N]; N]);
|
||||
for i in 0..N {
|
||||
for j in (i + 1)..N {
|
||||
up.write(i, j, mat.access(i, j) + mat.access(j, i));
|
||||
}
|
||||
for i in 0..N {
|
||||
up.write(i, i, mat.access(i, i));
|
||||
}
|
||||
}
|
||||
up
|
||||
}
|
||||
|
||||
impl<const R: usize, const C: usize> Mat<R, C> {
|
||||
#[inline]
|
||||
pub fn access(&self, i: usize, j: usize) -> u8 {
|
||||
self.0[i][j]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write(&mut self, i: usize, j: usize, v: u8) {
|
||||
self.0[i][j] = v;
|
||||
}
|
||||
|
||||
pub fn tp(&self) -> Mat<C, R> {
|
||||
let mut tp = Mat([[0; R]; C]);
|
||||
for i in 0..R {
|
||||
for j in 0..C {
|
||||
tp.write(j, i, self.access(i, j));
|
||||
}
|
||||
}
|
||||
tp
|
||||
}
|
||||
|
||||
pub fn mul_right<const N: usize>(&self, other: Mat<C, N>) -> Mat<R, N> {
|
||||
let other_tp = other.tp();
|
||||
let mut out = Mat([[0; N]; R]);
|
||||
for i in 0..R {
|
||||
for j in 0..N {
|
||||
let write = (0..C)
|
||||
.map(|k| mul(other_tp.0[j][k], self.0[i][k]))
|
||||
.fold(0, |acc, x| acc ^ x);
|
||||
out.write(i, j, write);
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
}
|
||||
|
||||
impl<const R: usize, const C: usize> Add for Mat<R, C> {
|
||||
type Output = Mat<R, C>;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
let mut out = Mat([[0; C]; R]);
|
||||
for i in 0..R {
|
||||
for j in 0..C {
|
||||
out.write(i, j, self.access(i, j) ^ rhs.access(i, j))
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
}
|
||||
|
||||
impl<const R: usize, const C: usize> Neg for Mat<R, C> {
|
||||
type Output = Mat<R, C>;
|
||||
|
||||
fn neg(self) -> Self::Output {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode_matrix<const R: usize, const C: usize, const L: Level>(bs: &[u8]) -> Mat<R, C> {
|
||||
let mut mat = Mat([[0; C]; R]);
|
||||
for i in 0..R {
|
||||
for j in 0..C {
|
||||
if (j + C * i) % 2 == 0 {
|
||||
mat.write(i, j, (bs[(j + C * i) / 2] >> 4) & 0xf);
|
||||
} else {
|
||||
mat.write(i, j, bs[(j + C * i) / 2] & 0xf);
|
||||
}
|
||||
}
|
||||
}
|
||||
mat
|
||||
}
|
||||
|
||||
pub fn decode_matrices<const R: usize, const C: usize, const M: usize, const L: Level>(
|
||||
bs: &[u8],
|
||||
num: usize,
|
||||
triangular: bool,
|
||||
) -> [Mat<R, C>; M] {
|
||||
let mut m = [Mat([[0; C]; R]); M];
|
||||
match triangular {
|
||||
true => {
|
||||
let mut ind = 0;
|
||||
for s in 0..M {
|
||||
for i in 0..R {
|
||||
for j in i..C {
|
||||
if ind % 2 == 0 {
|
||||
m[s].write(i, j, (bs[ind / 2] >> 4) & 0xf);
|
||||
} else {
|
||||
m[s].write(i, j, bs[ind / 2] & 0xf);
|
||||
}
|
||||
ind += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
false => {
|
||||
for s in 0..M {
|
||||
for i in 0..R {
|
||||
for j in 0..C {
|
||||
if (j + C * i) % 2 == 0 {
|
||||
m[s].write(i, j, (bs[(j + C * i + R * C * s) / 2] >> 4) & 0xf);
|
||||
} else {
|
||||
m[s].write(i, j, bs[(j + C * i + R * C * s) / 2] & 0xf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m
|
||||
}
|
||||
|
||||
pub fn encode_matrices<const R: usize, const C: usize, const M: usize, const L: Level>(
|
||||
bs: &[Mat<R, C>],
|
||||
triangular: bool,
|
||||
) -> Vec<u8> {
|
||||
let mut outvec = vec![];
|
||||
match triangular {
|
||||
true => {
|
||||
let mut ind = 0;
|
||||
for mat in bs {
|
||||
for i in 0..R {
|
||||
for j in i..C {
|
||||
if ind % 2 == 0 {
|
||||
outvec.push(mat.access(i, j) << 4);
|
||||
} else {
|
||||
outvec[ind / 2] |= mat.access(i, j);
|
||||
}
|
||||
ind += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
false => {
|
||||
for mat in bs {
|
||||
for i in 0..R {
|
||||
for j in 0..C {
|
||||
if (j + C * i) % 2 == 0 {
|
||||
outvec.push(mat.access(i, j) << 4);
|
||||
} else {
|
||||
outvec[(j + C * i) / 2] |= mat.access(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
outvec
|
||||
}
|
||||
|
||||
pub fn decode_vec<const R: usize>(bs: &[u8]) -> Mat<R, 1> {
|
||||
let mut ret = Mat([[0; 1]; R]);
|
||||
for i in 0..((R + 1) / 2) {
|
||||
ret.write(2 * i, 0, (bs[i] >> 4) & 0xf);
|
||||
if 2 * i + 1 < R {
|
||||
ret.write(2 * i + 1, 0, bs[i] & 0xf);
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn encode_vec<const R: usize>(vec: Mat<R, 1>) -> [u8; (R + 1) / 2] {
|
||||
let mut out = [0; (R + 1) / 2];
|
||||
for i in 0..((R + 1) / 2) {
|
||||
out[i] = vec.access(2 * i, 0) << 4;
|
||||
if 2 * i + 1 < R {
|
||||
out[i] |= vec.access(2 * i + 1, 0);
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
// pub struct FullMat<const R: usize, const C: usize>([[u8; C]; R]);
|
||||
//
|
||||
// pub const fn tpn(n: usize) -> usize {
|
||||
// (n * (n + 1)) / 2
|
||||
// }
|
||||
//
|
||||
// pub struct TMat<const N: usize>([u8; tpn(N)])
|
||||
// where
|
||||
// [(); tpn(N)]:;
|
||||
//
|
||||
// pub enum Mat<const R: usize, const C: usize>
|
||||
// where
|
||||
// [(); tpn(R)]:,
|
||||
// {
|
||||
// Full(FullMat<R, C>),
|
||||
// Upper(TMat<R>),
|
||||
// }
|
||||
//
|
||||
// pub fn upper<const N: usize>(mat: Mat<N, N>) -> Mat<N, N>
|
||||
// where
|
||||
// [(); tpn(N)]:,
|
||||
// {
|
||||
// match mat {
|
||||
// Mat::Full(f) => {
|
||||
// let mut up = Mat::Upper(TMat([0; tpn(N)]));
|
||||
// for i in 0..N {
|
||||
// for j in (i + 1)..N {
|
||||
// up.write(i, j, mat.access(i, j) + mat.access(j, i));
|
||||
// }
|
||||
// }
|
||||
// for i in 0..N {
|
||||
// up.write(i, i, mat.access(i, i));
|
||||
// }
|
||||
// up
|
||||
// }
|
||||
// Mat::Upper(u) => mat,
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl<const R: usize, const C: usize> Mat<R, C>
|
||||
// where
|
||||
// [(); tpn(R)]:,
|
||||
// [(); tpn(C)]:,
|
||||
// {
|
||||
// pub fn access(&self, i: usize, j: usize) -> u8 {
|
||||
// match self {
|
||||
// Mat::Full(f) => f.0[i][j],
|
||||
// Mat::Upper(u) => {
|
||||
// if i > j {
|
||||
// 0
|
||||
// } else {
|
||||
// u.0[tpn(R) - tpn(R - i) + j - i]
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// pub fn write(&mut self, i: usize, j: usize, v: u8) {
|
||||
// match self {
|
||||
// Mat::Full(f) => {
|
||||
// f.0[i][j] = v;
|
||||
// }
|
||||
// Mat::Upper(u) => {
|
||||
// if i <= j {
|
||||
// u.0[tpn(R) - tpn(R - i) + j - i] = v;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// pub fn tp(&self) -> Mat<C, R> {
|
||||
// todo!()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// pub fn decode_matrix<const R: usize, const C: usize, const L: Level>(bs: &[u8]) -> Mat<R, C>
|
||||
// where
|
||||
// [(); tpn(R)]:,
|
||||
// {
|
||||
// todo!()
|
||||
// })
|
||||
//
|
||||
// pub fn decode_matrices<const R: usize, const C: usize, const M: usize, const L: Level>(
|
||||
// bs: &[u8],
|
||||
// num: usize,
|
||||
// triangular: bool,
|
||||
// ) -> [Mat<R, C>; M]
|
||||
// where
|
||||
// [(); tpn(R)]:,
|
||||
// {
|
||||
// todo!()
|
||||
// }
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::math::{upper, Mat};
|
||||
#[test]
|
||||
fn test_upper() {
|
||||
let m = Mat([[0, 1, 2], [3, 4, 5], [6, 7, 8]]);
|
||||
println!("{:?}", upper(m));
|
||||
assert!(true);
|
||||
}
|
||||
}
|
271
src/mayo.rs
Normal file
271
src/mayo.rs
Normal file
|
@ -0,0 +1,271 @@
|
|||
use crate::math::{
|
||||
decode_matrices, decode_matrix, decode_vec, encode_matrices, encode_vec, upper, Mat,
|
||||
};
|
||||
use crate::params::Level;
|
||||
use crate::params::{
|
||||
digest_bytes, k, l_bytes, m, n, o, o_bytes, p1_bytes, p2_bytes, p3_bytes, pk_seed_bytes, poly,
|
||||
q, salt_bytes, v_bytes,
|
||||
};
|
||||
use crate::sig::{KeyGen, Signer, Verifier};
|
||||
use crate::sym::{aes_128_ctr, shake_256};
|
||||
use rand::rngs::OsRng;
|
||||
use rand::RngCore;
|
||||
use rayon::prelude::*;
|
||||
use tiny_keccak::{Hasher, Shake};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SigningKey<const L: Level>([u8; salt_bytes(L)], VerifyKey<L>)
|
||||
where
|
||||
[(); salt_bytes(L)]:,
|
||||
[(); pk_seed_bytes(L) + p3_bytes(L)]:;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VerifyKey<const L: Level>([u8; pk_seed_bytes(L) + p3_bytes(L)])
|
||||
where
|
||||
[(); pk_seed_bytes(L) + p3_bytes(L)]:;
|
||||
|
||||
impl<const L: Level> KeyGen for SigningKey<L>
|
||||
where
|
||||
[(); salt_bytes(L)]:,
|
||||
[(); pk_seed_bytes(L) + p3_bytes(L)]:,
|
||||
[(); o_bytes(L) + pk_seed_bytes(L)]:,
|
||||
[(); n(L) - o(L)]:,
|
||||
[(); m(L)]:,
|
||||
{
|
||||
fn gen() -> Self {
|
||||
let mut seed_sk: [u8; salt_bytes(L)] = [0; salt_bytes(L)];
|
||||
OsRng.fill_bytes(&mut seed_sk);
|
||||
|
||||
let s: [u8; o_bytes(L) + pk_seed_bytes(L)] = shake_256(vec![&seed_sk]);
|
||||
|
||||
let seed_pk = &s[0..pk_seed_bytes(L)];
|
||||
|
||||
let o_bs = &s[pk_seed_bytes(L)..(pk_seed_bytes(L) + o_bytes(L))];
|
||||
let om: Mat<{ n(L) - o(L) }, { o(L) }> =
|
||||
decode_matrix::<{ n(L) - o(L) }, { o(L) }, { L }>(o_bs);
|
||||
|
||||
let p = aes_128_ctr(seed_pk, p1_bytes(L) + p2_bytes(L));
|
||||
|
||||
let p1: [Mat<{ n(L) - o(L) }, { n(L) - o(L) }>; m(L)] =
|
||||
decode_matrices::<{ n(L) - o(L) }, { n(L) - o(L) }, { m(L) }, { L }>(
|
||||
&p[0..p1_bytes(L)],
|
||||
m(L),
|
||||
true,
|
||||
);
|
||||
let p2: [Mat<{ n(L) - o(L) }, { o(L) }>; m(L)] =
|
||||
decode_matrices::<{ n(L) - o(L) }, { o(L) }, { m(L) }, { L }>(
|
||||
&p[p1_bytes(L)..(p1_bytes(L) + p2_bytes(L))],
|
||||
m(L),
|
||||
false,
|
||||
);
|
||||
|
||||
let p3 = (0..m(L))
|
||||
.into_par_iter()
|
||||
.map(|i| upper(-om.tp().mul_right(p1[i].mul_right(om)) + (-om.tp().mul_right(p2[i]))))
|
||||
.collect::<Vec<Mat<{ o(L) }, { o(L) }>>>();
|
||||
|
||||
let p3_enc = encode_matrices::<{ o(L) }, { o(L) }, { m(L) }, { L }>(&p3, true);
|
||||
let mut out = [0; pk_seed_bytes(L) + p3_bytes(L)];
|
||||
out[..pk_seed_bytes(L)].copy_from_slice(&seed_pk[..pk_seed_bytes(L)]);
|
||||
out[pk_seed_bytes(L)..].copy_from_slice(&p3_enc);
|
||||
SigningKey(seed_sk, VerifyKey(out))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expand_sk<const L: Level>(
|
||||
csk: [u8; salt_bytes(L)],
|
||||
) -> [u8; salt_bytes(L) + o_bytes(L) + p1_bytes(L) + l_bytes(L)]
|
||||
where
|
||||
[(); salt_bytes(L)]:,
|
||||
[(); pk_seed_bytes(L) + p3_bytes(L)]:,
|
||||
[(); o_bytes(L) + pk_seed_bytes(L)]:,
|
||||
[(); n(L) - o(L)]:,
|
||||
[(); m(L)]:,
|
||||
{
|
||||
let seed_sk = csk;
|
||||
|
||||
let s: [u8; o_bytes(L) + pk_seed_bytes(L)] = shake_256(vec![&seed_sk]);
|
||||
|
||||
let seed_pk = &s[0..pk_seed_bytes(L)];
|
||||
|
||||
let o_bs = &s[pk_seed_bytes(L)..(pk_seed_bytes(L) + o_bytes(L))];
|
||||
let om: Mat<{ n(L) - o(L) }, { o(L) }> =
|
||||
decode_matrix::<{ n(L) - o(L) }, { o(L) }, { L }>(o_bs);
|
||||
|
||||
let p = aes_128_ctr(seed_pk, p1_bytes(L) + p2_bytes(L));
|
||||
|
||||
let p1: [Mat<{ n(L) - o(L) }, { n(L) - o(L) }>; m(L)] = decode_matrices::<
|
||||
{ n(L) - o(L) },
|
||||
{ n(L) - o(L) },
|
||||
{ m(L) },
|
||||
{ L },
|
||||
>(&p[0..p1_bytes(L)], m(L), true);
|
||||
|
||||
let p1_bm = encode_matrices::<{ n(L) - o(L) }, { n(L) - o(L) }, { m(L) }, { L }>(&p1, true);
|
||||
|
||||
let p2: [Mat<{ n(L) - o(L) }, { o(L) }>; m(L)] =
|
||||
decode_matrices::<{ n(L) - o(L) }, { o(L) }, { m(L) }, { L }>(
|
||||
&p[p1_bytes(L)..(p1_bytes(L) + p2_bytes(L))],
|
||||
m(L),
|
||||
false,
|
||||
);
|
||||
|
||||
let l = (0..m(L))
|
||||
.into_par_iter()
|
||||
.map(|i| (p1[i] + p1[i].tp()).mul_right(om) + p2[i])
|
||||
.collect::<Vec<Mat<{ n(L) - o(L) }, { o(L) }>>>();
|
||||
|
||||
let l_bs = encode_matrices::<{ n(L) - o(L) }, { o(L) }, { m(L) }, { L }>(&l, false);
|
||||
let mut out = [0; salt_bytes(L) + o_bytes(L) + p1_bytes(L) + l_bytes(L)];
|
||||
out[..salt_bytes(L)].copy_from_slice(&seed_sk);
|
||||
out[salt_bytes(L)..(salt_bytes(L) + o_bytes(L))].copy_from_slice(o_bs);
|
||||
out[(salt_bytes(L) + o_bytes(L))..(salt_bytes(L) + o_bytes(L) + p1_bytes(L))]
|
||||
.copy_from_slice(&p1_bm);
|
||||
out[(salt_bytes(L) + o_bytes(L) + p1_bytes(L))..].copy_from_slice(&l_bs);
|
||||
out
|
||||
}
|
||||
|
||||
impl<const L: Level> Signer<Vec<u8>> for SigningKey<L>
|
||||
where
|
||||
[(); salt_bytes(L)]:,
|
||||
[(); pk_seed_bytes(L) + p3_bytes(L)]:,
|
||||
[(); o_bytes(L) + pk_seed_bytes(L)]:,
|
||||
[(); n(L) - o(L)]:,
|
||||
[(); k(L) * n(L)]:,
|
||||
[(); m(L)]:,
|
||||
[(); m(L) / 2]:,
|
||||
[(); k(L) * v_bytes(L) + ((k(L) * o(L) + 1) / 2)]:,
|
||||
[(); salt_bytes(L) + o_bytes(L) + p1_bytes(L) + l_bytes(L)]:,
|
||||
[(); digest_bytes(L)]:,
|
||||
{
|
||||
fn sign(&self, msg: &[u8]) -> Vec<u8> {
|
||||
let esk = expand_sk(self.0);
|
||||
let seed_sk = &esk[..salt_bytes(L)];
|
||||
let om: Mat<{ n(L) - o(L) }, { o(L) }> = decode_matrix::<{ n(L) - o(L) }, { o(L) }, { L }>(
|
||||
&esk[salt_bytes(L)..(salt_bytes(L) + o_bytes(L))],
|
||||
);
|
||||
let p1: [Mat<{ n(L) - o(L) }, { n(L) - o(L) }>; m(L)] =
|
||||
decode_matrices::<{ n(L) - o(L) }, { n(L) - o(L) }, { m(L) }, { L }>(
|
||||
&esk[(salt_bytes(L) + o_bytes(L))..(salt_bytes(L) + o_bytes(L) + p1_bytes(L))],
|
||||
m(L),
|
||||
true,
|
||||
);
|
||||
let li: [Mat<{ n(L) - o(L) }, { o(L) }>; m(L)] =
|
||||
decode_matrices::<{ n(L) - o(L) }, { o(L) }, { m(L) }, { L }>(
|
||||
&esk[(salt_bytes(L) + o_bytes(L) + p1_bytes(L))..],
|
||||
m(L),
|
||||
false,
|
||||
);
|
||||
|
||||
let m_digest: [u8; digest_bytes(L)] = shake_256(vec![msg]);
|
||||
|
||||
let salt: [u8; salt_bytes(L)] = shake_256(vec![&m_digest, seed_sk]);
|
||||
|
||||
let t_bs: [u8; m(L) / 2] = shake_256(vec![&m_digest, &salt]);
|
||||
|
||||
let mut t = decode_vec::<{ m(L) }>(&t_bs);
|
||||
let v: [u8; k(L) * v_bytes(L) + ((k(L) * o(L) + 1) / 2)] =
|
||||
shake_256(vec![&m_digest, &salt, seed_sk, &[128]]);
|
||||
let mut vv: Vec<Mat<{ n(L) - o(L) }, 1>> = vec![];
|
||||
for i in 0..k(L) {
|
||||
vv.push(decode_vec::<{ n(L) - o(L) }>(
|
||||
&v[(i * v_bytes(L))..((i + 1) * v_bytes(L))],
|
||||
));
|
||||
}
|
||||
let r = decode_vec::<{ k(L) * o(L) }>(&v[(k(L) * v_bytes(L))..]);
|
||||
|
||||
let mut A = Mat([[0; { m(L) }]; { k(L) * o(L) }]);
|
||||
|
||||
let mut l = 0;
|
||||
|
||||
let mut el = Mat([[0; m(L)]; m(L)]);
|
||||
for i in 0..m(L) {
|
||||
el.write(i, i, 1);
|
||||
}
|
||||
|
||||
let mut Mi = [Mat([[0; { o(L) }]; { m(L) }]); k(L)];
|
||||
|
||||
for i in 0..k(L) {
|
||||
Mi[i] = Mat([[0; { o(L) }]; { m(L) }]);
|
||||
for j in 0..m(L) {
|
||||
Mi[i].0[j] = (vv[i].tp().mul_right(li[i])).0[0];
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0..k(L) {
|
||||
for j in (i..(k(L))).rev() {
|
||||
let mut u: Mat<{ m(L) }, 1> = Mat([[0; 1]; m(L)]);
|
||||
if j == i {
|
||||
for a in 0..m(L) {
|
||||
u.write(a, 0, vv[i].tp().mul_right(p1[a]).mul_right(vv[i]).0[0][0]);
|
||||
}
|
||||
} else {
|
||||
for a in 0..m(L) {
|
||||
u.write(
|
||||
a,
|
||||
0,
|
||||
(vv[i].tp().mul_right(p1[a]).mul_right(vv[j])
|
||||
+ vv[j].tp().mul_right(p1[a]).mul_right(vv[i]))
|
||||
.0[0][0],
|
||||
);
|
||||
}
|
||||
}
|
||||
t = t + (-el.mul_right(u));
|
||||
for z in (i * o(L))..((i + 1) * o(L)) {
|
||||
for y in 0..(m(L)) {
|
||||
A.write(y, z, A.access(y, z) + el.mul_right(Mi[j]).0[y][z]);
|
||||
}
|
||||
}
|
||||
|
||||
if i != j {
|
||||
for z in (j * o(L))..((j + 1) * o(L)) {
|
||||
for y in 0..(m(L)) {
|
||||
A.write(y, z, A.access(y, z) + el.mul_right(Mi[i]).0[y][z]);
|
||||
}
|
||||
}
|
||||
}
|
||||
l += 1;
|
||||
el = el.mul_right(E_mat(L));
|
||||
}
|
||||
}
|
||||
|
||||
let x = sample_solution(A, t, r);
|
||||
|
||||
let s = Mat([[0; k(L) * n(L)]; 1]);
|
||||
for i in 0..(k(L)) {
|
||||
s.0[0][(i * n(L))..((i + 1) * n(L) - o(L))] =
|
||||
(vv[i].tp() + Mat([(om.mul_right(x)).0[(i * o(L))..((i + 1) * o(L))]; 1])).0[0];
|
||||
s.0[0][((i + 1) * n(L) - o(L))..((i + 1) * n(L))] = x.0[(i * o(L))..((i + 1) * o(L))];
|
||||
}
|
||||
|
||||
let sig = encode_vec(s.tp()).to_vec();
|
||||
|
||||
for i in salt {
|
||||
sig.push(i);
|
||||
}
|
||||
|
||||
return sig;
|
||||
}
|
||||
}
|
||||
|
||||
impl<const L: Level> Verifier<Vec<u8>> for VerifyKey<L>
|
||||
where
|
||||
[(); pk_seed_bytes(L) + p3_bytes(L)]:,
|
||||
{
|
||||
fn verify(&self, sig: &Vec<u8>, msg: &[u8]) -> bool {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::SigningKey;
|
||||
use crate::params::Level;
|
||||
use crate::sig::KeyGen;
|
||||
|
||||
#[test]
|
||||
fn test_gen() {
|
||||
let s: SigningKey<{ Level::MAYO1 }> = SigningKey::gen();
|
||||
println!("{:?}", s);
|
||||
}
|
||||
}
|
104
src/params.rs
Normal file
104
src/params.rs
Normal file
|
@ -0,0 +1,104 @@
|
|||
use std::marker::ConstParamTy;
|
||||
|
||||
#[derive(ConstParamTy, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum Level {
|
||||
MAYO1,
|
||||
MAYO2,
|
||||
MAYO3,
|
||||
MAYO5,
|
||||
}
|
||||
|
||||
pub const fn n(level: Level) -> usize {
|
||||
match level {
|
||||
Level::MAYO1 => 66,
|
||||
Level::MAYO2 => 78,
|
||||
Level::MAYO3 => 99,
|
||||
Level::MAYO5 => 133,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn m(level: Level) -> usize {
|
||||
match level {
|
||||
Level::MAYO1 => 64,
|
||||
Level::MAYO2 => 64,
|
||||
Level::MAYO3 => 99,
|
||||
Level::MAYO5 => 128,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn o(level: Level) -> usize {
|
||||
match level {
|
||||
Level::MAYO1 => 8,
|
||||
Level::MAYO2 => 18,
|
||||
Level::MAYO3 => 10,
|
||||
Level::MAYO5 => 12,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn k(level: Level) -> usize {
|
||||
match level {
|
||||
Level::MAYO1 => 9,
|
||||
Level::MAYO2 => 4,
|
||||
Level::MAYO3 => 11,
|
||||
Level::MAYO5 => 12,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn q(level: Level) -> usize {
|
||||
16
|
||||
}
|
||||
|
||||
pub const fn salt_bytes(level: Level) -> usize {
|
||||
match level {
|
||||
Level::MAYO1 => 24,
|
||||
Level::MAYO2 => 24,
|
||||
Level::MAYO3 => 32,
|
||||
Level::MAYO5 => 40,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn digest_bytes(level: Level) -> usize {
|
||||
match level {
|
||||
Level::MAYO1 => 32,
|
||||
Level::MAYO2 => 32,
|
||||
Level::MAYO3 => 48,
|
||||
Level::MAYO5 => 64,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn pk_seed_bytes(_level: Level) -> usize {
|
||||
16
|
||||
}
|
||||
|
||||
pub const fn poly(level: Level) -> usize {
|
||||
match level {
|
||||
Level::MAYO1 => 64,
|
||||
Level::MAYO2 => 64,
|
||||
Level::MAYO3 => 64,
|
||||
Level::MAYO5 => 128,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn v_bytes(level: Level) -> usize {
|
||||
(n(level) - o(level) + 1) / 2
|
||||
}
|
||||
|
||||
pub const fn o_bytes(level: Level) -> usize {
|
||||
(((n(level) - o(level)) * o(level)) + 1) / 2
|
||||
}
|
||||
|
||||
pub const fn p1_bytes(level: Level) -> usize {
|
||||
m(level) * ((n(level) - o(level) + 1) * (n(level) - o(level))) / 2
|
||||
}
|
||||
|
||||
pub const fn p2_bytes(level: Level) -> usize {
|
||||
m(level) * (n(level) - o(level)) * o(level) / 2
|
||||
}
|
||||
|
||||
pub const fn p3_bytes(level: Level) -> usize {
|
||||
m(level) * (o(level) + 1) * (o(level)) / 4
|
||||
}
|
||||
|
||||
pub const fn l_bytes(level: Level) -> usize {
|
||||
m(level) * (n(level) - o(level)) * o(level) / 2
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
use rand::RngCore;
|
||||
|
||||
pub trait KeyGen<'a, P> {
|
||||
fn gen(params: P, rand: &'a mut dyn RngCore) -> Self;
|
||||
pub trait KeyGen {
|
||||
fn gen() -> Self;
|
||||
}
|
||||
|
||||
pub trait Signer<S> {
|
||||
|
|
25
src/sym.rs
Normal file
25
src/sym.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
use crypto::aes::{self, KeySize};
|
||||
use tiny_keccak::{Hasher, Shake};
|
||||
|
||||
pub fn aes_128_ctr(seed: &[u8], l: usize) -> Vec<u8> {
|
||||
let mut nonce = [0u8; 16];
|
||||
let mut cipher = aes::ctr(KeySize::KeySize128, &seed, &nonce);
|
||||
let enc = vec![0u8; l];
|
||||
let mut out = vec![0u8; l];
|
||||
cipher.process(&enc, &mut out[..]);
|
||||
out
|
||||
}
|
||||
|
||||
pub fn shake_256<const S: usize>(inputs: Vec<&[u8]>) -> [u8; S] {
|
||||
let mut shake = Shake::v256();
|
||||
|
||||
for inp in inputs {
|
||||
shake.update(inp);
|
||||
}
|
||||
|
||||
let mut out: [u8; S] = [0; S];
|
||||
|
||||
shake.finalize(&mut out);
|
||||
|
||||
out
|
||||
}
|
Loading…
Reference in New Issue
Block a user