use ed25519_dalek::{PUBLIC_KEY_LENGTH, Signature, Verifier, VerifyingKey};
use spki::SubjectPublicKeyInfoRef;
use crate::{RawSignatureValidationError, RawSignatureValidator, oids::ED25519_OID};
pub(crate) struct Ed25519Validator {}
impl RawSignatureValidator for Ed25519Validator {
fn validate(
&self,
sig: &[u8],
data: &[u8],
public_key: &[u8],
) -> Result<(), RawSignatureValidationError> {
let spki = SubjectPublicKeyInfoRef::try_from(public_key)
.map_err(|_| RawSignatureValidationError::InvalidPublicKey)?;
if spki.algorithm.oid.as_bytes() != ED25519_OID.as_bytes() {
return Err(RawSignatureValidationError::InvalidPublicKey);
}
let public_key = spki.subject_public_key.raw_bytes();
if public_key.len() != PUBLIC_KEY_LENGTH {
return Err(RawSignatureValidationError::InvalidPublicKey);
}
let mut public_key_slice: [u8; PUBLIC_KEY_LENGTH] = Default::default();
public_key_slice.copy_from_slice(public_key);
let vk = VerifyingKey::from_bytes(&public_key_slice)
.map_err(|_| RawSignatureValidationError::InvalidPublicKey)?;
let ed_sig = Signature::from_slice(sig)
.map_err(|_| RawSignatureValidationError::InvalidSignature)?;
match vk.verify(data, &ed_sig) {
Ok(_) => Ok(()),
Err(_) => Err(RawSignatureValidationError::SignatureMismatch),
}
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used)]
use super::*;
const SAMPLE_DATA: &[u8] = b"some sample content to sign";
#[test]
fn unparseable_public_key_rejected() {
let sig = include_bytes!("../../../tests/fixtures/raw_signature/ed25519.raw_sig");
assert_eq!(
Ed25519Validator {}
.validate(sig, SAMPLE_DATA, &[0x00, 0x01, 0x02])
.unwrap_err(),
RawSignatureValidationError::InvalidPublicKey
);
}
#[test]
fn wrong_algorithm_public_key_rejected() {
let sig = include_bytes!("../../../tests/fixtures/raw_signature/ed25519.raw_sig");
let ec_pub_key = include_bytes!("../../../tests/fixtures/raw_signature/es256.pub_key");
assert_eq!(
Ed25519Validator {}
.validate(sig, SAMPLE_DATA, ec_pub_key)
.unwrap_err(),
RawSignatureValidationError::InvalidPublicKey
);
}
#[test]
fn wrong_length_public_key_rejected() {
let spki = [
0x30, 0x0b, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x02, 0x00, 0x00, ];
let sig = include_bytes!("../../../tests/fixtures/raw_signature/ed25519.raw_sig");
assert_eq!(
Ed25519Validator {}
.validate(sig, SAMPLE_DATA, &spki)
.unwrap_err(),
RawSignatureValidationError::InvalidPublicKey
);
}
#[test]
fn invalid_signature_rejected() {
let pub_key = include_bytes!("../../../tests/fixtures/raw_signature/ed25519.pub_key");
assert_eq!(
Ed25519Validator {}
.validate(&[0u8; 8], SAMPLE_DATA, pub_key)
.unwrap_err(),
RawSignatureValidationError::InvalidSignature
);
}
}