pub mod address;
pub mod fors;
pub mod hash;
pub mod hypertree;
pub mod params;
pub mod rng;
pub mod sha3;
pub mod slh;
pub mod wots;
pub mod xmss;
pub use params::{Params, Shake128f, Shake128s, Shake192f, Shake192s, Shake256f, Shake256s};
pub use rng::CryptoRng;
#[cfg(feature = "std")]
pub use rng::OsRng;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SlhDsaError {
RngFailure,
InvalidKey,
InvalidSignature,
VerificationFailed,
FaultDetected,
}
impl core::fmt::Display for SlhDsaError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
SlhDsaError::RngFailure => write!(f, "RNG failure"),
SlhDsaError::InvalidKey => write!(f, "Invalid key"),
SlhDsaError::InvalidSignature => write!(f, "Invalid signature"),
SlhDsaError::VerificationFailed => write!(f, "Verification failed"),
SlhDsaError::FaultDetected => write!(f, "Signing-side fault detected by FORS redundancy"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for SlhDsaError {}
use crate::secret::SecretBytes;
use alloc::vec::Vec;
use core::marker::PhantomData;
pub struct VerifyingKey<P: Params> {
bytes: Vec<u8>,
_marker: PhantomData<P>,
}
impl<P: Params> VerifyingKey<P> {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, SlhDsaError> {
if bytes.len() != P::PK_LEN {
return Err(SlhDsaError::InvalidKey);
}
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, SlhDsaError> {
if bytes.len() != P::SK_LEN {
return Err(SlhDsaError::InvalidKey);
}
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, SlhDsaError> {
if bytes.len() != params::sig_len::<P>() {
return Err(SlhDsaError::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,
}
}
}
pub struct SlhDsa<P: Params> {
_marker: core::marker::PhantomData<P>,
}
impl<P: Params> SlhDsa<P> {
pub fn keygen(rng: &mut dyn CryptoRng) -> Result<(SigningKey<P>, VerifyingKey<P>), SlhDsaError> {
let (sk_v, pk_v) = slh::slh_keygen::<P>(rng)?;
Ok((
SigningKey {
bytes: SecretBytes::from_vec(sk_v),
_marker: PhantomData,
},
VerifyingKey {
bytes: pk_v,
_marker: PhantomData,
},
))
}
pub fn keygen_internal(sk_seed: &[u8], sk_prf: &[u8], pk_seed: &[u8]) -> (Vec<u8>, Vec<u8>) {
slh::slh_keygen_internal::<P>(sk_seed, sk_prf, pk_seed)
}
pub fn sign(
message: &[u8],
secret_key: &SigningKey<P>,
rng: &mut dyn CryptoRng,
) -> Result<Signature<P>, SlhDsaError> {
let sig_v = slh::slh_sign::<P>(message, secret_key.as_bytes(), rng)?;
Ok(Signature {
bytes: sig_v,
_marker: PhantomData,
})
}
pub fn sign_internal(message: &[u8], secret_key: &[u8], addrnd: &[u8]) -> Result<Vec<u8>, SlhDsaError> {
slh::slh_sign_internal::<P>(message, secret_key, addrnd)
}
pub fn verify(message: &[u8], signature: &Signature<P>, public_key: &VerifyingKey<P>) -> Result<bool, SlhDsaError> {
slh::slh_verify::<P>(message, signature.as_bytes(), public_key.as_bytes())
}
pub fn signature_size() -> usize {
params::sig_len::<P>()
}
pub fn public_key_size() -> usize {
P::PK_LEN
}
pub fn secret_key_size() -> usize {
P::SK_LEN
}
}