Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add import key #107

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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