1use crate::SignatureError;
2use p256::ecdsa::SigningKey;
3use p256::ecdsa::VerifyingKey;
4use p256::elliptic_curve::group::GroupEncoding;
5use signature::Signer;
6use signature::Verifier;
7use sui_sdk_types::Secp256r1PublicKey;
8use sui_sdk_types::Secp256r1Signature;
9use sui_sdk_types::SignatureScheme;
10use sui_sdk_types::SimpleSignature;
11use sui_sdk_types::UserSignature;
12
13#[derive(Clone)]
14pub struct Secp256r1PrivateKey(SigningKey);
15
16impl std::fmt::Debug for Secp256r1PrivateKey {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 f.debug_tuple("Secp256r1PrivateKey")
19 .field(&"__elided__")
20 .finish()
21 }
22}
23
24#[cfg(test)]
25impl proptest::arbitrary::Arbitrary for Secp256r1PrivateKey {
26 type Parameters = ();
27 type Strategy = proptest::strategy::BoxedStrategy<Self>;
28 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
29 use proptest::strategy::Strategy;
30
31 proptest::arbitrary::any::<[u8; Self::LENGTH]>()
32 .prop_map(Self::new)
33 .boxed()
34 }
35}
36
37impl Secp256r1PrivateKey {
38 pub const LENGTH: usize = 32;
40
41 pub fn new(bytes: [u8; Self::LENGTH]) -> Self {
42 Self(SigningKey::from_bytes(&bytes.into()).unwrap())
43 }
44
45 pub fn scheme(&self) -> SignatureScheme {
46 SignatureScheme::Secp256r1
47 }
48
49 pub fn verifying_key(&self) -> Secp256r1VerifyingKey {
50 let verifying_key = self.0.verifying_key();
51 Secp256r1VerifyingKey(*verifying_key)
52 }
53
54 pub fn public_key(&self) -> Secp256r1PublicKey {
55 Secp256r1PublicKey::new(self.0.verifying_key().as_ref().to_bytes().into())
56 }
57
58 pub fn generate<R>(mut rng: R) -> Self
59 where
60 R: rand_core::RngCore + rand_core::CryptoRng,
61 {
62 let mut buf: [u8; Self::LENGTH] = [0; Self::LENGTH];
63 rng.fill_bytes(&mut buf);
64 Self::new(buf)
65 }
66
67 #[cfg(feature = "pem")]
68 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
69 pub fn from_der(bytes: &[u8]) -> Result<Self, SignatureError> {
71 p256::pkcs8::DecodePrivateKey::from_pkcs8_der(bytes)
72 .map(Self)
73 .map_err(SignatureError::from_source)
74 }
75
76 #[cfg(feature = "pem")]
77 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
78 pub fn to_der(&self) -> Result<Vec<u8>, SignatureError> {
80 use p256::pkcs8::EncodePrivateKey;
81
82 self.0
83 .to_pkcs8_der()
84 .map_err(SignatureError::from_source)
85 .map(|der| der.as_bytes().to_owned())
86 }
87
88 #[cfg(feature = "pem")]
89 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
90 pub fn from_pem(s: &str) -> Result<Self, SignatureError> {
92 p256::pkcs8::DecodePrivateKey::from_pkcs8_pem(s)
93 .map(Self)
94 .map_err(SignatureError::from_source)
95 }
96
97 #[cfg(feature = "pem")]
98 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
99 pub fn to_pem(&self) -> Result<String, SignatureError> {
101 use pkcs8::EncodePrivateKey;
102
103 self.0
104 .to_pkcs8_pem(pkcs8::LineEnding::default())
105 .map_err(SignatureError::from_source)
106 .map(|pem| (*pem).to_owned())
107 }
108
109 #[cfg(feature = "pem")]
110 pub(crate) fn from_p256(private_key: SigningKey) -> Self {
111 Self(private_key)
112 }
113
114 #[cfg(feature = "bech32")]
115 #[cfg_attr(doc_cfg, doc(cfg(feature = "bech32")))]
116 pub fn from_suiprivkey(s: &str) -> Result<Self, SignatureError> {
122 let (scheme, key) = crate::suipriv::decode(s)?;
123 if scheme != SignatureScheme::Secp256r1 {
124 return Err(SignatureError::from_source(format!(
125 "suipriv scheme flag is `{}`, expected `secp256r1`",
126 scheme.name(),
127 )));
128 }
129 let bytes: [u8; Self::LENGTH] = key.try_into().map_err(|_: Vec<u8>| {
130 SignatureError::from_source("suipriv key has invalid length for secp256r1")
131 })?;
132 Ok(Self::new(bytes))
133 }
134
135 #[cfg(feature = "bech32")]
136 #[cfg_attr(doc_cfg, doc(cfg(feature = "bech32")))]
137 pub fn to_suiprivkey(&self) -> Result<String, SignatureError> {
139 let bytes = self.0.to_bytes();
140 crate::suipriv::encode(SignatureScheme::Secp256r1, &bytes)
141 }
142}
143
144impl Signer<Secp256r1Signature> for Secp256r1PrivateKey {
145 fn try_sign(&self, message: &[u8]) -> Result<Secp256r1Signature, SignatureError> {
146 let signature: p256::ecdsa::Signature = self.0.try_sign(message)?;
147 Ok(Secp256r1Signature::new(signature.to_bytes().into()))
148 }
149}
150
151impl Signer<SimpleSignature> for Secp256r1PrivateKey {
152 fn try_sign(&self, msg: &[u8]) -> Result<SimpleSignature, SignatureError> {
153 <Self as Signer<Secp256r1Signature>>::try_sign(self, msg).map(|signature| {
154 SimpleSignature::Secp256r1 {
155 signature,
156 public_key: self.public_key(),
157 }
158 })
159 }
160}
161
162impl Signer<UserSignature> for Secp256r1PrivateKey {
163 fn try_sign(&self, msg: &[u8]) -> Result<UserSignature, SignatureError> {
164 <Self as Signer<SimpleSignature>>::try_sign(self, msg).map(UserSignature::Simple)
165 }
166}
167
168#[derive(Debug, Clone, Eq, PartialEq)]
169pub struct Secp256r1VerifyingKey(VerifyingKey);
170
171impl Secp256r1VerifyingKey {
172 pub fn new(public_key: &Secp256r1PublicKey) -> Result<Self, SignatureError> {
173 VerifyingKey::try_from(public_key.inner().as_ref()).map(Self)
174 }
175
176 pub fn public_key(&self) -> Secp256r1PublicKey {
177 Secp256r1PublicKey::new(self.0.as_ref().to_bytes().into())
178 }
179
180 #[cfg(feature = "pem")]
181 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
182 pub fn from_der(bytes: &[u8]) -> Result<Self, SignatureError> {
184 p256::pkcs8::DecodePublicKey::from_public_key_der(bytes)
185 .map(Self)
186 .map_err(SignatureError::from_source)
187 }
188
189 #[cfg(feature = "pem")]
190 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
191 pub fn to_der(&self) -> Result<Vec<u8>, SignatureError> {
193 use pkcs8::EncodePublicKey;
194
195 self.0
196 .to_public_key_der()
197 .map_err(SignatureError::from_source)
198 .map(|der| der.into_vec())
199 }
200
201 #[cfg(feature = "pem")]
202 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
203 pub fn from_pem(s: &str) -> Result<Self, SignatureError> {
205 p256::pkcs8::DecodePublicKey::from_public_key_pem(s)
206 .map(Self)
207 .map_err(SignatureError::from_source)
208 }
209
210 #[cfg(feature = "pem")]
211 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
212 pub fn to_pem(&self) -> Result<String, SignatureError> {
214 use pkcs8::EncodePublicKey;
215
216 self.0
217 .to_public_key_pem(pkcs8::LineEnding::default())
218 .map_err(SignatureError::from_source)
219 }
220
221 #[cfg(feature = "pem")]
222 pub(crate) fn from_p256(verifying_key: VerifyingKey) -> Self {
223 Self(verifying_key)
224 }
225}
226
227impl Verifier<Secp256r1Signature> for Secp256r1VerifyingKey {
228 fn verify(&self, message: &[u8], signature: &Secp256r1Signature) -> Result<(), SignatureError> {
229 let signature = p256::ecdsa::Signature::from_bytes(signature.inner().into())?;
230 self.0.verify(message, &signature)
231 }
232}
233
234impl Verifier<SimpleSignature> for Secp256r1VerifyingKey {
235 fn verify(&self, message: &[u8], signature: &SimpleSignature) -> Result<(), SignatureError> {
236 let SimpleSignature::Secp256r1 {
237 signature,
238 public_key,
239 } = signature
240 else {
241 return Err(SignatureError::from_source("not a secp256r1 signature"));
242 };
243
244 if public_key.inner() != self.public_key().inner() {
245 return Err(SignatureError::from_source(
246 "public_key in signature does not match",
247 ));
248 }
249
250 <Self as Verifier<Secp256r1Signature>>::verify(self, message, signature)
251 }
252}
253
254impl Verifier<UserSignature> for Secp256r1VerifyingKey {
255 fn verify(&self, message: &[u8], signature: &UserSignature) -> Result<(), SignatureError> {
256 let UserSignature::Simple(signature) = signature else {
257 return Err(SignatureError::from_source("not a secp256r1 signature"));
258 };
259
260 <Self as Verifier<SimpleSignature>>::verify(self, message, signature)
261 }
262}
263
264#[derive(Default, Clone, Debug)]
265pub struct Secp256r1Verifier {}
266
267impl Secp256r1Verifier {
268 pub fn new() -> Self {
269 Self {}
270 }
271}
272
273impl Verifier<SimpleSignature> for Secp256r1Verifier {
274 fn verify(&self, message: &[u8], signature: &SimpleSignature) -> Result<(), SignatureError> {
275 let SimpleSignature::Secp256r1 {
276 signature,
277 public_key,
278 } = signature
279 else {
280 return Err(SignatureError::from_source("not a secp256r1 signature"));
281 };
282
283 let verifying_key = Secp256r1VerifyingKey::new(public_key)?;
284
285 verifying_key.verify(message, signature)
286 }
287}
288
289impl Verifier<UserSignature> for Secp256r1Verifier {
290 fn verify(&self, message: &[u8], signature: &UserSignature) -> Result<(), SignatureError> {
291 let UserSignature::Simple(signature) = signature else {
292 return Err(SignatureError::from_source("not a secp256r1 signature"));
293 };
294
295 <Self as Verifier<SimpleSignature>>::verify(self, message, signature)
296 }
297}
298
299#[cfg(test)]
300mod test {
301 use super::*;
302 use crate::SuiSigner;
303 use crate::SuiVerifier;
304 use sui_sdk_types::PersonalMessage;
305 use test_strategy::proptest;
306
307 #[cfg(target_arch = "wasm32")]
308 use wasm_bindgen_test::wasm_bindgen_test as test;
309
310 #[proptest]
321 fn personal_message_signing(signer: Secp256r1PrivateKey, message: Vec<u8>) {
322 let message = PersonalMessage(message.into());
323 let signature = signer.sign_personal_message(&message).unwrap();
324 let verifying_key = signer.verifying_key();
325 verifying_key
326 .verify_personal_message(&message, &signature)
327 .unwrap();
328
329 let verifier = Secp256r1Verifier::default();
330 verifier
331 .verify_personal_message(&message, &signature)
332 .unwrap();
333 }
334
335 #[test]
336 fn personal_message_signing_fixture() {
337 let key = [
338 167, 44, 116, 0, 51, 221, 254, 179, 210, 44, 93, 196, 125, 155, 85, 94, 29, 41, 13, 60,
339 59, 132, 69, 84, 176, 217, 77, 49, 25, 113, 118, 125,
340 ];
341 let signer = Secp256r1PrivateKey::new(key);
342
343 let message = PersonalMessage(b"hello".into());
344 let sig = signer.sign_personal_message(&message).unwrap();
345 let external_sig = "AlqWPdkIE2bZAUquKv2Tdh9i+Ih+rVSQXH/YsgvwkmeOJR0YLjL/kadivoPtiQkvZBQ1ZI8eDZxe8SaLniwoT88Dh+/vAuGf1UrouFTdefpBEWn3apy8x3EexN5c5ESzGDc=";
346 let b64 = sig.to_base64();
347 assert_eq!(external_sig, b64);
348 }
349}