Skip to content

Commit

Permalink
init run
Browse files Browse the repository at this point in the history
  • Loading branch information
eschorn1 committed Oct 27, 2023
1 parent f529a55 commit de9203e
Show file tree
Hide file tree
Showing 10 changed files with 199 additions and 135 deletions.
66 changes: 33 additions & 33 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ jobs:
rust:
- 1.72.0 # MSRV
- stable
target:
- thumbv7em-none-eabi
- wasm32-unknown-unknown
#target:
# - thumbv7em-none-eabi
# - wasm32-unknown-unknown
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
targets: ${{ matrix.target }}
#targets: ${{ matrix.target }}
- run: cargo build --target ${{ matrix.target }} --release

#benches:
Expand Down Expand Up @@ -76,38 +76,38 @@ jobs:
- run: cargo check --target ${{ matrix.target }} --all-features
- run: cargo test --release --target ${{ matrix.target }}

cross:
strategy:
matrix:
include:
# ARM32
- target: armv7-unknown-linux-gnueabihf
rust: 1.72.0 # MSRV (cross)
- target: armv7-unknown-linux-gnueabihf
rust: stable
#cross:
# strategy:
# matrix:
# include:
# # ARM32
# - target: armv7-unknown-linux-gnueabihf
# rust: 1.72.0 # MSRV (cross)
# - target: armv7-unknown-linux-gnueabihf
# rust: stable

# ARM64
- target: aarch64-unknown-linux-gnu
rust: 1.72.0 # MSRV (cross)
- target: aarch64-unknown-linux-gnu
rust: stable
# # ARM64
# - target: aarch64-unknown-linux-gnu
# rust: 1.72.0 # MSRV (cross)
# - target: aarch64-unknown-linux-gnu
# rust: stable

# PPC32
- target: powerpc-unknown-linux-gnu
rust: 1.72.0 # MSRV (cross)
- target: powerpc-unknown-linux-gnu
rust: stable
# # PPC32
# - target: powerpc-unknown-linux-gnu
# rust: 1.72.0 # MSRV (cross)
# - target: powerpc-unknown-linux-gnu
# rust: stable

runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ${{ matrix.deps }}
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
targets: ${{ matrix.target }}
- uses: RustCrypto/actions/cross-install@master
- run: cross test --release --target ${{ matrix.target }} --all-features
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - run: ${{ matrix.deps }}
# - uses: dtolnay/rust-toolchain@master
# with:
# toolchain: ${{ matrix.rust }}
# targets: ${{ matrix.target }}
# - uses: RustCrypto/actions/cross-install@master
# - run: cross test --release --target ${{ matrix.target }} --all-features

doc:
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ let alice_ct_bytes = bob_ct_bytes;
let alice_ct = ml_kem_512::new_ct(alice_ct_bytes);
let alice_ssk_bytes = alice_dk.decaps(&alice_ct);

// Alice and Bob will have the same secret key
// Alice and Bob will now have the same secret key
assert_eq!(bob_ssk_bytes, alice_ssk_bytes);
~~~

Expand Down
10 changes: 4 additions & 6 deletions src/byte_fns.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
//use std::convert::TryFrom;

use crate::{k_pke::Z256, Q};

