#![forbid(unsafe_code)]
use ed448_goldilocks::sha3::digest::Update;
use ed448_goldilocks::{
sha3::Shake256, EdwardsScalarBytes, PreHasherXof, Signature, SigningKey, VerifyingKey,
};
use oxicrypto_core::{CryptoError, Vec};
#[must_use = "signature result must be checked"]
pub fn ed448ph_sign(
sk: &[u8],
message: &[u8],
context: Option<&[u8]>,
) -> Result<Vec<u8>, CryptoError> {
let sk_bytes: [u8; 57] = sk.try_into().map_err(|_| CryptoError::InvalidKey)?;
let scalar = EdwardsScalarBytes::from(sk_bytes);
let signing_key = SigningKey::from(scalar);
let mut hasher = Shake256::default();
hasher.update(message);
let prehash = PreHasherXof::<Shake256>::new(hasher);
let sig: Signature = signing_key
.sign_prehashed(context, prehash)
.map_err(|_| CryptoError::Sign)?;
Ok(sig.to_bytes().to_vec())
}
#[must_use = "verification result must be checked"]
pub fn ed448ph_verify(
pk: &[u8],
message: &[u8],
sig: &[u8],
context: Option<&[u8]>,
) -> Result<(), CryptoError> {
let pk_bytes: &[u8; 57] = pk.try_into().map_err(|_| CryptoError::InvalidKey)?;
let sig_bytes: [u8; 114] = sig.try_into().map_err(|_| CryptoError::InvalidTag)?;
let verifying_key = VerifyingKey::from_bytes(pk_bytes).map_err(|_| CryptoError::InvalidKey)?;
let signature = Signature::from_bytes(&sig_bytes);
let mut hasher = Shake256::default();
hasher.update(message);
let prehash = PreHasherXof::<Shake256>::new(hasher);
verifying_key
.verify_prehashed(&signature, context, prehash)
.map_err(|_| CryptoError::InvalidTag)
}
#[must_use = "signature result must be checked"]
pub fn ed448ctx_sign(sk: &[u8], message: &[u8], context: &[u8]) -> Result<Vec<u8>, CryptoError> {
if context.len() > 255 {
return Err(CryptoError::BadInput);
}
let sk_bytes: [u8; 57] = sk.try_into().map_err(|_| CryptoError::InvalidKey)?;
let scalar = EdwardsScalarBytes::from(sk_bytes);
let signing_key = SigningKey::from(scalar);
let sig: Signature = signing_key
.sign_ctx(context, message)
.map_err(|_| CryptoError::Sign)?;
Ok(sig.to_bytes().to_vec())
}
#[must_use = "verification result must be checked"]
pub fn ed448ctx_verify(
pk: &[u8],
message: &[u8],
sig: &[u8],
context: &[u8],
) -> Result<(), CryptoError> {
if context.len() > 255 {
return Err(CryptoError::BadInput);
}
let pk_bytes: &[u8; 57] = pk.try_into().map_err(|_| CryptoError::InvalidKey)?;
let sig_bytes: [u8; 114] = sig.try_into().map_err(|_| CryptoError::InvalidTag)?;
let verifying_key = VerifyingKey::from_bytes(pk_bytes).map_err(|_| CryptoError::InvalidKey)?;
let signature = Signature::from_bytes(&sig_bytes);
verifying_key
.verify_ctx(&signature, context, message)
.map_err(|_| CryptoError::InvalidTag)
}