push online
This commit is contained in:
commit
955b8c396c
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/target
|
290
Cargo.lock
generated
Normal file
290
Cargo.lock
generated
Normal file
|
@ -0,0 +1,290 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"memoffset",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crunchy"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fuchsia-cprng"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gcc"
|
||||||
|
version = "0.3.55"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.150"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mayo"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"rand 0.8.5",
|
||||||
|
"rayon",
|
||||||
|
"rust-crypto",
|
||||||
|
"tiny-keccak",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.3.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand 0.4.6",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
|
||||||
|
dependencies = [
|
||||||
|
"fuchsia-cprng",
|
||||||
|
"libc",
|
||||||
|
"rand_core 0.3.1",
|
||||||
|
"rdrand",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.4.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rdrand"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.3.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust-crypto"
|
||||||
|
version = "0.2.36"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
|
||||||
|
dependencies = [
|
||||||
|
"gcc",
|
||||||
|
"libc",
|
||||||
|
"rand 0.3.23",
|
||||||
|
"rustc-serialize",
|
||||||
|
"time",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-serialize"
|
||||||
|
version = "0.3.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fe834bc780604f4674073badbad26d7219cadfb4a2275802db12cbae17498401"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time"
|
||||||
|
version = "0.1.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"wasi 0.10.0+wasi-snapshot-preview1",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tiny-keccak"
|
||||||
|
version = "2.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
|
||||||
|
dependencies = [
|
||||||
|
"crunchy",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.10.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
12
Cargo.toml
Normal file
12
Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "mayo"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tiny-keccak = { version = "2.0", features = ["shake"] }
|
||||||
|
rand = "0.8.5"
|
||||||
|
rust-crypto = "0.2.36"
|
||||||
|
rayon = "1.8.0"
|
11
src/lib.rs
Normal file
11
src/lib.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#![feature(adt_const_params)]
|
||||||
|
#![feature(generic_arg_infer)]
|
||||||
|
#![feature(generic_const_exprs)]
|
||||||
|
#![feature(portable_simd)]
|
||||||
|
|
||||||
|
mod math;
|
||||||
|
mod params;
|
||||||
|
mod sig;
|
||||||
|
mod sym;
|
||||||
|
|
||||||
|
pub mod mayo;
|
330
src/math.rs
Normal file
330
src/math.rs
Normal file
|
@ -0,0 +1,330 @@
|
||||||
|
use crate::params::{k, m, n, o, 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 fn sample_solution<const L: Level>(
|
||||||
|
mat: Mat<{ m(L) }, { k(L) * o(L) }>,
|
||||||
|
y: Mat<{ m(L) }, 1>,
|
||||||
|
r: Mat<{ k(L) * o(L) }, 1>,
|
||||||
|
) -> Mat<{ n(L) }, 1> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
278
src/mayo.rs
Normal file
278
src/mayo.rs
Normal file
|
@ -0,0 +1,278 @@
|
||||||
|
use crate::math::{
|
||||||
|
decode_matrices, decode_matrix, decode_vec, encode_matrices, encode_vec, sample_solution,
|
||||||
|
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,
|
||||||
|
polymat, 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::*;
|
||||||
|
|
||||||
|
#[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) * n(L) + 1) / 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(Mat(polymat()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let x = sample_solution(A.tp(), t, r).tp();
|
||||||
|
|
||||||
|
let mut s = Mat([[0; k(L) * n(L)]; 1]);
|
||||||
|
for i in 0..(k(L)) {
|
||||||
|
let x_inner = &x.0[0][(i * o(L))..((i + 1) * o(L))];
|
||||||
|
let mut xi = [0; o(L)];
|
||||||
|
for i in 0..o(L) {
|
||||||
|
xi[i] = x_inner[i];
|
||||||
|
}
|
||||||
|
s.0[0][(i * n(L))..((i + 1) * n(L) - o(L))]
|
||||||
|
.copy_from_slice(&(vv[i] + (om.mul_right(Mat([xi; 1]).tp()))).0[0]);
|
||||||
|
s.0[0][((i + 1) * n(L) - o(L))..((i + 1) * n(L))]
|
||||||
|
.copy_from_slice(&x.0[0][(i * o(L))..((i + 1) * o(L))]);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut sig = encode_vec::<{ k(L) * n(L) }>(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);
|
||||||
|
}
|
||||||
|
}
|
52
src/naive/mod.rs
Normal file
52
src/naive/mod.rs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
use crate::sig::KeyGen;
|
||||||
|
use aes::Aes128;
|
||||||
|
use rand::RngCore;
|
||||||
|
use tiny_keccak::{Shake, Xof};
|
||||||
|
|
||||||
|
pub struct SigParams {
|
||||||
|
m: u16,
|
||||||
|
n: u16,
|
||||||
|
o: u16,
|
||||||
|
k: u16,
|
||||||
|
salt_bytes: u8,
|
||||||
|
digest_bytes: u8,
|
||||||
|
pk_seed_bytes: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
// sk_seed_bytes = salt_bytes
|
||||||
|
// R_bytes = salt_bytes
|
||||||
|
// O_bytes = ceil((n - o)(o)/2)
|
||||||
|
// v_bytes = ceil((n - o)/2)
|
||||||
|
// P1_bytes = m*binom((n - o + 1), 2) / 2
|
||||||
|
// P2_bytes = m * (n - o) * o / 2
|
||||||
|
// P3_bytes = m * binom((o + 1), 2) / 2
|
||||||
|
// L_bytes = m * (n - o) * o / 2
|
||||||
|
// csk_bytes = salt_bytes
|
||||||
|
// esk_bytes = salt_bytes + O_bytes + P1_bytes + L_bytes
|
||||||
|
// cpk_bytes = pk_seed_bytes + P3_bytes
|
||||||
|
// epk_bytes = P1_bytes + P2_bytes + P3_bytes
|
||||||
|
// sig_bytes = ceil(nk / 2) + salt_bytes
|
||||||
|
|
||||||
|
pub struct SigningKey {
|
||||||
|
v: VerifyKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct VerifyKey {}
|
||||||
|
|
||||||
|
impl<'a> KeyGen<'a, SigParams> for SigningKey {
|
||||||
|
fn gen(params: SigParams, rand: &'a mut dyn RngCore) -> Self {
|
||||||
|
let sk_seed_bytes = params.salt_bytes as usize;
|
||||||
|
|
||||||
|
// Pick seed_sk at random
|
||||||
|
let mut seed_sk: Vec<u8> = vec![0; sk_seed_bytes];
|
||||||
|
rand.fill_bytes(&mut seed_sk);
|
||||||
|
|
||||||
|
// Derive seed_pk and O from seed_sk
|
||||||
|
let mut shake = Shake::v256();
|
||||||
|
let O_bytes = ((((params.n - params.o) as usize) * (params.o as usize)) + 1) / 2;
|
||||||
|
let mut S = vec![0; params.pk_seed_bytes as usize + O_bytes];
|
||||||
|
shake.squeeze(&mut S);
|
||||||
|
|
||||||
|
SigningKey { v: VerifyKey {} }
|
||||||
|
}
|
||||||
|
}
|
119
src/params.rs
Normal file
119
src/params.rs
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
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 => 96,
|
||||||
|
Level::MAYO5 => 128,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn polymat<const L: Level>() -> [[u8; m(L)]; m(L)] {
|
||||||
|
match poly(L) {
|
||||||
|
64 => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
96 => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
128 => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
11
src/sig.rs
Normal file
11
src/sig.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
pub trait KeyGen {
|
||||||
|
fn gen() -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Signer<S> {
|
||||||
|
fn sign(&self, msg: &[u8]) -> S;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Verifier<S> {
|
||||||
|
fn verify(&self, sig: &S, msg: &[u8]) -> bool;
|
||||||
|
}
|
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 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