#![allow(clippy::redundant_pub_crate)]
use ed25519_dalek::Verifier as _;
use ed25519_dalek::{Signature, VerifyingKey};
use sha2::{Digest as _, Sha512};
use super::CryptoError;
pub(crate) fn verify_ed25519(
public_key: &[u8],
message: &[u8],
signature: &[u8],
) -> Result<(), CryptoError> {
let key_bytes: [u8; 32] = public_key.try_into().map_err(|_err| CryptoError::InvalidKey)?;
let sig_bytes: [u8; 64] = signature
.try_into()
.map_err(|_err| CryptoError::InvalidSignature)?;
let verifying_key =
VerifyingKey::from_bytes(&key_bytes).map_err(|_err| CryptoError::InvalidKey)?;
let signature = Signature::from_bytes(&sig_bytes);
verifying_key
.verify(message, &signature)
.map_err(|_err| CryptoError::InvalidSignature)
}
pub(crate) fn sha512(data: &[u8]) -> [u8; 64] {
let mut hasher = Sha512::new();
hasher.update(data);
hasher.finalize().into()
}
#[cfg(feature = "std")]
pub(crate) fn fill_random(buf: &mut [u8]) -> Result<(), CryptoError> {
getrandom::fill(buf).map_err(|_err| CryptoError::RandomUnavailable)
}
#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used)]
use ed25519_dalek::{Signer as _, SigningKey};
use super::{sha512, verify_ed25519};
#[test]
fn verifies_a_valid_signature() {
let key = SigningKey::from_bytes(&[7u8; 32]);
let msg = b"hello roughtime";
let sig = key.sign(msg);
verify_ed25519(key.verifying_key().as_bytes(), msg, &sig.to_bytes()).unwrap();
}
#[test]
fn rejects_a_tampered_message() {
let key = SigningKey::from_bytes(&[7u8; 32]);
let sig = key.sign(b"hello roughtime");
assert!(
verify_ed25519(key.verifying_key().as_bytes(), b"goodbye roughtime", &sig.to_bytes())
.is_err()
);
}
#[test]
fn rejects_malformed_key_or_signature() {
assert!(verify_ed25519(&[0u8; 4], b"msg", &[0u8; 64]).is_err());
assert!(verify_ed25519(&[0u8; 32], b"msg", &[0u8; 4]).is_err());
}
#[test]
fn sha512_matches_known_vector() {
let digest = sha512(b"abc");
let expected = [
0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20,
0x41, 0x31, 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 0x0a, 0x9e, 0xee, 0xe6,
0x4b, 0x55, 0xd3, 0x9a, 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba,
0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f,
];
assert_eq!(digest, expected);
}
}