defuse_crypto/curve/
p256.rs

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