Skip to content

Commit

Permalink
Add import key
Browse files Browse the repository at this point in the history
  • Loading branch information
Guilhem committed Dec 7, 2023
1 parent 476e22c commit 50c014b
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 4 deletions.
2 changes: 2 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ The KyberError enum has two variants:

* **RandomBytesGeneration** - Error trying to fill random bytes (i.e external (hardware) RNG modules can fail).

* **InvalidKey** - Given public and secret key does not match. Probably an input error.

---

## Features
Expand Down
72 changes: 69 additions & 3 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use crate::{
params::*,
CryptoRng, RngCore,
};

#[cfg(feature = "zeroize")]
use zeroize::{Zeroize, ZeroizeOnDrop};
/// Keypair generation with a provided RNG.
///
/// ### Example
Expand All @@ -25,7 +26,51 @@ where
crypto_kem_keypair(&mut public, &mut secret, rng, None)?;
Ok(Keypair { public, secret })
}

/// Verify that given secret and public key matches and put them in
/// the KeyPair structure after zeroize them if asked.
/// ### Example
/// ```
/// # use pqc_kyber::*;
/// # fn main() -> Result<(), KyberError> {
/// let mut rng = rand::thread_rng();
/// let keys = keypair(&mut rng)?;
/// let mut public = keys.public;
/// let mut secret = keys.secret;
/// let _ = keypairfrom(&mut public, &mut secret, &mut rng)?;
/// # Ok(())}
/// ```
pub fn keypairfrom<R>(
public: &mut [u8; KYBER_PUBLICKEYBYTES],
secret: &mut [u8; KYBER_SECRETKEYBYTES],
rng: &mut R,
) -> Result<Keypair, KyberError>
where
R: RngCore + CryptoRng,
{
//Try to encapsulate and decapsule to verify secret key matches public key
let (ciphertext, shared_secret) = encapsulate(public, rng)?;
let expected_shared_secret = decapsulate(&ciphertext, secret)?;
//If it does match, return a KeyPair
if expected_shared_secret == shared_secret {
let mut public2 = *public;
let mut secret2 = *secret;
let key = Keypair {
public: public2,
secret: secret2,
};
#[cfg(feature = "zeroize")]
{
public.zeroize();
secret.zeroize();
public2.zeroize();
secret2.zeroize();
}
Ok(key)
} else {
//Else return an error
Err(KyberError::InvalidKey)
}
}
/// Encapsulates a public key returning the ciphertext to send
/// and the shared secret
///
Expand Down Expand Up @@ -77,7 +122,8 @@ pub fn decapsulate(ct: &[u8], sk: &[u8]) -> Decapsulated {
/// A public/secret keypair for use with Kyber.
///
/// Byte lengths of the keys are determined by the security level chosen.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "zeroize", derive(Zeroize, ZeroizeOnDrop))]
pub struct Keypair {
pub public: PublicKey,
pub secret: SecretKey,
Expand All @@ -99,6 +145,26 @@ impl Keypair {
pub fn generate<R: CryptoRng + RngCore>(rng: &mut R) -> Result<Keypair, KyberError> {
keypair(rng)
}
/// Verify that given secret and public key matches and put them in
/// the KeyPair structure after zeroize them if asked.
/// ### Example
/// ```
/// # use pqc_kyber::*;
/// # fn main() -> Result<(), KyberError> {
/// let mut rng = rand::thread_rng();
/// let keys = keypair(&mut rng)?;
/// let mut public = keys.public;
/// let mut secret = keys.secret;
/// let _ = Keypair::import(&mut public, &mut secret, &mut rng)?;
/// # Ok(())}
/// ```
pub fn import<R: CryptoRng + RngCore>(
public: &mut [u8; KYBER_PUBLICKEYBYTES],
secret: &mut [u8; KYBER_SECRETKEYBYTES],
rng: &mut R
) -> Result<Keypair, KyberError> {
keypairfrom(public, secret, rng)
}
}

struct DummyRng {}
Expand Down
5 changes: 5 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pub enum KyberError {
Decapsulation,
/// Error trying to fill random bytes (i.e external (hardware) RNG modules can fail).
RandomBytesGeneration,
/// Error when generating keys
InvalidKey,
}

impl core::fmt::Display for KyberError {
Expand All @@ -22,6 +24,9 @@ impl core::fmt::Display for KyberError {
KyberError::RandomBytesGeneration => {
write!(f, "Random bytes generation function failed")
}
KyberError::InvalidKey => {
write!(f, "The secret and public key given does not match.")
}
}
}
}
Expand Down
7 changes: 6 additions & 1 deletion tests/kem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ fn keypair_encap_decap() {
let ss2 = decapsulate(&ct, &keys.secret).unwrap();
assert_eq!(ss1, ss2);
}

#[test]
fn keypair_import_fake() {
let mut rng = rand::thread_rng();
let mut keys = keypair(&mut rng).unwrap();
let key = keypairfrom(&mut keys.public, &mut keys.secret, &mut rng).unwrap();
}
#[test]
fn keypair_encap_decap_invalid_ciphertext() {
let mut rng = rand::thread_rng();
Expand Down

0 comments on commit 50c014b

Please sign in to comment.