wip mayo: its going

This commit is contained in:
h 2023-05-01 16:45:53 -04:00
parent 1f51923832
commit e6e39c04f0
7 changed files with 737 additions and 14 deletions

View File

@ -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"

View File

@ -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
View 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
View 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
View 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
}

View File

@ -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
View 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
}