1use crate::Result;
23use nss::{ec::Curve, ec::PublicKey, pbkdf2::HashAlgorithm};
24
25pub struct VerificationAlgorithm {
27 curve: Curve,
28 digest_alg: HashAlgorithm,
29}
30
31pub static ECDSA_P256_SHA256: VerificationAlgorithm = VerificationAlgorithm {
32 curve: Curve::P256,
33 digest_alg: HashAlgorithm::SHA256,
34};
35
36pub static ECDSA_P384_SHA384: VerificationAlgorithm = VerificationAlgorithm {
37 curve: Curve::P384,
38 digest_alg: HashAlgorithm::SHA384,
39};
40
41pub struct UnparsedPublicKey<'a> {
43 alg: &'static VerificationAlgorithm,
44 bytes: &'a [u8],
45}
46
47impl<'a> UnparsedPublicKey<'a> {
48 pub fn new(algorithm: &'static VerificationAlgorithm, bytes: &'a [u8]) -> Self {
49 Self {
50 alg: algorithm,
51 bytes,
52 }
53 }
54
55 pub fn verify(&self, message: &[u8], signature: &[u8]) -> Result<()> {
56 let pub_key = PublicKey::from_bytes(self.alg.curve, self.bytes)?;
57 Ok(pub_key.verify(message, signature, self.alg.digest_alg)?)
58 }
59
60 pub fn algorithm(&self) -> &'static VerificationAlgorithm {
61 self.alg
62 }
63
64 pub fn bytes(&self) -> &'a [u8] {
65 self.bytes
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72 use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine};
73 use nss::ensure_initialized;
74
75 #[test]
76 fn test_ecdsa_p384_sha384_verify() {
77 ensure_initialized();
78 let pub_key_bytes = URL_SAFE_NO_PAD.decode(
80 "BMZj_xHOfLQn5DIEQcYUkyASDWo8O30gWdkWXHHHWN5owKhGWplYHEb4PLf3DkFTg_smprr-ApdULy3NV10x8IZ0EfVaUZdXvTquH1kiw2PxD7fhqiozMXUaSuZI5KBE6w",
81 ).unwrap();
82 let message = URL_SAFE_NO_PAD.decode(
83 "F9MQDmEEdvOfm-NkCRrXqG-aVA9kq0xqtjvtWLndmmt6bO2gfLE2CVDDLzJYds0n88uz27c5JkzdsLpm5HP3aLFgD8bgnGm-EgdBpm99CRiIm7mAMbb0-NRAyUxeoGmdgJPVQLWFNoHRwzKV2wZ0Bk-Bq7jkeDHmDfnx-CJKVMQ",
84 )
85 .unwrap();
86 let signature = URL_SAFE_NO_PAD.decode(
87 "XLZmtJweW4qx0u0l6EpfmB5z-S-CNj4mrl9d7U0MuftdNPhmlNacV4AKR-i4uNn0TUIycU7GsfIjIqxuiL9WdAnfq_KH_SJ95mduqXgWNKlyt8JgMLd4h-jKOllh4erh",
88 )
89 .unwrap();
90 let public_key =
91 crate::signature::UnparsedPublicKey::new(&ECDSA_P384_SHA384, &pub_key_bytes);
92
93 let public_key_wrong_alg =
95 crate::signature::UnparsedPublicKey::new(&ECDSA_P256_SHA256, &pub_key_bytes);
96 assert!(public_key_wrong_alg.verify(&message, &signature).is_err());
97
98 let mut garbage_signature = signature.clone();
100 garbage_signature.push(42);
101 assert!(public_key.verify(&message, &garbage_signature).is_err());
102
103 let mut garbage_message = message.clone();
105 garbage_message[42] = 42;
106 assert!(public_key.verify(&garbage_message, &signature).is_err());
107
108 assert!(public_key.verify(&message, &signature).is_ok());
110 }
111}