Skip to content

Commit

Permalink
Update documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Christiaan676 committed Sep 23, 2024
1 parent 4671685 commit a6d882d
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 30 deletions.
2 changes: 2 additions & 0 deletions x-wing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ hybrid key encapsulation mechanism (PQ/T KEM) built on X25519 and ML-KEM-768. Us

Current implementation matches the [draft RFC][RFC-DRAFT] version 04.

The original paper: [X-Wing The Hybrid KEM You’ve Been Looking For][X-WING-PAPER]

[Documentation][docs-link]

## About
Expand Down
62 changes: 32 additions & 30 deletions x-wing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
//!
//! assert_eq!(ss_sender, ss_receiver);
//! ```
//!
//! [X-Wing draft]: https://datatracker.ietf.org/doc/html/draft-connolly-cfrg-xwing-kem
use kem::{Decapsulate, Encapsulate};
use ml_kem::array::ArrayN;
Expand All @@ -45,10 +43,14 @@ type MlKem768EncapsulationKey = kem::EncapsulationKey<MlKem768Params>;

const X_WING_LABEL: &[u8; 6] = br"\.//^\";

const PUBLIC_KEY_SIZE: usize = 1216;
const PRIVATE_KEY_SIZE: usize = 32;
/// Size in bytes of the `EncapsulationKey`.
pub const ENCAPSULATION_KEY_SIZE: usize = 1216;
/// Size in bytes of the `DecapsulationKey`.
pub const DECAPSULATION_KEY_SIZE: usize = 32;
/// Size in bytes of the `Ciphertext`.
pub const CIPHERTEXT_SIZE: usize = 1120;

/// Shared secret key
/// Shared secret key.
pub type SharedSecret = [u8; 32];

// The naming convention of variables matches the RFC.
Expand All @@ -61,7 +63,7 @@ pub type SharedSecret = [u8; 32];
// _m -> ML-Kem related key
// _x -> x25519 related key

