Skip to content

Small API update #19

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

Open
wants to merge 3 commits 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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use pqc_dilithium::*;
### Key Generation
```rust
let keys = Keypair::generate();
assert!(keys.public.len() == PUBLICKEYBYTES);
assert!(keys.public().len() == PUBLICKEYBYTES);
assert!(keys.expose_secret().len() == SECRETKEYBYTES);
```

Expand All @@ -47,7 +47,7 @@ assert!(sig.len() == SIGNBYTES);

### Verification
```rust
let sig_verify = verify(&sig, &msg, &keys.public);
let sig_verify = verify(&sig, &msg, &keys.public());
assert!(sig_verify.is_ok());
```

Expand Down
2 changes: 1 addition & 1 deletion benches/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fn verify_small_msg(c: &mut Criterion) {
let msg = "Hello".as_bytes();
let sig = keys.sign(msg);
c.bench_function("Verify Small Message", |b| {
b.iter(|| verify(black_box(sig), black_box(msg), black_box(&keys.public)))
b.iter(|| verify(black_box(sig), black_box(msg), black_box(&keys.public())))
});
}

Expand Down
69 changes: 63 additions & 6 deletions src/api.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use rand_core::CryptoRngCore;

use crate::params::{PUBLICKEYBYTES, SECRETKEYBYTES, SIGNBYTES};
use crate::sign::*;
use crate::{sign::*, SEEDBYTES};

#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct Keypair {
pub public: [u8; PUBLICKEYBYTES],
public: [u8; PUBLICKEYBYTES],
secret: [u8; SECRETKEYBYTES],
}

Expand All @@ -20,6 +22,17 @@ pub enum SignError {
}

impl Keypair {
/// Get public key
/// ```
/// # use pqc_dilithium::*;
/// let keys = Keypair::generate();
/// let public_key = keys.public();
/// assert!(public_key.len() == PUBLICKEYBYTES);
/// ```
pub fn public(&self) -> &[u8] {
&self.public
}

/// Explicitly expose secret key
/// ```
/// # use pqc_dilithium::*;
Expand All @@ -37,14 +50,35 @@ impl Keypair {
/// ```
/// # use pqc_dilithium::*;
/// let keys = Keypair::generate();
/// assert!(keys.public.len() == PUBLICKEYBYTES);
/// assert!(keys.public().len() == PUBLICKEYBYTES);
/// assert!(keys.expose_secret().len() == SECRETKEYBYTES);
/// ```
pub fn generate() -> Keypair {
pub fn generate() -> Self {
let mut public = [0u8; PUBLICKEYBYTES];
let mut secret = [0u8; SECRETKEYBYTES];
crypto_sign_keypair(&mut public, &mut secret, None);
Keypair { public, secret }
Self { public, secret }
}

/// Generates a keypair for signing and verification using a rng
///
/// Example:
/// ```
/// # use pqc_dilithium::*;
/// # use rand_core::OsRng;
/// let keys = Keypair::random(&mut OsRng);
/// assert!(keys.public().len() == PUBLICKEYBYTES);
/// assert!(keys.expose_secret().len() == SECRETKEYBYTES);
/// ```
pub fn random(rng: &mut impl CryptoRngCore) -> Self {
let mut public = [0u8; PUBLICKEYBYTES];
let mut secret = [0u8; SECRETKEYBYTES];

let mut seed = [0u8; SEEDBYTES];
rng.fill_bytes(&mut seed);

crypto_sign_keypair(&mut public, &mut secret, Some(&seed));
Self { public, secret }
}

/// Generates a signature for the given message using a keypair
Expand All @@ -62,6 +96,29 @@ impl Keypair {
crypto_sign_signature(&mut sig, msg, &self.secret);
sig
}

/// Get Keypair struct from raw bytes
///
/// Example:
/// ```
/// # use pqc_dilithium::*;
/// # let keys = Keypair::generate();
/// let public_key = keys.public();
/// let secret_key = keys.expose_secret();
/// let keys = Keypair::from_bytes(public_key, secret_key);
/// # let msg = "Hello".as_bytes();
/// # let signature = keys.sign(msg);
/// # assert!(verify(&signature, msg, &keys.public()).is_ok());
/// ```
pub fn from_bytes(public_key: &[u8], secret_key: &[u8]) -> Self {
let mut public = [0u8; PUBLICKEYBYTES];
let mut secret = [0u8; SECRETKEYBYTES];

public.copy_from_slice(public_key);
secret.copy_from_slice(secret_key);

Self { public, secret }
}
}

/// Verify signature using keypair
Expand All @@ -72,7 +129,7 @@ impl Keypair {
/// # let keys = Keypair::generate();
/// # let msg = [0u8; 32];
/// # let sig = keys.sign(&msg);
/// let sig_verify = verify(&sig, &msg, &keys.public);
/// let sig_verify = verify(&sig, &msg, &keys.public());
/// assert!(sig_verify.is_ok());
pub fn verify(
sig: &[u8],
Expand Down
15 changes: 13 additions & 2 deletions tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ fn sign_then_verify_valid() {
let msg = b"Hello";
let keys = Keypair::generate();
let signature = keys.sign(msg);
assert!(verify(&signature, msg, &keys.public).is_ok())
assert!(verify(&signature, msg, &keys.public()).is_ok());
}

#[test]
Expand All @@ -14,5 +14,16 @@ fn sign_then_verify_invalid() {
let keys = Keypair::generate();
let mut signature = keys.sign(msg);
signature[..4].copy_from_slice(&[255u8; 4]);
assert!(verify(&signature, msg, &keys.public).is_err())
assert!(verify(&signature, msg, &keys.public()).is_err());
}

#[test]
fn to_and_from_bytes() {
let keys = Keypair::generate();
let public_key = keys.public();
let secret_key = keys.expose_secret();
let keys = Keypair::from_bytes(public_key, secret_key);
let msg = b"Hello";
let signature = keys.sign(msg);
assert!(verify(&signature, msg, &keys.public()).is_ok());
}