Skip to content
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
5 changes: 4 additions & 1 deletion oqs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ license = "MIT OR Apache-2.0"
libc = "0.2"
cstr_core = { version = "0.2", default-features = false, features = ["alloc"] }
serde = { version = "1.0", optional = true, default-features = false, features = ["derive", "alloc"] }
kem = "=0.3.0-pre.0"
signature = "2.2.0"
rand_core = { version = "0.6", features = ["getrandom"] }

[dependencies.oqs-sys]
path = "../oqs-sys"
Expand Down Expand Up @@ -43,4 +46,4 @@ falcon = ["oqs-sys/falcon"]
mayo = ["oqs-sys/mayo"]
ml_dsa = ["oqs-sys/ml_dsa"]
sphincs = ["oqs-sys/sphincs"]
uov = ["oqs-sys/uov"]
uov = ["oqs-sys/uov"]
92 changes: 92 additions & 0 deletions oqs/src/kem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@
//! See [`Kem`] for the main functionality.
//! [`Algorithm`] lists the available algorithms.
use alloc::vec::Vec;
use rand_core::CryptoRngCore;

use core::ptr::NonNull;

use ::kem::Decapsulate as RustCryptoDecapsulate;
use ::kem::Encapsulate as RustCryptoEncapsulate;

#[cfg(not(feature = "std"))]
use cstr_core::CStr;
#[cfg(feature = "std")]
Expand Down Expand Up @@ -478,3 +482,91 @@ impl Kem {
Ok(ss)
}
}

/// Encapsulator uses the public key of a KEM to encapsulate keys. This struct implements RustCrypto's Encapsulate trait.
///
/// # Example
/// ```rust
/// # if !cfg!(feature = "ml_kem") { return; }
/// use oqs;
/// use kem::{Encapsulate,Decapsulate};
/// use rand_core::OsRng;
/// oqs::init();
/// let kem = oqs::kem::Kem::new(oqs::kem::Algorithm::MlKem512).unwrap();
/// let (pk, sk) = kem.keypair().unwrap();
/// let encap = oqs::kem::Encapsulator::new(&kem, pk);
/// let decap = oqs::kem::Decapsulator::new(&kem, sk);
/// // Note that encapsulate ignores the provided rng
/// let (ct, ss) = encap.encapsulate(&mut OsRng).unwrap();
/// let ss2 = decap.decapsulate(&ct).unwrap();
/// assert_eq!(ss, ss2);
/// ```
pub struct Encapsulator<'a> {
scheme: &'a Kem,
pk: PublicKey,
}

impl<'a> Encapsulator<'a> {
/// Creates a new [`Encapsulator`].
pub fn new(scheme: &'a Kem, pk: PublicKey) -> Self {
Encapsulator {
scheme: scheme,
pk: pk,
}
}
}

/// Decapsulator struct containing a kem scheme and a secret key.
///
/// # Example
/// ```rust
/// # if !cfg!(feature = "ml_kem") { return; }
/// use oqs;
/// use kem::{Encapsulate,Decapsulate};
/// use rand_core::OsRng;
/// oqs::init();
/// let kem = oqs::kem::Kem::new(oqs::kem::Algorithm::MlKem512).unwrap();
/// let (pk, sk) = kem.keypair().unwrap();
/// let encap = oqs::kem::Encapsulator::new(&kem, pk);
/// let decap = oqs::kem::Decapsulator::new(&kem, sk);
/// // Note that encapsulate ignores the provided rng
/// let (ct, ss) = encap.encapsulate(&mut OsRng).unwrap();
/// let ss2 = decap.decapsulate(&ct).unwrap();
/// assert_eq!(ss, ss2);
/// ```
pub struct Decapsulator<'a> {
scheme: &'a Kem,
sk: SecretKey,
}

impl<'a> Decapsulator<'a> {
/// Creates a new [`Decapsulator`].
pub fn new(scheme: &'a Kem, sk: SecretKey) -> Self {
Decapsulator {
scheme: scheme,
sk: sk,
}
}
}