/// The X-Wing encapsulation or public key
/// X-Wing encapsulation or public key.
#[derive(Clone, PartialEq)]
pub struct EncapsulationKey {
pk_m: MlKem768EncapsulationKey,
Expand Down Expand Up @@ -96,19 +98,19 @@ impl Encapsulate<Ciphertext, SharedSecret> for EncapsulationKey {
}

impl EncapsulationKey {
/// Covert the key to the following format:
/// ML-KEM-768 public key(1184 bytes) | X25519 public key(32 bytes)
/// Convert the key to the following format:
/// ML-KEM-768 public key(1184 bytes) | X25519 public key(32 bytes).
#[must_use]
pub fn as_bytes(&self) -> [u8; PUBLIC_KEY_SIZE] {
let mut buffer = [0u8; PUBLIC_KEY_SIZE];
pub fn as_bytes(&self) -> [u8; ENCAPSULATION_KEY_SIZE] {
let mut buffer = [0u8; ENCAPSULATION_KEY_SIZE];
buffer[0..1184].copy_from_slice(&self.pk_m.as_bytes());
buffer[1184..1216].copy_from_slice(self.pk_x.as_bytes());
buffer
}
}

impl From<&[u8; PUBLIC_KEY_SIZE]> for EncapsulationKey {
fn from(value: &[u8; PUBLIC_KEY_SIZE]) -> Self {
impl From<&[u8; ENCAPSULATION_KEY_SIZE]> for EncapsulationKey {
fn from(value: &[u8; ENCAPSULATION_KEY_SIZE]) -> Self {
let mut pk_m = [0; 1184];
pk_m.copy_from_slice(&value[0..1184]);
let pk_m = MlKem768EncapsulationKey::from_bytes(&pk_m.into());
Expand All @@ -120,11 +122,11 @@ impl From<&[u8; PUBLIC_KEY_SIZE]> for EncapsulationKey {
}
}

/// X-Wing decapsulation key or private key
/// X-Wing decapsulation key or private key.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "zeroize", derive(Zeroize, ZeroizeOnDrop))]
pub struct DecapsulationKey {
sk: [u8; PRIVATE_KEY_SIZE],
sk: [u8; DECAPSULATION_KEY_SIZE],
}

impl Decapsulate<Ciphertext, SharedSecret> for DecapsulationKey {
Expand All @@ -147,19 +149,19 @@ impl Decapsulate<Ciphertext, SharedSecret> for DecapsulationKey {
}

impl DecapsulationKey {
/// Generate a new `DecapsulationKey` using `OsRng`
/// Generate a new `DecapsulationKey` using `OsRng`.
#[cfg(feature = "getrandom")]
pub fn generate_rng() -> DecapsulationKey {
Self::generate(&mut rand_core::OsRng)
}

/// Generate a new `DecapsulationKey` using the provided RNG
/// Generate a new `DecapsulationKey` using the provided RNG.
pub fn generate(rng: &mut impl CryptoRngCore) -> DecapsulationKey {
let sk = generate(rng);
DecapsulationKey { sk }
}

/// Provide the matching `EncapsulationKey`
/// Provide the matching `EncapsulationKey`.
#[must_use]
pub fn encapsulation_key(&self) -> EncapsulationKey {
let (_sk_m, _sk_x, pk_m, pk_x) = self.expand_key();
Expand Down Expand Up @@ -190,20 +192,20 @@ impl DecapsulationKey {
(sk_m, sk_x, pk_m, pk_x)
}

/// Private key
/// Private key as bytes.
#[must_use]
pub fn as_bytes(&self) -> &[u8; PRIVATE_KEY_SIZE] {
pub fn as_bytes(&self) -> &[u8; DECAPSULATION_KEY_SIZE] {
&self.sk
}
}

impl From<[u8; PRIVATE_KEY_SIZE]> for DecapsulationKey {
fn from(sk: [u8; PRIVATE_KEY_SIZE]) -> Self {
impl From<[u8; DECAPSULATION_KEY_SIZE]> for DecapsulationKey {
fn from(sk: [u8; DECAPSULATION_KEY_SIZE]) -> Self {
DecapsulationKey { sk }
}
}

/// X-Wing ciphertext
/// X-Wing ciphertext.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "zeroize", derive(Zeroize, ZeroizeOnDrop))]
pub struct Ciphertext {
Expand All @@ -212,19 +214,19 @@ pub struct Ciphertext {
}

impl Ciphertext {
/// Covert the ciphertext to the following format:
/// ML-KEM-768 ciphertext(1088 bytes) | X25519 ciphertext(32 bytes)
/// Convert the ciphertext to the following format:
/// ML-KEM-768 ciphertext(1088 bytes) | X25519 ciphertext(32 bytes).
#[must_use]
pub fn as_bytes(&self) -> [u8; 1120] {
let mut buffer = [0; 1120];
pub fn as_bytes(&self) -> [u8; CIPHERTEXT_SIZE] {
let mut buffer = [0; CIPHERTEXT_SIZE];
buffer[0..1088].copy_from_slice(&self.ct_m);
buffer[1088..].copy_from_slice(&self.ct_x);
buffer
}
}

impl From<&[u8; 1120]> for Ciphertext {
fn from(value: &[u8; 1120]) -> Self {
impl From<&[u8; CIPHERTEXT_SIZE]> for Ciphertext {
fn from(value: &[u8; CIPHERTEXT_SIZE]) -> Self {
let mut ct_m = [0; 1088];
ct_m.copy_from_slice(&value[0..1088]);
let mut ct_x = [0; 32];
Expand All @@ -237,13 +239,13 @@ impl From<&[u8; 1120]> for Ciphertext {
}
}

/// Generate a X-Wing key pair using a the `OsRng`
/// Generate a X-Wing key pair using `OsRng`.
#[cfg(feature = "getrandom")]
pub fn generate_key_pair_rng() -> (DecapsulationKey, EncapsulationKey) {
generate_key_pair(&mut rand_core::OsRng)
}

/// Generate a X-Wing key pair
/// Generate a X-Wing key pair using the provided rng.
pub fn generate_key_pair(rng: &mut impl CryptoRngCore) -> (DecapsulationKey, EncapsulationKey) {
let sk = DecapsulationKey::generate(rng);
let pk = sk.encapsulation_key();
Expand Down

0 comments on commit a6d882d

Please sign in to comment.