1use crate::{CryptoHash, Curve, CurveType, TypedCurve, VerifiableCurve};
2use generic_array::GenericArray;
3use p256::{
4 EncodedPoint,
5 ecdsa::{Signature, VerifyingKey, signature::hazmat::PrehashVerifier},
6 elliptic_curve::scalar::IsHigh,
7};
8
9pub struct P256;
10
11impl Curve for P256 {
12 type PublicKey = [u8; 33];
14
15 type Signature = [u8; 64];
17
18 type Message = CryptoHash;
20
21 type VerifyingKey = Self::PublicKey;
22}
23
24impl VerifiableCurve for P256 {
25 fn verify(
26 signature: &Self::Signature,
27 prehashed: &Self::Message,
28 public_key: &Self::VerifyingKey,
29 ) -> Option<Self::PublicKey> {
30 let signature =
32 Signature::from_bytes(GenericArray::from_slice(signature).as_0_14()).ok()?;
33
34 if signature.s().is_high().into() {
35 return None;
37 }
38
39 let verifying_key = VerifyingKey::from_sec1_bytes(public_key).ok()?;
41
42 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}
54
55#[cfg_attr(any(feature = "arbitrary", test), derive(arbitrary::Arbitrary))]
57#[cfg_attr(
58 feature = "serde",
59 derive(::serde_with::SerializeDisplay, ::serde_with::DeserializeFromStr),
60 cfg_attr(feature = "abi", derive(::schemars::JsonSchema))
61)]
62#[cfg_attr(
63 feature = "borsh",
64 derive(::borsh::BorshSerialize, ::borsh::BorshDeserialize),
65 cfg_attr(feature = "abi", derive(::borsh::BorshSchema))
66)]
67#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
68#[repr(transparent)]
69pub struct P256CompressedPublicKey(
70 #[cfg_attr(all(feature = "abi", feature = "serde"), schemars(with = "String"))]
72 pub <P256 as Curve>::PublicKey,
73);
74
75#[cfg(feature = "parse")]
76const _: () = {
77 use crate::ParseCurveError;
78 use core::fmt::{self, Debug, Display};
79 use std::str::FromStr;
80
81 impl Debug for P256CompressedPublicKey {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 Display::fmt(self, f)
84 }
85 }
86
87 impl Display for P256CompressedPublicKey {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 f.write_str(&<P256 as TypedCurve>::to_base58(self.0))
90 }
91 }
92
93 impl FromStr for P256CompressedPublicKey {
94 type Err = ParseCurveError;
95
96 fn from_str(s: &str) -> Result<Self, Self::Err> {
97 P256::parse_base58(s).map(Self)
98 }
99 }
100};
101
102#[cfg_attr(any(feature = "arbitrary", test), derive(arbitrary::Arbitrary))]
104#[cfg_attr(
105 feature = "borsh",
106 derive(::borsh::BorshSerialize, ::borsh::BorshDeserialize),
107 cfg_attr(feature = "abi", derive(::borsh::BorshSchema))
108)]
109#[cfg_attr(
110 feature = "serde",
111 derive(::serde_with::SerializeDisplay, ::serde_with::DeserializeFromStr),
112 cfg_attr(feature = "abi", derive(::schemars::JsonSchema))
113)]
114#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
115#[repr(transparent)]
116pub struct P256UncompressedPublicKey(
117 #[cfg_attr(all(feature = "abi", feature = "serde"), schemars(with = "String"))] pub [u8; 64],
119);
120
121#[cfg(feature = "parse")]
122const _: () = {
123 use crate::ParseCurveError;
124 use core::fmt::{self, Debug, Display};
125 use std::str::FromStr;
126
127 impl Debug for P256UncompressedPublicKey {
128 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129 Display::fmt(self, f)
130 }
131 }
132
133 impl Display for P256UncompressedPublicKey {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 f.write_str(&<P256 as TypedCurve>::to_base58(self.0))
136 }
137 }
138
139 impl FromStr for P256UncompressedPublicKey {
140 type Err = ParseCurveError;
141
142 fn from_str(s: &str) -> Result<Self, Self::Err> {
143 P256::parse_base58(s).map(Self)
144 }
145 }
146};
147
148#[cfg_attr(any(feature = "arbitrary", test), derive(arbitrary::Arbitrary))]
149#[cfg_attr(
150 feature = "borsh",
151 derive(::borsh::BorshSerialize, ::borsh::BorshDeserialize),
152 cfg_attr(feature = "abi", derive(::borsh::BorshSchema))
153)]
154#[cfg_attr(
155 feature = "serde",
156 derive(::serde_with::SerializeDisplay, ::serde_with::DeserializeFromStr),
157 cfg_attr(feature = "abi", derive(::schemars::JsonSchema))
158)]
159#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
160#[repr(transparent)]
161pub struct P256Signature(
162 #[cfg_attr(all(feature = "abi", feature = "serde"), schemars(with = "String"))]
164 pub <P256 as Curve>::Signature,
165);
166
167#[cfg(feature = "parse")]
168const _: () = {
169 use crate::ParseCurveError;
170 use core::fmt::{self, Debug, Display};
171 use std::str::FromStr;
172
173 impl Debug for P256Signature {
174 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
175 Display::fmt(self, f)
176 }
177 }
178
179 impl Display for P256Signature {
180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181 f.write_str(&<P256 as TypedCurve>::to_base58(self.0))
182 }
183 }
184
185 impl FromStr for P256Signature {
186 type Err = ParseCurveError;
187
188 fn from_str(s: &str) -> Result<Self, Self::Err> {
189 P256::parse_base58(s).map(Self)
190 }
191 }
192};
193
194pub fn compress_public_key(public_key: P256UncompressedPublicKey) -> P256CompressedPublicKey {
198 EncodedPoint::from_untagged_bytes(GenericArray::from_array(public_key.0).as_0_14())
199 .compress()
200 .as_bytes()
201 .try_into()
202 .map_or_else(|_| unreachable!(), P256CompressedPublicKey)
203}