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