Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
thomwiggers committed Apr 3, 2019
0 parents commit aba13f1
Show file tree
Hide file tree
Showing 11 changed files with 280 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/target
**/*.rs.bk

/target
**/*.rs.bk
Cargo.lock
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "pqclean"]
path = pqclean
url = https://github.com/pqclean/PQClean.git
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[workspace]
members=[
"pqcrypto-traits",
"pqcrypto-kyber",
]
1 change: 1 addition & 0 deletions pqclean
Submodule pqclean added at 266e80
14 changes: 14 additions & 0 deletions pqcrypto-kyber/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "pqcrypto-kyber"
description = "Post-Quantum key-encapsulation mechanism Kyber768"
version = "0.1.0"
authors = ["Thom Wiggers <[email protected]>"]
edition = "2018"

[dependencies]
pqcrypto-traits = {path = "../pqcrypto-traits", version = "0.1.0" }
libc = "0.2.0"

[build-dependencies]
cc = { version = "1.0" }
glob = "0.3.0"
23 changes: 23 additions & 0 deletions pqcrypto-kyber/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
extern crate cc;
extern crate glob;

use std::path::Path;


fn main() {
let target_dir = Path::new("../pqclean/crypto_kem/kyber768/clean");
let common_dir = Path::new("../pqclean/common");
let common_files = [
common_dir.join("fips202.c"),
common_dir.join("notrandombytes.c"),
common_dir.join("sha2.c"),
];

let scheme_files = glob::glob(target_dir.join("*.c").to_str().unwrap()).unwrap();
cc::Build::new()
.include("../pqclean/common")
.include(target_dir)
.files(common_files.into_iter())
.files(scheme_files.into_iter().map(|p| p.unwrap().to_string_lossy().into_owned()))
.compile("libkyber768.a");
}
52 changes: 52 additions & 0 deletions pqcrypto-kyber/src/ffi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#![allow(unused)]
use libc::c_int;

pub const PQCLEAN_KYBER768_CLEAN_CRYPTO_SECRETKEYBYTES: usize = 2400;
pub const PQCLEAN_KYBER768_CLEAN_CRYPTO_PUBLICKEYBYTES: usize = 1088;
pub const PQCLEAN_KYBER768_CLEAN_CRYPTO_CIPHERTEXTBYTES: usize = 1152;
pub const PQCLEAN_KYBER768_CLEAN_CRYPTO_BYTES: usize = 32;

#[link(name = "kyber768")]
extern "C" {
pub fn PQCLEAN_KYBER768_CLEAN_crypto_kem_keypair(pk: *mut u8, sk: *mut u8) -> c_int;
pub fn PQCLEAN_KYBER768_CLEAN_crypto_kem_enc(ct: *mut u8, ss: *mut u8, pk: *const u8) -> c_int;
pub fn PQCLEAN_KYBER768_CLEAN_crypto_kem_dec(
ss: *mut u8,
ct: *const u8,
sk: *const u8,
) -> c_int;
}

#[cfg(test)]
mod test {
use super::*;
use std::mem;
#[test]
fn test_ffi() {
unsafe {
let mut pk: [u8; PQCLEAN_KYBER768_CLEAN_CRYPTO_PUBLICKEYBYTES] = mem::uninitialized();
let mut sk: [u8; PQCLEAN_KYBER768_CLEAN_CRYPTO_SECRETKEYBYTES] = mem::uninitialized();
let mut ct: [u8; PQCLEAN_KYBER768_CLEAN_CRYPTO_CIPHERTEXTBYTES] = mem::uninitialized();
let mut ss1: [u8; PQCLEAN_KYBER768_CLEAN_CRYPTO_BYTES] = mem::uninitialized();
let mut ss2: [u8; PQCLEAN_KYBER768_CLEAN_CRYPTO_BYTES] = mem::uninitialized();

assert_eq!(
0,
PQCLEAN_KYBER768_CLEAN_crypto_kem_keypair(pk.as_mut_ptr(), sk.as_mut_ptr())
);
assert_eq!(
0,
PQCLEAN_KYBER768_CLEAN_crypto_kem_enc(
ct.as_mut_ptr(),
ss1.as_mut_ptr(),
pk.as_ptr()
)
);
assert_eq!(
0,
PQCLEAN_KYBER768_CLEAN_crypto_kem_dec(ss2.as_mut_ptr(), ct.as_ptr(), sk.as_ptr())
);
assert_eq!(ss1, ss2);
}
}
}
149 changes: 149 additions & 0 deletions pqcrypto-kyber/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
//! Kyber 768
//!
//! Kyber is an IND-CCA2-secure key encapsulation mechanism (KEM), whose security is based on the
//! hardness of solving the learning-with-errors (LWE) problem over module lattices. Kyber is one
//! of the candidate algorithms submitted to the NIST post-quantum cryptography project. The
//! submission lists three different parameter sets aiming at different security levels.
//! Specifically, Kyber-512 aims at security roughly equivalent to AES-128, Kyber-768 aims at
//! security roughly equivalent to AES-192, and Kyber-1024 aims at security roughly equivalent to
//! AES-256.
//!
//! https://pq-crystals.org/kyber/
//!
//! # Examples
//! ```
//! use pqcrypto_kyber::*;
//! let (pk, sk) = keygen();
//! let (ss1, ct) = encapsulate(pk);
//! let ss2 = decapsulate(ct, sk);
//! assert!(ss1 == ss2);
//! ```
use std::mem;