impl<'a> RustCryptoEncapsulate<Ciphertext, SharedSecret> for Encapsulator<'a> {
type Error = crate::Error;

fn encapsulate(
&self,
_csprng: &mut impl CryptoRngCore,
) -> core::result::Result<(Ciphertext, SharedSecret), Self::Error> {
self.scheme.encapsulate(&self.pk)
}
}

impl<'a> RustCryptoDecapsulate<Ciphertext, SharedSecret> for Decapsulator<'a> {
type Error = crate::Error;

fn decapsulate(
&self,
encapsulated_key: &Ciphertext,
) -> core::result::Result<SharedSecret, Self::Error> {
self.scheme.decapsulate(&self.sk, encapsulated_key)
}
}
88 changes: 88 additions & 0 deletions oqs/src/sig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ use std::ffi::CStr;
use crate::ffi::sig as ffi;
use crate::newtype_buffer;
use crate::*;
use ::signature::Signer as RustCryptoSigner;
use ::signature::Verifier as RustCryptoVerifier;

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -531,3 +533,89 @@ impl Sig {
status_to_result(status)
}
}

/// Signer struct containing a signature scheme and a signing key.
///
/// # Example
/// ```rust
/// # if !cfg!(feature = "ml_dsa") { return; }
/// use oqs;
/// use signature::{Signer,Verifier};
/// oqs::init();
/// let scheme = oqs::sig::Sig::new(oqs::sig::Algorithm::MlDsa44).unwrap();
/// let message = [0u8; 100];
/// let (pk, sk) = scheme.keypair().unwrap();
/// let signer = oqs::sig::Signer::new(&scheme,sk);
/// let verifier = oqs::sig::Verifier::new(&scheme,pk);
/// let signature = signer.try_sign(&message).unwrap();
/// assert!(verifier.verify(&message, &signature).is_ok());
/// ```
pub struct Signer<'a> {
scheme: &'a Sig,
sk: SecretKey,
}

impl<'a> Signer<'a> {
/// Creates a new [`Signer`] with the given signature scheme and secret key.
pub fn new(scheme: &'a Sig, sk: SecretKey) -> Self {
Signer {
scheme: scheme,
sk: sk,
}
}
}

impl<'a> RustCryptoSigner<sig::Signature> for Signer<'a> {
fn try_sign(&self, msg: &[u8]) -> core::result::Result<sig::Signature, signature::Error> {
match self.scheme.sign(msg, &self.sk) {
Ok(s) => Ok(s),
Err(_) => Err(signature::Error::new()),
}
}
}

/// Verifier struct containing a signature scheme and a public verification key.
///
/// # Example
/// ```rust
/// # if !cfg!(feature = "ml_dsa") { return; }
/// use oqs;
/// use signature::{Signer,Verifier};
/// oqs::init();
/// let scheme = oqs::sig::Sig::new(oqs::sig::Algorithm::MlDsa44).unwrap();
/// let message = [0u8; 100];
/// let (pk, sk) = scheme.keypair().unwrap();
/// let signer = oqs::sig::Signer::new(&scheme,sk);
/// let verifier = oqs::sig::Verifier::new(&scheme,pk);
/// let signature = signer.try_sign(&message).unwrap();
/// assert!(verifier.verify(&message, &signature).is_ok());
/// ```
///
/// Used to verify signatures for a given message.
pub struct Verifier<'a> {
scheme: &'a Sig,
pk: PublicKey,
}

impl<'a> Verifier<'a>{
/// Creates a new [`Verifier`] with the given signature scheme and public key.
pub fn new(scheme: &'a Sig, pk: PublicKey) -> Self{
Verifier{
scheme: scheme,
pk: pk,
}
}
}

impl<'a> RustCryptoVerifier<sig::Signature> for Verifier<'a> {
fn verify(
&self,
msg: &[u8],
signature: &sig::Signature,
) -> core::result::Result<(), signature::Error> {
match self.scheme.verify(msg, signature, &self.pk) {
Ok(_) => Ok(()),
Err(_) => Err(signature::Error::new()),
}
}
}
Loading