pub mod decompose;
pub mod dsa;
pub mod encode;
pub mod ntt;
pub mod params;
pub mod rng;
pub mod sample;
pub mod sha3;
#[cfg(feature = "sca-protected")]
pub mod masked;
#[cfg(feature = "sca-protected")]
pub mod shuffle;
#[cfg(feature = "small-secret")]
pub mod smallpoly;
#[cfg(any(feature = "compressed-poly", feature = "compressed-challenge"))]
pub mod compressed;
use alloc::vec::Vec;
use core::marker::PhantomData;
pub use params::{MlDsa44, MlDsa65, MlDsa87, Params};
pub use rng::CryptoRng;
#[cfg(feature = "std")]
pub use rng::OsRng;
use crate::secret::SecretBytes;
pub struct VerifyingKey<P: Params> {
bytes: Vec<u8>,
_marker: PhantomData<P>,
}
impl<P: Params> VerifyingKey<P> {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, MlDsaError> {
if bytes.len() != P::PK_LEN {
return Err(MlDsaError::InvalidPublicKey);
}
Ok(Self {
bytes: bytes.to_vec(),
_marker: PhantomData,
})
}
pub fn as_bytes(&self) -> &[u8] {
&self.bytes
}
pub fn len(&self) -> usize {
self.bytes.len()
}
}
impl<P: Params> AsRef<[u8]> for VerifyingKey<P> {
fn as_ref(&self) -> &[u8] {
&self.bytes
}
}
impl<P: Params> core::ops::Deref for VerifyingKey<P> {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.bytes
}
}
impl<P: Params> Clone for VerifyingKey<P> {
fn clone(&self) -> Self {
Self {
bytes: self.bytes.clone(),
_marker: PhantomData,
}
}
}
pub struct SigningKey<P: Params> {
bytes: SecretBytes,
_marker: PhantomData<P>,
}
impl<P: Params> SigningKey<P> {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, MlDsaError> {
if bytes.len() != P::SK_LEN {
return Err(MlDsaError::InvalidSecretKey);
}
Ok(Self {
bytes: SecretBytes::from_slice(bytes),
_marker: PhantomData,
})
}
pub fn as_bytes(&self) -> &[u8] {
self.bytes.as_bytes()
}
pub fn len(&self) -> usize {
self.bytes.len()
}
}
impl<P: Params> AsRef<[u8]> for SigningKey<P> {
fn as_ref(&self) -> &[u8] {
self.bytes.as_bytes()
}
}
impl<P: Params> core::ops::Deref for SigningKey<P> {
type Target = [u8];
fn deref(&self) -> &[u8] {
self.bytes.as_bytes()
}
}
pub struct Signature<P: Params> {
bytes: Vec<u8>,
_marker: PhantomData<P>,
}
impl<P: Params> Signature<P> {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, MlDsaError> {
if bytes.len() != P::SIG_LEN {
return Err(MlDsaError::InvalidSignature);
}
Ok(Self {
bytes: bytes.to_vec(),
_marker: PhantomData,
})
}
pub fn as_bytes(&self) -> &[u8] {
&self.bytes
}
pub fn len(&self) -> usize {
self.bytes.len()
}
}
impl<P: Params> AsRef<[u8]> for Signature<P> {
fn as_ref(&self) -> &[u8] {
&self.bytes
}
}
impl<P: Params> core::ops::Deref for Signature<P> {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.bytes
}
}
impl<P: Params> Clone for Signature<P> {
fn clone(&self) -> Self {
Self {
bytes: self.bytes.clone(),
_marker: PhantomData,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum MlDsaError {
RngFailure,
InvalidPublicKey,
InvalidSecretKey,
InvalidSignature,
ContextTooLong,
VerificationFailed,
}
impl core::fmt::Display for MlDsaError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
MlDsaError::RngFailure => write!(f, "RNG failure"),
MlDsaError::InvalidPublicKey => write!(f, "Invalid public key"),
MlDsaError::InvalidSecretKey => write!(f, "Invalid secret key"),
MlDsaError::InvalidSignature => write!(f, "Invalid signature"),
MlDsaError::ContextTooLong => write!(f, "Context string too long"),
MlDsaError::VerificationFailed => write!(f, "Signature verification failed"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for MlDsaError {}
pub struct MlDsa<P: Params> {
_marker: PhantomData<P>,
}
impl<P: Params> MlDsa<P> {
pub fn keygen(rng: &mut dyn CryptoRng) -> Result<(VerifyingKey<P>, SigningKey<P>), MlDsaError> {
let (pk_v, sk_v) = dsa::keygen::<P>(rng)?;
Ok((
VerifyingKey {
bytes: pk_v,
_marker: PhantomData,
},
SigningKey {
bytes: SecretBytes::from_vec(sk_v),
_marker: PhantomData,
},
))
}
pub fn keygen_internal(xi: &[u8; 32]) -> (Vec<u8>, Vec<u8>) {
dsa::keygen_internal::<P>(xi)
}
pub fn sign(
sk: &SigningKey<P>,
msg: &[u8],
ctx: &[u8],
rng: &mut dyn CryptoRng,
) -> Result<Signature<P>, MlDsaError> {
let sig_v = dsa::sign::<P>(sk.as_bytes(), msg, ctx, rng)?;
Ok(Signature {
bytes: sig_v,
_marker: PhantomData,
})
}
pub fn sign_internal(sk: &[u8], m_prime: &[u8], rnd: &[u8; 32]) -> Result<Vec<u8>, MlDsaError> {
dsa::sign_internal::<P>(sk, m_prime, rnd)
}
pub fn verify(pk: &VerifyingKey<P>, msg: &[u8], ctx: &[u8], sig: &Signature<P>) -> Result<bool, MlDsaError> {
dsa::verify::<P>(pk.as_bytes(), msg, ctx, sig.as_bytes())
}
pub fn verify_internal(pk: &[u8], m_prime: &[u8], sig: &[u8]) -> Result<bool, MlDsaError> {
dsa::verify_internal::<P>(pk, m_prime, sig)
}
pub const PK_LEN: usize = P::PK_LEN;
pub const SK_LEN: usize = P::SK_LEN;
pub const SIG_LEN: usize = P::SIG_LEN;
}
pub type MlDsa44Scheme = MlDsa<MlDsa44>;
pub type MlDsa65Scheme = MlDsa<MlDsa65>;
pub type MlDsa87Scheme = MlDsa<MlDsa87>;