pub mod ffi;
use pqcrypto_traits::kem;

macro_rules! simple_struct {
($type: ident, $size: expr) => {
pub struct $type([u8; $size]);

impl $type {
/// Generates an uninitialized object
///
/// Used to pass to ``ffi`` interfaces.
///
/// Internal use only!
fn new() -> Self {
$type(unsafe { mem::uninitialized() })
}
}

impl kem::$type for $type {
/// Get this object as a byte slice
#[inline]
fn as_bytes(&self) -> &[u8] {
&self.0
}

/// Construct this object from a byte slice
fn from_bytes(bytes: &[u8]) -> Self {
let mut array: [u8; $size] = unsafe { mem::uninitialized() };
array.copy_from_slice(bytes);
$type(array)
}
}

impl PartialEq for $type {
fn eq(&self, other: &Self) -> bool {
self.0
.iter()
.zip(other.0.iter())
.try_for_each(|(a, b)| if a == b { Ok(()) } else { Err(()) })
.is_ok()
}
}
};
}

simple_struct!(PublicKey, ffi::PQCLEAN_KYBER768_CLEAN_CRYPTO_PUBLICKEYBYTES);
simple_struct!(SecretKey, ffi::PQCLEAN_KYBER768_CLEAN_CRYPTO_SECRETKEYBYTES);
simple_struct!(
Ciphertext,
ffi::PQCLEAN_KYBER768_CLEAN_CRYPTO_CIPHERTEXTBYTES
);
simple_struct!(SharedSecret, ffi::PQCLEAN_KYBER768_CLEAN_CRYPTO_BYTES);

pub const fn public_key_bytes() -> usize {
ffi::PQCLEAN_KYBER768_CLEAN_CRYPTO_PUBLICKEYBYTES
}

pub const fn secret_key_bytes() -> usize {
ffi::PQCLEAN_KYBER768_CLEAN_CRYPTO_SECRETKEYBYTES
}

pub const fn ciphertext_bytes() -> usize {
ffi::PQCLEAN_KYBER768_CLEAN_CRYPTO_CIPHERTEXTBYTES
}

pub const fn shared_secret_bytes() -> usize {
ffi::PQCLEAN_KYBER768_CLEAN_CRYPTO_BYTES
}

pub fn keygen() -> (PublicKey, SecretKey) {
let mut pk = PublicKey::new();
let mut sk = SecretKey::new();
assert_eq!(
unsafe {
ffi::PQCLEAN_KYBER768_CLEAN_crypto_kem_keypair(pk.0.as_mut_ptr(), sk.0.as_mut_ptr())
},
0
);
(pk, sk)
}

pub fn encapsulate(pk: PublicKey) -> (SharedSecret, Ciphertext) {
let mut ss = SharedSecret::new();
let mut ct = Ciphertext::new();

assert_eq!(
unsafe {
ffi::PQCLEAN_KYBER768_CLEAN_crypto_kem_enc(
ct.0.as_mut_ptr(),
ss.0.as_mut_ptr(),
pk.0.as_ptr(),
)
},
0,
);

(ss, ct)
}

pub fn decapsulate(ct: Ciphertext, sk: SecretKey) -> SharedSecret {
let mut ss = SharedSecret::new();
assert_eq!(
unsafe {
ffi::PQCLEAN_KYBER768_CLEAN_crypto_kem_dec(
ss.0.as_mut_ptr(),
ct.0.as_ptr(),
sk.0.as_ptr(),
)
},
0
);
ss
}

#[cfg(test)]
mod test {
use super::*;

#[test]
pub fn test_kem() {
let (pk, sk) = keygen();
let (ss1, ct) = encapsulate(pk);
let ss2 = decapsulate(ct, sk);
assert!(ss1.0 == ss2.0, "Difference in shared secrets!");
}
}
7 changes: 7 additions & 0 deletions pqcrypto-traits/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "pqcrypto-traits"
version = "0.1.0"
authors = ["Thom Wiggers <[email protected]>"]
edition = "2018"

[dependencies]
19 changes: 19 additions & 0 deletions pqcrypto-traits/src/kem.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
pub trait PublicKey {
fn as_bytes(&self) -> &[u8];
fn from_bytes(bytes: &[u8]) -> Self where Self: Sized;
}

pub trait SecretKey {
fn as_bytes(&self) -> &[u8];
fn from_bytes(bytes: &[u8]) -> Self where Self: Sized;
}

pub trait Ciphertext {
fn as_bytes(&self) -> &[u8];
fn from_bytes(bytes: &[u8]) -> Self where Self: Sized;
}

pub trait SharedSecret {
fn as_bytes(&self) -> &[u8];
fn from_bytes(bytes: &[u8]) -> Self where Self: Sized;
}
1 change: 1 addition & 0 deletions pqcrypto-traits/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod kem;

0 comments on commit aba13f1

Please sign in to comment.