#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use subtle::ConstantTimeEq;
use zeroize::{Zeroize, ZeroizeOnDrop};
use crate::classic::crypto_sign::{
SignerState, crypto_sign_detached, crypto_sign_final_create, crypto_sign_final_verify,
crypto_sign_init, crypto_sign_keypair_inplace, crypto_sign_seed_keypair_inplace,
crypto_sign_update, crypto_sign_verify_detached,
};
use crate::constants::{
CRYPTO_SIGN_BYTES, CRYPTO_SIGN_PUBLICKEYBYTES, CRYPTO_SIGN_SECRETKEYBYTES,
CRYPTO_SIGN_SEEDBYTES,
};
use crate::error::Error;
use crate::types::*;
pub type PublicKey = StackByteArray<CRYPTO_SIGN_PUBLICKEYBYTES>;
pub type SecretKey = StackByteArray<CRYPTO_SIGN_SECRETKEYBYTES>;
pub type Signature = StackByteArray<CRYPTO_SIGN_BYTES>;
pub type Message = Vec<u8>;
#[cfg_attr(
feature = "serde",
derive(Zeroize, ZeroizeOnDrop, Serialize, Deserialize, Debug, Clone)
)]
#[cfg_attr(not(feature = "serde"), derive(Zeroize, ZeroizeOnDrop, Debug, Clone))]
pub struct SigningKeyPair<
PublicKey: ByteArray<CRYPTO_SIGN_PUBLICKEYBYTES> + Zeroize,
SecretKey: ByteArray<CRYPTO_SIGN_SECRETKEYBYTES> + Zeroize,
> {
pub public_key: PublicKey,
pub secret_key: SecretKey,
}
impl<
PublicKey: NewByteArray<CRYPTO_SIGN_PUBLICKEYBYTES> + Zeroize,
SecretKey: NewByteArray<CRYPTO_SIGN_SECRETKEYBYTES> + Zeroize,
> SigningKeyPair<PublicKey, SecretKey>
{
pub fn new() -> Self {
Self {
public_key: PublicKey::new_byte_array(),
secret_key: SecretKey::new_byte_array(),
}
}
pub fn gen() -> Self {
let mut public_key = PublicKey::new_byte_array();
let mut secret_key = SecretKey::new_byte_array();
crypto_sign_keypair_inplace(public_key.as_mut_array(), secret_key.as_mut_array());
Self {
public_key,
secret_key,
}
}
pub fn from_secret_key(secret_key: SecretKey) -> Self {
let mut seed = [0u8; 32];
seed.copy_from_slice(&secret_key.as_slice()[..32]);
Self::from_seed(&seed)
}
pub fn from_seed<Seed: ByteArray<CRYPTO_SIGN_SEEDBYTES>>(seed: &Seed) -> Self {
let mut public_key = PublicKey::new_byte_array();
let mut secret_key = SecretKey::new_byte_array();
crypto_sign_seed_keypair_inplace(
public_key.as_mut_array(),
secret_key.as_mut_array(),
seed.as_array(),
);
Self {
public_key,
secret_key,
}
}
}
impl
SigningKeyPair<
StackByteArray<CRYPTO_SIGN_PUBLICKEYBYTES>,
StackByteArray<CRYPTO_SIGN_SECRETKEYBYTES>,
>
{
pub fn gen_with_defaults() -> Self {
Self::gen()
}
}
impl<
'a,
PublicKey: ByteArray<CRYPTO_SIGN_PUBLICKEYBYTES> + std::convert::TryFrom<&'a [u8]> + Zeroize,
SecretKey: ByteArray<CRYPTO_SIGN_SECRETKEYBYTES> + std::convert::TryFrom<&'a [u8]> + Zeroize,
> SigningKeyPair<PublicKey, SecretKey>
{
pub fn from_slices(public_key: &'a [u8], secret_key: &'a [u8]) -> Result<Self, Error> {
Ok(Self {
public_key: PublicKey::try_from(public_key)
.map_err(|_e| dryoc_error!("invalid public key"))?,
secret_key: SecretKey::try_from(secret_key)
.map_err(|_e| dryoc_error!("invalid secret key"))?,
})
}
}
#[cfg(any(feature = "nightly", all(doc, not(doctest))))]
#[cfg_attr(all(feature = "nightly", doc), doc(cfg(feature = "nightly")))]
pub mod protected {
use super::*;
pub use crate::protected::*;
pub type PublicKey = HeapByteArray<CRYPTO_SIGN_PUBLICKEYBYTES>;
pub type SecretKey = HeapByteArray<CRYPTO_SIGN_SECRETKEYBYTES>;
pub type Signature = HeapByteArray<CRYPTO_SIGN_BYTES>;
pub type Message = HeapBytes;
pub type LockedSigningKeyPair = SigningKeyPair<Locked<PublicKey>, Locked<SecretKey>>;
pub type LockedSignedMessage = SignedMessage<Locked<Signature>, Locked<Message>>;
impl
SigningKeyPair<
Locked<HeapByteArray<CRYPTO_SIGN_PUBLICKEYBYTES>>,
Locked<HeapByteArray<CRYPTO_SIGN_SECRETKEYBYTES>>,
>
{
pub fn new_locked_keypair() -> Result<Self, std::io::Error> {
Ok(Self {
public_key: HeapByteArray::<CRYPTO_SIGN_PUBLICKEYBYTES>::new_locked()?,
secret_key: HeapByteArray::<CRYPTO_SIGN_SECRETKEYBYTES>::new_locked()?,
})
}
pub fn gen_locked_keypair() -> Result<Self, std::io::Error> {
let mut res = Self::new_locked_keypair()?;
crypto_sign_keypair_inplace(
res.public_key.as_mut_array(),
res.secret_key.as_mut_array(),
);
Ok(res)
}
}
impl
SigningKeyPair<
LockedRO<HeapByteArray<CRYPTO_SIGN_PUBLICKEYBYTES>>,
LockedRO<HeapByteArray<CRYPTO_SIGN_SECRETKEYBYTES>>,
>
{
pub fn gen_readonly_locked_keypair() -> Result<Self, std::io::Error> {
let mut public_key = HeapByteArray::<CRYPTO_SIGN_PUBLICKEYBYTES>::new_locked()?;
let mut secret_key = HeapByteArray::<CRYPTO_SIGN_SECRETKEYBYTES>::new_locked()?;
crypto_sign_keypair_inplace(public_key.as_mut_array(), secret_key.as_mut_array());
let public_key = public_key.mprotect_readonly()?;
let secret_key = secret_key.mprotect_readonly()?;
Ok(Self {
public_key,
secret_key,
})
}
}
}
#[cfg_attr(
feature = "serde",
derive(Zeroize, Clone, Debug, Serialize, Deserialize)
)]
#[cfg_attr(not(feature = "serde"), derive(Zeroize, Clone, Debug))]
pub struct SignedMessage<
Signature: ByteArray<CRYPTO_SIGN_BYTES> + Zeroize,
Message: Bytes + Zeroize,
> {
signature: Signature,
message: Message,
}
pub type VecSignedMessage = SignedMessage<Signature, Vec<u8>>;
impl<
PublicKey: ByteArray<CRYPTO_SIGN_PUBLICKEYBYTES> + Zeroize,
SecretKey: ByteArray<CRYPTO_SIGN_SECRETKEYBYTES> + Zeroize,
> SigningKeyPair<PublicKey, SecretKey>
{
pub fn sign<Signature: NewByteArray<CRYPTO_SIGN_BYTES> + Zeroize, Message: Bytes + Zeroize>(
&self,
message: Message,
) -> Result<SignedMessage<Signature, Message>, Error> {
let mut signature = Signature::new_byte_array();
crypto_sign_detached(
signature.as_mut_array(),
message.as_slice(),
self.secret_key.as_array(),
)?;
Ok(SignedMessage::<Signature, Message> { signature, message })
}
pub fn sign_with_defaults<Message: Bytes>(
&self,
message: Message,
) -> Result<SignedMessage<StackByteArray<CRYPTO_SIGN_BYTES>, Vec<u8>>, Error> {
self.sign(Vec::from(message.as_slice()))
}
}
impl Default for SigningKeyPair<PublicKey, SecretKey> {
fn default() -> Self {
Self::new()
}
}
pub struct IncrementalSigner {
state: SignerState,
}
impl IncrementalSigner {
pub fn new() -> Self {
Self {
state: crypto_sign_init(),
}
}
pub fn update<Message: Bytes>(&mut self, message: &Message) {
crypto_sign_update(&mut self.state, message.as_slice())
}
pub fn finalize<
Signature: NewByteArray<CRYPTO_SIGN_BYTES>,
SecretKey: ByteArray<CRYPTO_SIGN_SECRETKEYBYTES>,
>(
self,
secret_key: &SecretKey,
) -> Result<Signature, Error> {
let mut signature = Signature::new_byte_array();
crypto_sign_final_create(self.state, signature.as_mut_array(), secret_key.as_array())?;
Ok(signature)
}
pub fn verify<
Signature: ByteArray<CRYPTO_SIGN_BYTES>,
PublicKey: ByteArray<CRYPTO_SIGN_PUBLICKEYBYTES>,
>(
self,
signature: &Signature,
public_key: &PublicKey,
) -> Result<(), Error> {
crypto_sign_final_verify(self.state, signature.as_array(), public_key.as_array())?;
Ok(())
}
}
impl Default for IncrementalSigner {
fn default() -> Self {
Self::new()
}
}
impl<Signature: ByteArray<CRYPTO_SIGN_BYTES> + Zeroize, Message: Bytes + Zeroize>
SignedMessage<Signature, Message>
{
pub fn verify<PublicKey: ByteArray<CRYPTO_SIGN_PUBLICKEYBYTES>>(
&self,
public_key: &PublicKey,
) -> Result<(), Error> {
crypto_sign_verify_detached(
self.signature.as_array(),
self.message.as_slice(),
public_key.as_array(),
)
}
}
impl<
'a,
Signature: ByteArray<CRYPTO_SIGN_BYTES> + std::convert::TryFrom<&'a [u8]> + Zeroize,
Message: Bytes + From<&'a [u8]> + Zeroize,
> SignedMessage<Signature, Message>
{
pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, Error> {
if bytes.len() < CRYPTO_SIGN_BYTES {
Err(dryoc_error!(format!(
"bytes of len {} less than expected minimum of {}",
bytes.len(),
CRYPTO_SIGN_BYTES
)))
} else {
let (signature, message) = bytes.split_at(CRYPTO_SIGN_BYTES);
Ok(Self {
signature: Signature::try_from(signature)
.map_err(|_e| dryoc_error!("invalid signature"))?,
message: Message::from(message),
})
}
}
}
impl<Signature: ByteArray<CRYPTO_SIGN_BYTES> + Zeroize, Message: Bytes + Zeroize>
SignedMessage<Signature, Message>
{
pub fn from_parts(signature: Signature, message: Message) -> Self {
Self { signature, message }
}
pub fn to_vec(&self) -> Vec<u8> {
self.to_bytes()
}
pub fn into_parts(self) -> (Signature, Message) {
(self.signature, self.message)
}
pub fn to_bytes<Bytes: NewBytes + ResizableBytes>(&self) -> Bytes {
let mut data = Bytes::new_bytes();
data.resize(self.signature.len() + self.message.len(), 0);
let s = data.as_mut_slice();
s[..CRYPTO_SIGN_BYTES].copy_from_slice(self.signature.as_slice());
s[CRYPTO_SIGN_BYTES..].copy_from_slice(self.message.as_slice());
data
}
}
impl<
PublicKey: ByteArray<CRYPTO_SIGN_PUBLICKEYBYTES> + Zeroize,
SecretKey: ByteArray<CRYPTO_SIGN_SECRETKEYBYTES> + Zeroize,
> PartialEq<SigningKeyPair<PublicKey, SecretKey>> for SigningKeyPair<PublicKey, SecretKey>
{
fn eq(&self, other: &Self) -> bool {
self.public_key
.as_slice()
.ct_eq(other.public_key.as_slice())
.unwrap_u8()
== 1
&& self
.secret_key
.as_slice()
.ct_eq(other.secret_key.as_slice())
.unwrap_u8()
== 1
}
}
impl<Signature: ByteArray<CRYPTO_SIGN_BYTES> + Zeroize, Message: Bytes + Zeroize>
PartialEq<SignedMessage<Signature, Message>> for SignedMessage<Signature, Message>
{
fn eq(&self, other: &Self) -> bool {
self.signature
.as_slice()
.ct_eq(other.signature.as_slice())
.unwrap_u8()
== 1
&& self
.message
.as_slice()
.ct_eq(other.message.as_slice())
.unwrap_u8()
== 1
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_message_signing() {
let keypair = SigningKeyPair::gen_with_defaults();
let message = b"hello my frens";
let signed_message = keypair.sign_with_defaults(message).expect("signing failed");
signed_message
.verify(&keypair.public_key)
.expect("verification failed");
}
}