defuse_crypto/curve/
p256.rs

1use super::{Curve, CurveType, TypedCurve};
2use generic_array::GenericArray;
3use near_sdk::CryptoHash;
4use p256::{
5    EncodedPoint,
6    ecdsa::{Signature, VerifyingKey, signature::hazmat::PrehashVerifier},
7    elliptic_curve::scalar::IsHigh,
8};
9
10pub struct P256;
11
12impl Curve for P256 {
13    /// Concatenated `x || y` coordinates with no leading SEC1 tag byte.
14    type PublicKey = [u8; 64];
15
16    /// Concatenated `r || s` coordinates
17    type Signature = [u8; 64];
18
19    // Output of cryptographic hash function
20    type Message = CryptoHash;
21
22    type VerifyingKey = Self::PublicKey;
23
24    fn verify(
25        signature: &Self::Signature,
26        prehashed: &Self::Message,
27        public_key: &Self::VerifyingKey,
28    ) -> Option<Self::PublicKey> {
29        // convert signature
30        let signature =
31            Signature::from_bytes(GenericArray::from_slice(signature).as_0_14()).ok()?;
32
33        if signature.s().is_high().into() {
34            // guard against signature malleability
35            return None;
36        }
37
38        // convert verifying key
39        let verifying_key = VerifyingKey::from_encoded_point(&EncodedPoint::from_untagged_bytes(
40            GenericArray::from_slice(public_key).as_0_14(),
41        ))
42        .ok()?;
43
44        // verify signature over prehashed
45        verifying_key
46            .verify_prehash(prehashed, &signature)
47            .is_ok()
48            .then_some(public_key)
49            .copied()
50    }
51}
52
53impl TypedCurve for P256 {
54    const CURVE_TYPE: CurveType = CurveType::P256;
55}