argyle-software / kyber Goto Github PK
View Code? Open in Web Editor NEWA rust implementation of the Kyber post-quantum KEM
Home Page: https://docs.rs/pqc_kyber/
License: Apache License 2.0
A rust implementation of the Kyber post-quantum KEM
Home Page: https://docs.rs/pqc_kyber/
License: Apache License 2.0
[Tracking issue]
There is an optimised C implementation for neon arm-v8 here: https://github.com/cothan/kyber/tree/master/neon
At the moment many of these platform specific intrinsics needed don't exist in core_arch::aarch64
so it's either build the C lib and use that or work on getting them into rust core.
In examples/ake.rs
we have this
// Alice initiates key exchange with bob
let client_send = alice.client_init(&bob_keys.public, &mut rng);
// Bob receives the request and authenticates Alice, sends
// encapsulated shared secret back
let server_send = bob.server_receive(
client_send, &alice_keys.public, &bob_keys.secret, &mut rng
)?;
To me, this assumes Alice sends an encrypted blob (client_send
) and her public key (clear text) to Bob in order for Bob to do server_receive
. But what if Alice is privacy-conscious and only wants to send her public key if its encrypted? Is this possible using the current tools in this crate?
The current implementation is flawed:
pub(crate) fn keccak_absorb(
s: &mut[u64],
mut pos: usize,
r: usize,
input: &[u8],
mut inlen: usize
) -> usize
{
let mut idx = 0usize;
while pos+inlen >= r {
for i in pos..r {
s[i/8] ^= (input[idx] as u64) << 8 * (i%8);
idx += 1;
}
inlen -= r-pos;
keccakf1600_statepermute(s);
pos = 0;
}
let new_pos = pos+inlen;
for i in pos..new_pos {
s[i/8] ^= (input[idx] as u64) << 8 * (i%8);
}
new_pos
}
Note that idx
is not incremented in the final loop.
Hello,
Sorry if I'm doing something wrong but I have some inconsistent. And if I was indeed doing wrong, I'm wondering why it would not give an error...
Let's say Bob and Alice uses Kyber in Rust and C respectively because they are purist.
Bob uses this code after the first part of Alice one (it was for convenient) :
/* Deterministic randombytes by Daniel J. Bernstein */
/* taken from SUPERCOP (https://bench.cr.yp.to) */
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "kem.h"
#include <fcntl.h>
#include <sys/stat.h>
#include "randombytes.h"
#include <string.h>
#include <errno.h>
static uint8_t* datafromhex(char *string)
{
//From https://stackoverflow.com/a/35452093
//Needs the char* and returns an already allocated array
if (string == NULL)
return NULL;
size_t slength = strlen(string);
if ((slength % 2) != 0) // must be even
return NULL;
size_t dlength = slength / 2;
uint8_t *data = malloc(dlength);
memset(data, 0, dlength);
size_t index = 0;
while (index < slength)
{
char c = string[index];
int value = 0;
if (c >= '0' && c <= '9')
value = (c - '0');
else if (c >= 'A' && c <= 'F')
value = (10 + (c - 'A'));
else if (c >= 'a' && c <= 'f')
value = (10 + (c - 'a'));
else
{
free(data);
return NULL;
}
data[(index / 2)] += value << (((index + 1) % 2) * 4);
index++;
}
return data;
}
int main(void)
{
unsigned int j;
uint8_t pk[CRYPTO_PUBLICKEYBYTES]={0};
uint8_t sk[CRYPTO_SECRETKEYBYTES]={0};
char pkhex[CRYPTO_PUBLICKEYBYTES*2+1]={0};
char skhex[CRYPTO_SECRETKEYBYTES*2+1]={0};
FILE *file;
FILE *skey;
FILE *pkey;
mode_t umode;
uint8_t ct[CRYPTO_CIPHERTEXTBYTES];
uint8_t key_a[CRYPTO_BYTES];
uint8_t key_b[CRYPTO_BYTES];
pkey = fopen("bobpublickey.pem", "r");
if (fread(pkhex, sizeof(pkhex[0]), CRYPTO_PUBLICKEYBYTES*2, pkey) != CRYPTO_PUBLICKEYBYTES*2)
{
fprintf(stderr, "Cannot extract public key.\n");
exit(EXIT_FAILURE);
}
uint8_t *result;
printf("Pkhex is %s\n",pkhex);
result=datafromhex(pkhex);
if (result==NULL) {
fprintf(stderr, "Cannot extract public key.\n");
exit(EXIT_FAILURE);
}
*pk=*result;
free(result);
fclose(pkey);
skey = fopen("bobsecretkey.pem", "r");
// if (fread(skhex, sizeof(skhex[0]), CRYPTO_SECRETKEYBYTES*2, skey) != CRYPTO_SECRETKEYBYTES*2)
if (fread(skhex, sizeof(skhex[0]), 6336, skey) != 6336)
{
fprintf(stderr, "Cannot extract secret key\n");
exit(EXIT_FAILURE);
}
printf("SKhex is : %s\n",skhex);
result=datafromhex(skhex);
if (result==NULL) {
fprintf(stderr, "Cannot decode secret key.\n");
exit(EXIT_FAILURE);
}
*sk=*result;
free(result);
fclose(skey);
// Encapsulation
crypto_kem_enc(ct, key_b, pk);
crypto_kem_dec(key_a, ct, sk);
file = fopen("sharedsecret.pem", "w");
if (file == NULL)
{
fprintf(stderr, "Cannot create file for shared secret.\n");
exit(EXIT_FAILURE);
}
for (j = 0; j < CRYPTO_BYTES; j++)
fprintf(file, "%02x", key_a[j]);
fclose(file);
file = fopen("cipher.pem", "w");
if (file == NULL)
{
fprintf(stderr, "Cannot create file for shared secret.\n");
exit(EXIT_FAILURE);
}
for (j = 0; j < CRYPTO_CIPHERTEXTBYTES; j++)
fprintf(file,"%02x", ct[j]);
fclose(file);
return 0;
}
Bob shares its key to Alice (just to test, we don't do that in real life) so she can try her Rust code :
use hex::{self, FromHexError, decode};
use pqc_kyber::*;
use rand;
use std::fs::{self, File};
use std::io::{Error, Write};
#[cfg(target_family = "unix")]
use std::os::unix::fs::PermissionsExt;
fn encodehex(data: &[u8]) -> String {
hex::encode(data)
}
fn decodehex(hex: &str) -> Result<Vec<u8>, FromHexError> {
hex::decode(hex)
}
fn main() -> Result<(), KyberError> {
let mut rng = rand::thread_rng();
let mut alice = Ake::new();
let mut bob = Ake::new();
let alice_keys = keypair(&mut rng)?;
let bob_keys = keypair(&mut rng)?;
fs::write("bobpublickey.pem",hex::encode(bob_keys.public));
fs::write("bobsecretkey.pem",hex::encode(bob_keys.secret));
fs::write("alicepublickey.pem",hex::encode(alice_keys.public));
fs::write("alicesecretkey.pem",hex::encode(alice_keys.secret));
let bobpkey = fs::read("bobpublickey.pem").unwrap();
let bobskey = fs::read("bobsecretkey.pem").unwrap();
let bobpkey: [u8;KYBER_PUBLICKEYBYTES] = bobpkey[..KYBER_PUBLICKEYBYTES].try_into().unwrap();
let bobskey: [u8;KYBER_SECRETKEYBYTES] = bobskey[..KYBER_SECRETKEYBYTES].try_into().unwrap();
//let keys_bob = keypair(&mut rng)?;
let keys_bob=Keypair {
public: bobpkey,
secret: bobskey
};
//Go to C to get the cipher to verify here.
let ciphertext=fs::read_to_string("cipher.pem").unwrap();
println!("Keys would be {}",ciphertext);
let ciphertext = decodehex(&ciphertext.trim()).unwrap();
// Alice encapsulates a shared secret using Bob's public key
//let (ciphertext, shared_secret_alice) = encapsulate(&publickey, &mut rng)?;
// Bob decapsulates a shared secret using the ciphertext sent by Alice
let shared_secret_bob = decapsulate(&ciphertext, &keys_bob.secret)?;
println!("Shared secret is {}",hex::encode(shared_secret_bob));
Ok(())
}
However at the end, the shared secret is different :
Rust : 12d6dc3e341bb2afd57d7266d898771e6c25db3d28b3d321784dffec5b6f2401
C : fe3f00af8029fdfc22c84eb4f5ece5819ca9e373c94d72430623cc9fe21728fe
I don't know if I'm doing something wrong or if the implementation has some issues but the shared secret should be the same using same keys and same cipher.
Can it encrypt custom messages to replace GPG? GPG is a program made by GNU project, it can encrypt user-inputted messages.
I noticed this crate vendors a portable bitsliced implementation of AES along with an AES-NI implementation which have been translated from the Kyber reference implementation.
Instead of that, I'd like to suggest using the aes
crate from @RustCrypto. It includes a portable "fixsliced" implementation of AES, AES-NI support, and also support for the ARMv8 Cryptography Extensions. Additionally it implements runtime CPU feature detection on both x86 and ARM to determine if the hardware implementations are available, falling back to the portable implementations if not.
Performing key-exchange with Kyber is only half the story. Using the resulting keys to perform encryption/decryption of chosen plaintexts should also be a feature of this crate.
To what extent is Kyber still in flux or is the current standard solid?
https://groups.google.com/a/list.nist.gov/g/pqc-forum/c/C0D3W1KoINY
Of course maybe there's no way to know... just curious if you know or not.
As with the 0.4 release, things are now broken. Not urgent but would be nice to update the benchmarking suite.
Incorrectly says avx2 is used by default.
Maybe a few other errors with recent changes .
tab_spaces = 2
brace_style = "AlwaysNextLine"
brace_style requires nightly but you can alias it: cargo +nightly fmt
The current API emulates the NIST code to follow along with the standardisation process. Now that is all done we can do a proper cleanup to make it more idiomatic along with general quality of life improvements. A non-comprehensive list of to-do's:
Keypair
with no visible fieldsKeypair
Keypair
struct from existing private keyKeypair
struct from 64 byte seedimpl AsRef<PublicKey>
/ impl AsRef<SecretKey>
Keypair
- impl Hash
- For public key only, non-cryptographic hashes often usedKeypair
- impl Debug
- For public key only, elide secret key from any possible loggingKeypair
- impl PartialEq
- For public key only, make note in docs that it is not constant timeKeypair
- impl Eq
Keypair
- impl Zeroize
- will require an alternative api using Pin
/ Box
along with documentation. Needs a locally instantiated SecretBuffer
by the end user to prevent return value optimisations copying everything willynilly.SharedSecret
with a concrete type, implement the same traits as for Keypair
above.Related to #59, it's preferable to get this all wrapped up into one release.
https://docs.rs/pqc_kyber/latest/src/pqc_kyber/params.rs.html There're some constants without comment e.g., KYBER_ETA1, KYBER_POLYBYTES, KYBER_POLYCOMPRESSEDBYTES, etc.
Tests on rust 1.47.0 are now failing on Mac, stable works fine.
Need to find the min version and update CI runners and the readme.
https://github.com/Argyle-Software/kyber/actions/runs/3476592582/jobs/5811960048
After running:
git clone https://github.com/Argyle-Software/kyber kyber-clippy-test && cd kyber-clippy-test && cargo clippy --features=90s-fixslice -- -W clippy::pedantic -W clippy::correctness -W clippy::perf -W clippy::style -W clippy::suspicious -W clippy::complexity -A clippy::missing_errors_doc -W clippy::nursery -A clippy::module-name-repetitions -D warnings
I get a total of 547 errors, many of which could be pretty bad (I use even harsher lints in my lib.rs
, there's a lot of warnings). Even with just cargo clippy --features=90s-fixslice
I get 45 warnings.
I do also understand that these are some pretty harsh lints, and the lints I personally use in my work are even harsher, but I can't begin to imagine the amount of subtle bugs/performance issues they've solved - and my code is a lot more idiomatic.
The majority of the issues stem from needless borrowing or redundant slicing, but as_conversions
are probably something to keep an eye on, as well as possible truncations.
I've forked the repo and started cleaning it up and making things more safe, but sadly I removed a lot of the functionality present here as it's not requried for our needs, otherwise I would've contributed my changes. I spent a few hours and got down to 140~ errors, most of which are now just as_conversions
, which I'll still be fixing and making safe as I've had an issue with an as x
conversion before that took far too long to debug, so now I use From
/Into
or their fallible counterparts.
This evidently isn't a major issue, so feel free to close it, I just wanted to bring attention to it as clippy
is great at catching subtle mistakes. It could be good to add into CI too.
$ git log --format=oneline origin/master | head -n3
1b1637ce63197fb15fbccd9b03080e0714cc2656 v0.5.0 (#70)
1e9e7c95a568b8698d2f35f6637af76c70288b66 Merge pull request #66 from francescomedina/more-kem-tests
06f58d5ee98fd4529afcf0ab1399cde89e7bfbbf Rustcrypto aes256ctr (#64)
$ git log --format=oneline v0.5.0 | head -n3
22fedf357b4603a820f7689c883f19687d0a1403 v0.5.0 Update: changelog Update: wasm binary and files Bump: deps Add: release on version tag github action Add: release checklist
1e9e7c95a568b8698d2f35f6637af76c70288b66 Merge pull request #66 from francescomedina/more-kem-tests
06f58d5ee98fd4529afcf0ab1399cde89e7bfbbf Rustcrypto aes256ctr (#64)
$ git diff origin/master v0.5.0
diff --git a/.github/workflows/cross.yml b/.github/workflows/cross.yml
index 48ab046..6d97df9 100644
--- a/.github/workflows/cross.yml
+++ b/.github/workflows/cross.yml
@@ -9,6 +9,7 @@ jobs:
strategy:
matrix:
target: [
+ aarch64-linux-android,
aarch64-unknown-linux-gnu,
aarch64-unknown-linux-musl,
arm-unknown-linux-gnueabi,
You get this, which after a dive into a rabbit hole seems caused by no_std. Commenting out the no_std directive in lib.rs
gets rid of this. Note that I am using reference
so no AVX2 errors are involved.
no_std
should maybe be a feature flag?
Compiling pqc_kyber v0.2.1
error: `#[panic_handler]` function required, but not found
error: language item required, but not found: `eh_personality`
|
= note: this can occur when a binary crate with `#![no_std]` is compiled for a target where `eh_personality` is defined in the standard library
= help: you may be able to compile for a target that doesn't need `eh_personality`, specify a target with `--target` or in `.cargo/config`
error: could not compile `pqc_kyber` due to 2 previous errors
I would really like to try and use the NPM package with the WASM implementation but am having issues
This relative module was not found:
This relative module was not found:
* ./pqc_kyber_bg.js in ./node_modules/pqc-kyber/pqc_kyber_bg.wasm
Is there an example implementation around anywhere with the wasm exports being used?
I've also tried building it myself from this repo but am met with the "js" feature issue below. Unfortunately this was my first interaction with rust and I am unable to solve.
wasm-pack build -- --features wasm
[INFO]: Checking for the Wasm target...
[INFO]: Compiling to Wasm...
Compiling proc-macro2 v1.0.27
Compiling unicode-xid v0.2.2
Compiling syn v1.0.72
Compiling wasm-bindgen-shared v0.2.74
Compiling log v0.4.14
Compiling cfg-if v1.0.0
Compiling bumpalo v3.7.0
Compiling lazy_static v1.4.0
Compiling cc v1.0.68
Compiling wasm-bindgen v0.2.74
Compiling getrandom v0.2.3
error: the wasm32-unknown-unknown target is not supported by default, you may need to enable the "js" feature. For more information see: https://docs.rs/getrandom/#webassembly-support
--> /home/altfreq/.cargo/registry/src/github.com-1ecc6299db9ec823/getrandom-0.2.3/src/lib.rs:219:9
|
219 | / compile_error!("the wasm32-unknown-unknown target is not supported by \
220 | | default, you may need to enable the \"js\" feature. \
221 | | For more information see: \
222 | | https://docs.rs/getrandom/#webassembly-support");
| |_________________________________________________________________________^
error[E0433]: failed to resolve: use of undeclared crate or module `imp`
--> /home/altfreq/.cargo/registry/src/github.com-1ecc6299db9ec823/getrandom-0.2.3/src/lib.rs:246:5
|
246 | imp::getrandom_inner(dest)
| ^^^ use of undeclared crate or module `imp`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0433`.
error: could not compile `getrandom`
To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: build failed
Error: Compiling your crate to WebAssembly failed
Caused by: failed to execute `cargo build`: exited with exit code: 101
full command: "cargo" "build" "--lib" "--release" "--target" "wasm32-unknown-unknown" "--features" "wasm"
In order to publish a version of our software on crates.io, we need all our dependencies to have a release version. Could you release a version after 8c7927e
(we need the IND-CPA primitives)?
So this is an investigative issue looking into a feature that implements memfd support for Linux and Android platforms. This can offer additional side-channel protection, though it isn't immune to kernel exploits.
Essentially returning a file descriptor instead of a keypair and then running the encapsulation/encapsulation on that is the preliminary starting point here.
Additional reading:
As far as I can tell, this repository does not have any changelog. The absence of a changelog together with the absence of tags (#24) makes it quite hard to figure out what changed between 0.2
and 0.3
.
Hello,
We are working on the hybridization of our scheme. We are using your library because it allows compiling to WASM. However, we would like to be able to use the CPA-Kyber primitives.
Could you consider making the reference
module public?
Regards,
The Kyber reference implementation has been updated to eliminate usages of division out of timing-variability concerns: pq-crystals/kyber@dda29cc
It would probably be good to do something similar, e.g.
kyber/src/reference/polyvec.rs
Line 63 in 476e22c
Apple Silicon M2 running MacOS Ventura 13.3.1, Xcode-14.3, Rust-1.69.0.
$ cargo bench --features "benchmarking kyber1024"
Downloaded tinytemplate v1.2.1
Downloaded ciborium-io v0.2.0
. . .
Compiling pqc_kyber v0.6.0 (/Users/ur20980/src/kyber-pure)
Compiling clap v3.2.24
Compiling lazy_static v1.4.0
Compiling ppv-lite86 v0.2.17
Compiling crossbeam-deque v0.8.3
Compiling rand_chacha v0.3.1
Compiling rand v0.8.5
Compiling rayon v1.7.0
Compiling plotters v0.3.4
Compiling ciborium v0.2.0
Compiling tinytemplate v1.2.1
Compiling criterion v0.4.0
Finished bench [optimized] target(s) in 12.63s
Running unittests src/lib.rs (target/release/deps/pqc_kyber-795659d6ce51cfa5)
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Running benches/api.rs (target/release/deps/api-52af575b14e196b1)
Gnuplot not found, using plotters backend
Keypair Generation time: [30.546 µs 30.712 µs 30.904 µs]
Found 2 outliers among 100 measurements (2.00%)
2 (2.00%) high mild
Benchmarking Encapsulate: Warming up for 3.0000 sthread 'main' panicked at 'index out of bounds: the len is 0 but the index is 0', src/reference/fips202.rs:27:11
stack backtrace:
0: rust_begin_unwind
at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/std/src/panicking.rs:579:5
1: core::panicking::panic_fmt
at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/core/src/panicking.rs:64:14
2: core::panicking::panic_bounds_check
at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/core/src/panicking.rs:159:5
3: pqc_kyber::reference::fips202::keccak_absorb_once
4: pqc_kyber::reference::fips202::sha3_256
5: pqc_kyber::kem::crypto_kem_enc
6: criterion::bencher::Bencher<M>::iter
7: <criterion::routine::Function<M,F,T> as criterion::routine::Routine<M,T>>::warm_up
8: criterion::routine::Routine::sample
9: criterion::analysis::common
10: criterion::benchmark_group::BenchmarkGroup<M>::bench_function
11: api::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
error: bench failed, to rerun pass `--bench api`
and
$ cargo bench --features "benchmarking kyber1024" --bench api
Finished bench [optimized] target(s) in 0.04s
Running benches/api.rs (target/release/deps/api-52af575b14e196b1)
Keypair Generation time: [31.035 µs 31.092 µs 31.146 µs]
change: [-0.9414% -0.3577% +0.2071%] (p = 0.23 > 0.05)
No change in performance detected.
Found 1 outliers among 100 measurements (1.00%)
1 (1.00%) high mild
Benchmarking Encapsulate: Warming up for 3.0000 sthread 'main' panicked at 'index out of bounds: the len is 0 but the index is 0', src/reference/fips202.rs:27:11
stack backtrace:
0: rust_begin_unwind
at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/std/src/panicking.rs:579:5
1: core::panicking::panic_fmt
at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/core/src/panicking.rs:64:14
2: core::panicking::panic_bounds_check
at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/core/src/panicking.rs:159:5
3: pqc_kyber::reference::fips202::keccak_absorb_once
4: pqc_kyber::reference::fips202::sha3_256
5: pqc_kyber::kem::crypto_kem_enc
6: criterion::bencher::Bencher<M>::iter
7: <criterion::routine::Function<M,F,T> as criterion::routine::Routine<M,T>>::warm_up
8: criterion::routine::Routine::sample
9: criterion::analysis::common
10: criterion::benchmark_group::BenchmarkGroup<M>::bench_function
11: api::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
error: bench failed, to rerun pass `--bench api`
Probably very related to #2. I just clone the master branch and run cargo build
and I get the following:
$ cargo build
Compiling pqc_kyber v0.2.1 (C:\Users\faern\src\kyber-master)
Compiling synstructure v0.12.6
The following warnings were emitted during compilation:
warning: cl : Command line warning D9024 : unrecognized source file type 'src/avx2/basemul.S', object file assumed
warning: cl : Command line warning D9027 : source file 'src/avx2/basemul.S' ignored
warning: cl : Command line warning D9024 : unrecognized source file type 'src/avx2/fq.S', object file assumed
warning: cl : Command line warning D9027 : source file 'src/avx2/fq.S' ignored
warning: cl : Command line warning D9024 : unrecognized source file type 'src/avx2/invntt.S', object file assumed
warning: cl : Command line warning D9027 : source file 'src/avx2/invntt.S' ignored
warning: cl : Command line warning D9024 : unrecognized source file type 'src/avx2/ntt.S', object file assumed
warning: cl : Command line warning D9027 : source file 'src/avx2/ntt.S' ignored
warning: cl : Command line warning D9024 : unrecognized source file type 'src/avx2/shuffle.S', object file assumed
warning: cl : Command line warning D9027 : source file 'src/avx2/shuffle.S' ignored
error: failed to run custom build command for `pqc_kyber v0.2.1 (C:\Users\faern\src\kyber-master)`
Caused by:
process didn't exit successfully: `C:\Users\faern\src\kyber-master\target\debug\build\pqc_kyber-de0e4d6bdeecf67b\build-script-build` (exit code: 1)
--- stdout
TARGET = Some("x86_64-pc-windows-msvc")
OPT_LEVEL = Some("0")
HOST = Some("x86_64-pc-windows-msvc")
CC_x86_64-pc-windows-msvc = None
CC_x86_64_pc_windows_msvc = None
HOST_CC = None
CC = None
CFLAGS_x86_64-pc-windows-msvc = None
CFLAGS_x86_64_pc_windows_msvc = None
HOST_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
CARGO_CFG_TARGET_FEATURE = Some("fxsr,sse,sse2")
DEBUG = Some("true")
running: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.29.30133\\bin\\HostX64\\x64\\cl.exe" "-nologo" "-MD" "-Z7" "-Brepro" "-I" "src/avx2/" "-W4" "-FoC:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/basemul.o" "-c" "src/avx2/basemul.S"
cargo:warning=cl : Command line warning D9024 : unrecognized source file type 'src/avx2/basemul.S', object file assumed
cargo:warning=cl : Command line warning D9027 : source file 'src/avx2/basemul.S' ignored
cl : Command line warning D9021 : no action performed
exit code: 0
running: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.29.30133\\bin\\HostX64\\x64\\cl.exe" "-nologo" "-MD" "-Z7" "-Brepro" "-I" "src/avx2/" "-W4" "-FoC:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/fq.o" "-c" "src/avx2/fq.S"
cargo:warning=cl : Command line warning D9024 : unrecognized source file type 'src/avx2/fq.S', object file assumed
cargo:warning=cl : Command line warning D9027 : source file 'src/avx2/fq.S' ignored
cl : Command line warning D9021 : no action performed
exit code: 0
running: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.29.30133\\bin\\HostX64\\x64\\cl.exe" "-nologo" "-MD" "-Z7" "-Brepro" "-I" "src/avx2/" "-W4" "-FoC:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/invntt.o" "-c" "src/avx2/invntt.S"
cargo:warning=cl : Command line warning D9024 : unrecognized source file type 'src/avx2/invntt.S', object file assumed
cargo:warning=cl : Command line warning D9027 : source file 'src/avx2/invntt.S' ignored
cl : Command line warning D9021 : no action performed
exit code: 0
running: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.29.30133\\bin\\HostX64\\x64\\cl.exe" "-nologo" "-MD" "-Z7" "-Brepro" "-I" "src/avx2/" "-W4" "-FoC:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/ntt.o" "-c" "src/avx2/ntt.S"
cargo:warning=cl : Command line warning D9024 : unrecognized source file type 'src/avx2/ntt.S', object file assumed
cargo:warning=cl : Command line warning D9027 : source file 'src/avx2/ntt.S' ignored
cl : Command line warning D9021 : no action performed
exit code: 0
running: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.29.30133\\bin\\HostX64\\x64\\cl.exe" "-nologo" "-MD" "-Z7" "-Brepro" "-I" "src/avx2/" "-W4" "-FoC:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/shuffle.o" "-c" "src/avx2/shuffle.S"
cargo:warning=cl : Command line warning D9024 : unrecognized source file type 'src/avx2/shuffle.S', object file assumed
cargo:warning=cl : Command line warning D9027 : source file 'src/avx2/shuffle.S' ignored
cl : Command line warning D9021 : no action performed
exit code: 0
AR_x86_64-pc-windows-msvc = None
AR_x86_64_pc_windows_msvc = None
HOST_AR = None
AR = None
running: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.29.30133\\bin\\HostX64\\x64\\lib.exe" "-out:C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\libpqc_kyber.a" "-nologo" "C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/basemul.o" "C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/fq.o" "C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/invntt.o" "C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/ntt.o" "C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/shuffle.o"
LINK : fatal error LNK1181: cannot open input file 'C:\Users\faern\src\kyber-master\target\debug\build\pqc_kyber-4e4cd6b4fd1f06c6\out\src\avx2\basemul.o'
exit code: 1181
--- stderr
error occurred: Command "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.29.30133\\bin\\HostX64\\x64\\lib.exe" "-out:C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\libpqc_kyber.a" "-nologo" "C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/basemul.o" "C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/fq.o" "C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/invntt.o" "C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/ntt.o" "C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/shuffle.o" with args "lib.exe" did not execute successfully (status code exit code: 1181).
warning: build failed, waiting for other jobs to finish...
It works if I build for the gnu target (x86_64-pc-windows-gnu
), but that's not the target I build my program for. It of course also works if activating the reference
feature.
Issue: When using the npm package pqc-kyber
within a react framework, the application will not complie.
Discussion: My current assumption is there is an issue with WASM dependencies when getting the react's webpack to compile the WASM.
Alternatively, WASM pack is not compiling from rust to WASM with the correct dependencies.
Some steps I have already tried:
Recommendation: I think if the collective group could look at this problem we could find a solution. React is one of the most popular front end frameworks, so if we could get this package work with react we could increase adoption.
This is the exact error I see:
Uncaught TypeError: wasm.keypair is not a function
keypair pqc_kyber_bg.js:189
App App.js:7
React 11
workLoop scheduler.development.js:266
flushWork scheduler.development.js:239
performWorkUntilDeadline scheduler.development.js:533
js scheduler.development.js:571
js scheduler.development.js:633
factory react refresh:6
Webpack 24
pqc_kyber_bg.js:189
A common and very good practice is to add git tags to the commits where a crate was published from. This makes it so much easier to find the relevant code and see code diffs between releases. I would appreciate this a lot.
./Cargo.toml:# Defaults to "kyber764" if none selected
./readme.md:See the [**features**](#features) section for different options regarding security levels and modes of operation. The default security setting is kyber764.
./readme.md:If no security level is specified then kyber764 is used by default as recommended by the authors. It is roughly equivalent to AES-196. Apart from the two security levels, all other features can be combined as needed. For example:
./src/avx2/indcpa.rs: #[cfg(not(any(feature="kyber1024", feature="kyber512", feature="90s")))] // kyber764
./src/avx2/indcpa.rs: #[cfg(not(any(feature="kyber1024", feature="kyber512", feature="90s")))] // kyber764)
./src/lib.rs://! If no security level is set then Kyber764 is used, this is roughly equivalent to AES-196. See below for setting other levels.
./tests/run_all_tests.sh:announce "Kyber764"
./tests/run_all_tests.sh:announce "Kyber764-90s"
./tests/run_all_tests.sh:announce "Reference Kyber764"
./tests/run_all_tests.sh:announce "Reference Kyber764-90s"
./tests/run_all_tests.sh:announce "Kyber764 KATs"
./tests/run_all_tests.sh:announce "Kyber764-90s KATs"
./tests/run_all_tests.sh:announce "Reference Kyber764 KATs"
./tests/run_all_tests.sh:announce "Reference Kyber764-90s KATs"
Please change those strings to 768 which is the actual standard (and which you actually implemented
Add public traits for keygen, encap and decap.
Could you provide application programming interface for PKE (public key encryption scheme)? Which is lower level and more customizable.
The intermediate values should be an enum
The current implementation of gen_matrix
, given below, is incorrect. The problem is in the case that the initial BUFLEN
=504 bytes squeezed from the XOF are not enough. Then only a single extra block is squeezed from the XOF, but the whole buffer is used for rejection sampling.
Compare your Rust implementation:
fn gen_matrix(a: &mut [Polyvec], seed: &[u8], transposed: bool)
{
let mut ctr;
// 530 is expected number of required bytes
const GEN_MATRIX_NBLOCKS: usize =
(12*KYBER_N/8*(1 << 12)/KYBER_Q + XOF_BLOCKBYTES)/XOF_BLOCKBYTES;
const BUFLEN: usize = GEN_MATRIX_NBLOCKS*XOF_BLOCKBYTES;
let mut buf = [0u8; BUFLEN+2];
let mut off: usize;
let mut state = XofState::new();
for i in 0..KYBER_K {
for j in 0..KYBER_K {
if transposed {
xof_absorb(&mut state, seed, i as u8, j as u8);
}
else {
xof_absorb(&mut state, seed, j as u8, i as u8);
}
xof_squeezeblocks(&mut buf, GEN_MATRIX_NBLOCKS, &mut state);
ctr = rej_uniform(&mut a[i].vec[j].coeffs, KYBER_N, &buf, BUFLEN);
while ctr < KYBER_N
{
off = BUFLEN % 3;
for k in 0..off {
buf[k] = buf[BUFLEN - off + k];
}
xof_squeezeblocks(&mut buf[off..], 1, &mut state);
ctr += rej_uniform(&mut a[i].vec[j].coeffs[ctr..], KYBER_N - ctr, &buf, BUFLEN);
}
}
}
}
To the reference implementation where buflen
is correctly adjusted:
void gen_matrix(polyvec *a, const uint8_t seed[KYBER_SYMBYTES], int transposed)
{
unsigned int ctr, i, j, k;
unsigned int buflen, off;
uint8_t buf[GEN_MATRIX_NBLOCKS*XOF_BLOCKBYTES+2];
xof_state state;
for(i=0;i<KYBER_K;i++) {
for(j=0;j<KYBER_K;j++) {
if(transposed)
xof_absorb(&state, seed, i, j);
else
xof_absorb(&state, seed, j, i);
xof_squeezeblocks(buf, GEN_MATRIX_NBLOCKS, &state);
buflen = GEN_MATRIX_NBLOCKS*XOF_BLOCKBYTES;
ctr = rej_uniform(a[i].vec[j].coeffs, KYBER_N, buf, buflen);
while(ctr < KYBER_N) {
off = buflen % 3;
for(k = 0; k < off; k++)
buf[k] = buf[buflen - off + k];
xof_squeezeblocks(buf + off, 1, &state);
buflen = off + XOF_BLOCKBYTES;
ctr += rej_uniform(a[i].vec[j].coeffs + ctr, KYBER_N - ctr, buf, buflen);
}
}
}
}
The issue for regular Kyber occurs with probability approximately 2^-105.
Use rustcrypto for the 90's mode AES functions.
Kyber uses some intermediate functions not exposed by the rustcrypto crate, namely aes256ctr_init
and aes256ctr_squeezeblocks
The PRF is already implemented yet not in use.
Lines 117 to 129 in 6e274dc
Kyber should not be used by itself currently[1][2] in most cases. There's notes in the readme about this but always a chance of misuse with shiny new thing. We should have an easy to use/ hard to fuckup hybrid[3] mechanism.
The IETF TLS 1.3 draft proposal uses a simple concatenation[4]. OpenSSH currently uses concatenation then hashing for its sntrup761x25519 kem[5]. The other alternative here is xor'ing the shared secrets assuming they are the same size (a fair assumption).
I'd suggest Kyber768x25519 as an opinionated default, though it should be pluggable with other kem's as curve25519 isn't accepted by some companies/clouds/governments/standards bodies today and probably never will be.
[1] https://www.ietf.org/archive/id/draft-campagna-tls-bike-sike-hybrid-07.html
BIKE, Kyber and SIKE are post-quantum candidates which were submitted to the NIST Call for Proposals for Post-Quantum Cryptographic Schemes. While these schemes are still being analyzed as part of that process, there is already a need to protect the confidentiality of today's TLS connections against a future adversary with a quantum computer. Hybrid key exchanges are designed to provide two parallel key exchanges: one which is classical (e.g., ECDHE) and the other which is quantum-safe (e.g., SIKE). The hybrid schemes we propose are at least as secure as ECDH against a classical adversary, and at least as secure as the PQ KEM against a quantum adversary. This strategy is emerging as a method to speculatively provide additional security to existing protocols.
[2] https://eprint.iacr.org/2022/975.pdf
Our Magma implementation breaks the instantiation SIKEp434, which aims at security level 1
of the Post-Quantum Cryptography standardization process currently ran by
NIST, in about one hour on a single core.
[3] https://www.ietf.org/archive/id/draft-ietf-tls-hybrid-design-04.html#section-1.2
"Hybrid" key exchange, in this context, means the use of two (or more) key exchange algorithms based on different cryptographic assumptions, e.g., one traditional algorithm and one next-gen algorithm, with the purpose of the final session key being secure as long as at least one of the component key exchange algorithms remains unbroken.
[4] https://www.ietf.org/archive/id/draft-ietf-tls-hybrid-design-04.html#section-3
[5] https://github.com/openssh/openssh-portable/blob/master/kexsntrup761x25519.c#L103
The assembly files included for the AVX2 code don't export underscore-prefixed names, which is what the ABI on MacOS expects. Thus this crate fails to compile on Mac. (without specifying reference
)
https://docs.rs/pqc_kyber/0.4.0/src/pqc_kyber/kex.rs.html There're 2 words "Epheremal", seemingly the correct spelling is "Ephemeral".
Would be a breaking change for embedded devices but this should probably be done, most people want the error handling and the standard library.
Hi,
I am trying to play with pqc_library in order to test some crypto latencies. At the moment of building cargo ( cargo build --release
), pqc_library throws the following errors:
$ cargo build --release`
Compiling pqc_kyber v0.7.1
error: #[panic_handler] function required, but not found
error: language item required, but not found: eh_personality
|
= note: this can occur when a binary crate with #![no_std] is compiled for a target where eh_personality is defined in the standard library
= help: you may be able to compile for a target that doesn't need eh_personality, specify a target with --target or in .cargo/config
error: could not compile pqc_kyber (lib) due to 2 previous errors
I've tried several things such as adding a #[panic_handler] function with panic warnings in main.rs, or adding
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
to the cargo.toml file, nothing changes for me. I am running the program in ubuntu20.04.
Any help is welcome,
R.
Currently tests are only run on Linux.
Add Windows and MacOS, the latter will need to be reference only until #2 is fixed.
Include 32 bit runners to make sure the usage of usize
isn't causing trouble anywhere.
Also investigate using QEMU to do a sanity check for the load/store functions and integer conversions on a big-endian system.
softprops is likely a better choice and actively maintained
The current signature of both encapsulate and decapsulate (fn encapsulate(...) -> Result<... [u8; 32] ...>
, fn decapsulate(...) -> Result<[u8; 32], ...>
stores the secret on the stack. This means it will potentially be copied around many times in memory, depending on how optimizations happen to generate the final code.
It is recommended to zero out cryptographic secrets when done with them/before other software has a chance to read that memory. This is currently not really possible with pqc_kyber
and the current function signatures.
I recommend, and would be very interested in improving this. I implemented something very similar for classic-mceliece-rust
recently. All secrets were bundled up in dedicated containers that allowed both borrowed and owned versions of the data, but that was never copied around in the memory, and that automatically cleared themselves on drop. See here for one example: https://github.com/Colfenor/classic-mceliece-rust/blob/bb57cd4f97ae2d092b8b1bfbc88c49507eca2892/src/lib.rs#L283-L333
The same goes for the SecretKey
type really. It should implement Zeroize + ZeroizeOnDrop
.
Two-part issue:
Key generation benchmarking uses a cryptographic rng, this leads to wildly fluctuating benches due to the bottleneck of entropy generation and is basically worthless. Temporarily should probably be removed.
It needs to be replaced with a non-cryptographic rng to get accurate readings, this should probably be something like fastrand or perhaps XXHash with deterministic output.
Setup a github action using the current Criterion benchmark harness that can report any regressions on PR's.
Keypairs components should not be individual inputs for the API.
The entire keypair should be passed to the functions. Perhaps add something like a strict mode also that confirms correctness for any end users faced with adversarial input.
https://media.defense.gov/2022/Sep/07/2003071836/-1/-1/0/CSI_CNSA_2.0_FAQ_.PDF
Let's ses these 2 parts:
First: NSA suggests using Leighton-Micali Signature (LMS) or Xtended Merkle Signature Scheme (XMSS) to sign firmware or software. You should implement them in pure Rust.
Second:
Q: What is NSA’s position on the use of hybrid solutions?
A: NSA has confidence in CNSA 2.0 algorithms and will not require NSS developers to
use hybrid certified products for security purposes. Product availability
and interoperability requirements may lead to adopting hybrid solutions. NSA recognizes
that some standards may require using hybrid-like constructions to accommodate the
larger sizes of CRQC algorithms and will work with industry on the best options for
implementation.
In my opinion, "product availability and interoperability" means compatibility for old browsers in WinXP and even Win10. So only when you're still using WinXP or even Win10, you use hybrid mode for your old browser. In my opinion, it's only for old browsers, Kyber is strong enough and works well without legacy cryptographies.
There's nothing in the /tests readme about the the flags the convenience test runner script uses.
In this implementation, when re-encryption fails, explicit rejection is used. That is not allowed by the Kyber specification: decapsulation always has to succeed.
It might make sense to remove "90s" mode at some point since from what I can see on the mailing list it's not going to be standardized and therefore also will not fall under the carte blanche patent grant that only covers the standardized form.
use pqc_kyber::*;
fn main(){
let mut rng = rand::thread_rng();
let pair = keypair(&mut rng);
let (ct, ss) = encapsulate(&pair.public, &mut rng)?;
}
#[panic_handler]
fn my_panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}
#[lang = "eh_personality"]
extern "C" fn eh_personality() {}
Still get compile time error:
error: #[panic_handler]
function required, but not found
error: language item required, but not found: eh_personality
|
= note: this can occur when a binary crate with #![no_std]
is compiled for a target where eh_personality
is defined in the standard library
= help: you may be able to compile for a target that doesn't need eh_personality
, specify a target with --target
or in .cargo/config
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.