defuse_webauthn/
ed25519.rs1use crate::Algorithm;
2
3pub struct Ed25519;
6
7impl Algorithm for Ed25519 {
8 type Curve = defuse_crypto::ed25519::Ed25519;
9
10 fn maybe_prehash(msg: impl AsRef<[u8]>) -> impl AsRef<[u8]> {
11 msg
13 }
14}
15
16#[cfg(test)]
17mod tests {
18 use defuse_crypto::{
19 Signer,
20 ed25519::{Ed25519PublicKey, Ed25519Signature, ed25519_dalek},
21 };
22 use hex_literal::hex;
23 use rand::rng;
24 use rstest::rstest;
25
26 use crate::{
27 IgnoreUserVerification, RequireUserVerification, Webauthn, WebauthnAssertion,
28 mock::MockWebauthnSigner,
29 };
30
31 use super::*;
32
33 #[rstest]
34 #[case(
35 hex!("e2e9cb7ac57cb46d4da1ce1d1cc2c33bdfe17407c517916b522724a8ea2c6c50"),
36 hex!("06f269191431372337a0c606a15822e349bd0d5ec317704f97bef1a4ed6f5e1d"),
37 WebauthnAssertion {
38 authenticator_data: hex!("49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97631d00000000").to_vec(),
39 client_data_json: r#"{"type":"webauthn.get","challenge":"BvJpGRQxNyM3oMYGoVgi40m9DV7DF3BPl77xpO1vXh0","origin":"http://localhost:5173","crossOrigin":false}"#.to_string(),
40 },
41 hex!("7cd68c54af557c3d5d7bb6810d90a3efd0eb09e11d13feae3df589d0a54e5629c56dd4e4f6ce48766fccd305135edcbfa1928b0e3131930825c464a68c7d6d0b"),
42 )]
43 fn verify_ok(
44 #[case] public_key: impl Into<Ed25519PublicKey>,
45 #[case] challenge: impl AsRef<[u8]>,
46 #[case] payload: WebauthnAssertion,
47 #[case] signature: impl Into<Ed25519Signature>,
48 ) {
49 assert!(
50 Webauthn::<Ed25519, RequireUserVerification>::verify(
51 &public_key.into().try_into().unwrap(),
52 challenge,
53 &payload,
54 &signature.into().into(),
55 ),
56 "signature is invalid",
57 );
58 }
59
60 #[rstest]
61 #[case("")]
62 #[case("test")]
63 #[case(hex!("9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"))]
64 #[tokio::test]
65 async fn sign_verify_ok(#[case] challenge: impl AsRef<[u8]>) {
66 let challenge = challenge.as_ref();
67
68 let signer = ed25519_dalek::SigningKey::generate(&mut rng());
69 let mock = MockWebauthnSigner::<Ed25519, IgnoreUserVerification, _>::new(signer);
70 let (assertion, signature) = mock.sign(challenge).await.unwrap();
71
72 assert!(
73 Webauthn::<Ed25519, IgnoreUserVerification>::verify(
74 &mock.signer().public_key(),
75 challenge,
76 &assertion,
77 &signature
78 ),
79 "signer produced invalid signature"
80 );
81 }
82}