diff --git a/Cargo.toml b/Cargo.toml index 2952118..e67e085 100644 --- a/Cargo.toml +++ b/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" diff --git a/src/lib.rs b/src/lib.rs index 837b606..5e011eb 100644 --- a/src/lib.rs +++ b/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; diff --git a/src/math.rs b/src/math.rs new file mode 100644 index 0000000..b63bfe0 --- /dev/null +++ b/src/math.rs @@ -0,0 +1,322 @@ +use crate::params::{o_bytes, Level}; +use std::ops::{Add, Neg}; + +#[derive(Debug, Clone, Copy)] +pub struct Mat(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(mat: Mat) -> Mat { + 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 Mat { + #[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 { + 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(&self, other: Mat) -> Mat { + 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 Add for Mat { + type Output = Mat; + + 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 Neg for Mat { + type Output = Mat; + + fn neg(self) -> Self::Output { + self + } +} + +pub fn decode_matrix(bs: &[u8]) -> Mat { + 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( + bs: &[u8], + num: usize, + triangular: bool, +) -> [Mat; 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( + bs: &[Mat], + triangular: bool, +) -> Vec { + 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(bs: &[u8]) -> Mat { + 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(vec: Mat) -> [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([[u8; C]; R]); +// +// pub const fn tpn(n: usize) -> usize { +// (n * (n + 1)) / 2 +// } +// +// pub struct TMat([u8; tpn(N)]) +// where +// [(); tpn(N)]:; +// +// pub enum Mat +// where +// [(); tpn(R)]:, +// { +// Full(FullMat), +// Upper(TMat), +// } +// +// pub fn upper(mat: Mat) -> Mat +// 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 Mat +// 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 { +// todo!() +// } +// } +// +// pub fn decode_matrix(bs: &[u8]) -> Mat +// where +// [(); tpn(R)]:, +// { +// todo!() +// }) +// +// pub fn decode_matrices( +// bs: &[u8], +// num: usize, +// triangular: bool, +// ) -> [Mat; 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); + } +} diff --git a/src/mayo.rs b/src/mayo.rs new file mode 100644 index 0000000..a7bc485 --- /dev/null +++ b/src/mayo.rs @@ -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([u8; salt_bytes(L)], VerifyKey) +where + [(); salt_bytes(L)]:, + [(); pk_seed_bytes(L) + p3_bytes(L)]:; + +#[derive(Debug)] +pub struct VerifyKey([u8; pk_seed_bytes(L) + p3_bytes(L)]) +where + [(); pk_seed_bytes(L) + p3_bytes(L)]:; + +impl KeyGen for SigningKey +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::>>(); + + 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( + 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::>>(); + + 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 Signer> for SigningKey +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 { + 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> = 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 Verifier> for VerifyKey +where + [(); pk_seed_bytes(L) + p3_bytes(L)]:, +{ + fn verify(&self, sig: &Vec, 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); + } +} diff --git a/src/params.rs b/src/params.rs new file mode 100644 index 0000000..3326b7c --- /dev/null +++ b/src/params.rs @@ -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 +} diff --git a/src/sig.rs b/src/sig.rs index 06165cd..9000103 100644 --- a/src/sig.rs +++ b/src/sig.rs @@ -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 { diff --git a/src/sym.rs b/src/sym.rs new file mode 100644 index 0000000..1317809 --- /dev/null +++ b/src/sym.rs @@ -0,0 +1,25 @@ +use crypto::aes::{self, KeySize}; +use tiny_keccak::{Hasher, Shake}; + +pub fn aes_128_ctr(seed: &[u8], l: usize) -> Vec { + 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(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 +}