/// Algorithm 2 `BitsToBytes(b)` on page 17
/// Algorithm 2 `BitsToBytes(b)` on page 17.
/// Converts a bit string (of length a multiple of eight) into an array of bytes.
pub fn bits_to_bytes(bit_array_b: &[u8], byte_array_b: &mut [u8]) {
// Input: bit array b ∈ {0, 1}^{8·ℓ}
Expand All @@ -18,7 +16,7 @@ pub fn bits_to_bytes(bit_array_b: &[u8], byte_array_b: &mut [u8]) {
// 5: return B
}

/// Algorithm 3 `BytesToBits(B)` on page 18
/// Algorithm 3 `BytesToBits(B)` on page 18.
/// Performs the inverse of `BitsToBytes`, converting a byte array into a bit array.
pub fn bytes_to_bits(byte_array_b: &[u8], bit_array_b: &mut [u8]) {
// Input: byte array B ∈ B^ℓ
Expand All @@ -39,7 +37,7 @@ pub fn bytes_to_bits(byte_array_b: &[u8], bit_array_b: &mut [u8]) {
// 7: return b
}

/// Algorithm 4 `ByteEncode<d>(F)` on page 19
/// Algorithm 4 `ByteEncode<d>(F)` on page 19.
/// Encodes an array of d-bit integers into a byte array, for 1 ≤ d ≤ 12.
pub fn byte_encode<const D: usize, const D_256: usize>(integer_array_f: &[Z256; 256], byte_array_b: &mut [u8]) {
// Input: integer array F ∈ Z^256_m, where m = 2^d if d < 12 and m = q if d = 12
Expand Down Expand Up @@ -71,7 +69,7 @@ pub fn byte_encode<const D: usize, const D_256: usize>(integer_array_f: &[Z256;
// 9: return B
}

/// Algorithm 5 `ByteDecode<d>(B)` on page 19
/// Algorithm 5 `ByteDecode<d>(B)` on page 19.
/// Decodes a byte array into an array of d-bit integers, for 1 ≤ d ≤ 12.
pub fn byte_decode<const D: usize, const D_256: usize>(byte_array_b: &[u8], integer_array_f: &mut [Z256; 256]) {
// Input: byte array B ∈ B^{32d}
Expand Down
128 changes: 69 additions & 59 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,70 @@ use crate::k_pke::Z256;
use crate::ntt::multiply_ntts;
use crate::Q;

/// Function PRF on line 726 of page 16 TODO:hardcode N1 to 2
pub fn prf<const ETA1_64: usize>(s: &[u8; 32], b: u8) -> [u8; ETA1_64] {
/// Vector addition; See bottom of page 9, second row: z_hat = u_hat + v_hat
pub fn vec_add<const K: usize>(vec_a: &[[Z256; 256]; K], vec_b: &[[Z256; 256]; K]) -> [[Z256; 256]; K] {
let mut result = [[Z256(0); 256]; K];
for i in 0..vec_a.len() {
for j in 0..vec_a[i].len() {
result[i][j].set_u16(vec_a[i][j].get_u32() + vec_b[i][j].get_u32());
}
}
result
}

/// Matrix by vector multiplication; See top of page 10, first row: w_hat = A_hat mul u_hat
#[must_use]
pub fn mat_vec_mul<const K: usize>(mat_a: &[[[Z256; 256]; K]; K], vec_b: &[[Z256; 256]; K]) -> [[Z256; 256]; K] {
let mut result = [[Z256(0); 256]; K];
for (i, result_ref) in result.iter_mut().enumerate() {
for j in 0..K {
let tmp = multiply_ntts(&mat_a[i][j], &vec_b[j]);
for k in 0..tmp.len() {
result_ref[k].set_u16(result_ref[k].get_u32() + tmp[k].get_u32());
}
}
}
result
}

/// Matrix transpose by vector multiplication; See top of page 10, second row: y_hat = A_hatT mul u_hat
pub fn mat_t_vec_mul<const K: usize>(mat_a: &[[[Z256; 256]; K]; K], vec_b: &[[Z256; 256]; K]) -> [[Z256; 256]; K] {
let mut result = [[Z256(0); 256]; K];
for (i, result_ref) in result.iter_mut().enumerate() {
for j in 0..K {
let tmp = multiply_ntts(&mat_a[j][i], &vec_b[j]); // Note i and j are reversed
for k in 0..tmp.len() {
result_ref[k].set_u16(result_ref[k].get_u32() + tmp[k].get_u32());
}
}
}
result
}

/// Vector dot product; See top of page 10, third row: z_dat = u_hatT mul v_hat
pub fn dot_t_prod<const K: usize>(vec_a: &[[Z256; 256]; K], vec_b: &[[Z256; 256]; K]) -> [Z256; 256] {
let mut result = [Z256(0); 256];
for j in 0..vec_a.len() {
let tmp = multiply_ntts(&vec_a[j], &vec_b[j]);
for k in 0..vec_a[j].len() {
result[k].set_u16(result[k].get_u32() + tmp[k].get_u32());
}
}
result
}

/// Function PRF on page 16 (4.1).
pub fn prf<const ETA_64: usize>(s: &[u8; 32], b: u8) -> [u8; ETA_64] {
let mut hasher = Shake256::default();
hasher.update(s);
hasher.update(&[b]);
let mut reader = hasher.finalize_xof();
let mut result = [0u8; ETA1_64];
let mut result = [0u8; ETA_64];
reader.read(&mut result);
result
}

/// XOF
/// Function XOF on page 16 (4.2).
pub fn xof(rho: &[u8; 32], i: u8, j: u8) -> impl XofReader {
let mut hasher = Shake128::default();
hasher.update(rho);
Expand All @@ -26,7 +78,7 @@ pub fn xof(rho: &[u8; 32], i: u8, j: u8) -> impl XofReader {
hasher.finalize_xof()
}

/// Function G from line 746 on page 17
/// Function G on page 17 (4.4).
pub(crate) fn g(bytes: &[u8]) -> ([u8; 32], [u8; 32]) {
let mut hasher = Sha3_512::new();
Digest::update(&mut hasher, bytes);
Expand All @@ -38,15 +90,17 @@ pub(crate) fn g(bytes: &[u8]) -> ([u8; 32], [u8; 32]) {
(a, b)
}

/// Function H from line 746 on page 17
/// Function H on page 17 (4.3).
#[must_use]
pub fn h(bytes: &[u8]) -> [u8; 32] {
let mut hasher = Sha3_256::new();
Digest::update(&mut hasher, bytes);
let digest = hasher.finalize();
digest.into()
}

/// Function J from line 746 on page 17
/// Function J n page 17 (4.4).
#[must_use]
pub fn j(bytes: &[u8], int: u8) -> [u8; 32] {
debug_assert_eq!(int, 32);
let mut hasher = Shake256::default();
Expand All @@ -57,13 +111,15 @@ pub fn j(bytes: &[u8], int: u8) -> [u8; 32] {
result
}

/// BitRev7(i) -- an unnumbered algorithm -- reverse lower 7 bits
/// BitRev7(i) from page 21 line 839-840.
/// Returns the integer represented by bit-reversing the unsigned 7-bit value that
/// corresponds to the input integer i ∈ {0, . . . , 127}.
#[must_use]
pub fn bit_rev_7(a: u8) -> u8 {
((a >> 6) & 1) | ((a >> 4) & 2) | ((a >> 2) & 4) | (a & 8) | ((a << 2) & 16) | ((a << 4) & 32) | ((a << 6) & 64)
}

/// HAC Algorithm 14.76 Right-to-left binary exponentiation
/// HAC Algorithm 14.76 Right-to-left binary exponentiation mod Q.
pub fn pow_mod_q(g: u32, e: u8) -> u32 {
let mut result = 1;
let mut s = g;
Expand All @@ -80,64 +136,18 @@ pub fn pow_mod_q(g: u32, e: u8) -> u32 {
result
}

#[allow(dead_code)]
/// Compress<d> from page 18 (4.5).
/// x → ⌈(2^d/q) · x⌋
pub fn compress<const D: usize>(inout: &mut [Z256]) {
for x_ref in inout.iter_mut() {
x_ref.0 = ((x_ref.0 as u32) * (2u32.pow(D as u32) / Q)) as u16;
}
}

/// Decompress<d> from page 18 (4.6).
/// y → ⌈(q/2^d) · y⌋ .
pub fn decompress<const D: usize>(inout: &mut [Z256]) {
for y_ref in inout.iter_mut() {
y_ref.0 = ((y_ref.0 as u32) * (Q / 2u32.pow(D as u32))) as u16;
}
}

// See page 10 just above line 531 -- defition of w_hat = A_hat o u_hat
pub fn mat_mul<const K: usize>(mat_a: &[[[Z256; 256]; K]; K], vec_b: &[[Z256; 256]; K]) -> [[Z256; 256]; K] {
let mut result = [[Z256(0); 256]; K];
for (i, result_ref) in result.iter_mut().enumerate() {
for j in 0..K {
let tmp = multiply_ntts(&mat_a[i][j], &vec_b[j]);
for k in 0..tmp.len() {
result_ref[k].set_u16(result_ref[k].get_u32() + tmp[k].get_u32());
}
}
}
result
}

pub fn vec_add<const K: usize>(vec_a: &[[Z256; 256]; K], vec_b: &[[Z256; 256]; K]) -> [[Z256; 256]; K] {
let mut result = [[Z256(0); 256]; K];
for i in 0..vec_a.len() {
for j in 0..vec_a[i].len() {
result[i][j].set_u16(vec_a[i][j].get_u32() + vec_b[i][j].get_u32());
}
}
result
}

// See transpose page 10 just above line 531 -- defition of y_hat = A_hat^T o u_hat
pub fn mat_t_mul<const K: usize>(mat_a: &[[[Z256; 256]; K]; K], vec_b: &[[Z256; 256]; K]) -> [[Z256; 256]; K] {
let mut result = [[Z256(0); 256]; K];
for (i, result_ref) in result.iter_mut().enumerate() {
for j in 0..K {
let tmp = multiply_ntts(&mat_a[j][i], &vec_b[j]); // Note i and j are reversed
for k in 0..tmp.len() {
result_ref[k].set_u16(result_ref[k].get_u32() + tmp[k].get_u32());
}
}
}
result
}

pub fn dot_t_prod<const K: usize>(vec_a: &[[Z256; 256]; K], vec_b: &[[Z256; 256]; K]) -> [Z256; 256] {
let mut result = [Z256(0); 256];
for j in 0..vec_a.len() {
let tmp = multiply_ntts(&vec_a[j], &vec_b[j]);
for k in 0..vec_a[j].len() {
result[k].set_u16(result[k].get_u32() + tmp[k].get_u32());
}
}
result
}
16 changes: 8 additions & 8 deletions src/k_pke.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use rand::random;

use crate::byte_fns::{byte_decode, byte_encode};
use crate::helpers::{compress, decompress, dot_t_prod, g, mat_mul, mat_t_mul, prf, vec_add, xof};
use crate::helpers::{compress, decompress, dot_t_prod, g, mat_t_vec_mul, mat_vec_mul, prf, vec_add, xof};
use crate::ntt::{ntt, ntt_inv};
use crate::Q;
use crate::sampling::{sample_ntt, sample_poly_cbd};
Expand Down Expand Up @@ -31,7 +31,7 @@ impl Z256 {
}
}

/// AAlgorithm 12 K-PKE.KeyGen() on page 26
/// Algorithm 12 `K-PKE.KeyGen()` on page 26.
/// Generates an encryption key and a corresponding decryption key.
pub fn k_pke_key_gen<const K: usize, const ETA1: usize, const ETA1_64: usize, const ETA1_512: usize>(
ek_pke: &mut [u8], dk_pke: &mut [u8],
Expand Down Expand Up @@ -83,7 +83,7 @@ pub fn k_pke_key_gen<const K: usize, const ETA1: usize, const ETA1_64: usize, co
}

// 19: t̂ ← Â ◦ ŝ + ê
let t_hat = vec_add(&mat_mul(&a_hat, &s_hat), &e_hat);
let t_hat = vec_add(&mat_vec_mul(&a_hat, &s_hat), &e_hat);

// 20: ek_{PKE} ← ByteEncode12(t̂)∥ρ ▷ ByteEncode12 is run k times; include seed for Â
for i in 0..K {
Expand All @@ -98,7 +98,7 @@ pub fn k_pke_key_gen<const K: usize, const ETA1: usize, const ETA1_64: usize, co
// 22: return (ekPKE , dkPKE )
}

/// Algorithm 13 `K-PKE.Encrypt(ekPKE , m, r)` on page 27
/// Algorithm 13 `K-PKE.Encrypt(ekPKE , m, r)` on page 27.
/// Uses the encryption key to encrypt a plaintext message using the randomness r.
pub(crate) fn k_pke_encrypt<
const K: usize,
Expand Down Expand Up @@ -171,7 +171,7 @@ pub(crate) fn k_pke_encrypt<
r_hat[i] = ntt(&r[i]);
}
// 19: u ← NTT−1 (Â⊺ ◦ r̂) + e1
let mut u = mat_t_mul(&a_hat, &r_hat);
let mut u = mat_t_vec_mul(&a_hat, &r_hat);
for i in 0..K {
u[i] = ntt_inv(&u[i]);
}
Expand All @@ -192,11 +192,11 @@ pub(crate) fn k_pke_encrypt<
}
// 23: c2 ← ByteEncode_{dv}(Compress_{dv}(v))
compress::<DV>(&mut v);
byte_encode::<DV, DV_256>(&v, &mut ct[K * step..(K * step + 32 * DV)]); // TODO: fix step (?)
byte_encode::<DV, DV_256>(&v, &mut ct[K * step..(K * step + 32 * DV)]); // TODO: fix step (?)
// 24: return c ← (c1 ∥ c2 )
}

/// Algorithm 14 K-PKE.Decrypt(dkPKE, c) on page 28
/// Algorithm 14 `K-PKE.Decrypt(dkPKE, c)` on page 28.
/// Uses the decryption key to decrypt a ciphertext.
pub(crate) fn k_pke_decrypt<
const K: usize,
Expand Down Expand Up @@ -234,7 +234,7 @@ pub(crate) fn k_pke_decrypt<
// 6: w ← v − NTT−1 (ŝ⊺ ◦ NTT(u)) ▷ NTT−1 and NTT invoked k times
let mut w = [Z256(0); 256];
for i in 0..K {
let xx = mat_t_mul(&[[s_hat]], &[ntt(&u[i])]); // TODO: UNLIKELY TO BE CORRECT
let xx = mat_t_vec_mul(&[[s_hat]], &[ntt(&u[i])]); // TODO: UNLIKELY TO BE CORRECT
let yy = ntt_inv(&xx[0]);
for i in 0..256 {
w[i].set_u16((Q + v[i].get_u32() - yy[i].get_u32()) % Q);
Expand Down
Loading

0 comments on commit de9203e

Please sign in to comment.