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 fn from_flagged_key_bytes(
120 scheme: SignatureScheme,
121 key: Vec<u8>,
122 ) -> Result<Self, SignatureError> {
123 if scheme != SignatureScheme::Secp256r1 {
124 return Err(SignatureError::from_source(format!(
125 "private key 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("private key has invalid length for secp256r1")
131 })?;
132 SigningKey::from_bytes(&bytes.into())
133 .map(Self)
134 .map_err(SignatureError::from_source)
135 }
136
137 #[cfg(feature = "bech32")]
138 #[cfg_attr(doc_cfg, doc(cfg(feature = "bech32")))]
139 pub fn from_suiprivkey(s: &str) -> Result<Self, SignatureError> {
146 let (scheme, key) = crate::suipriv::decode(s)?;
147 Self::from_flagged_key_bytes(scheme, key)
148 }
149
150 #[cfg(feature = "bech32")]
151 #[cfg_attr(doc_cfg, doc(cfg(feature = "bech32")))]
152 pub fn to_suiprivkey(&self) -> Result<String, SignatureError> {
154 let bytes = self.0.to_bytes();
155 crate::suipriv::encode(SignatureScheme::Secp256r1, &bytes)
156 }
157
158 pub fn from_base64(s: &str) -> Result<Self, SignatureError> {
165 let (scheme, key) = crate::suipriv::decode_base64(s)?;
166 Self::from_flagged_key_bytes(scheme, key)
167 }
168
169 pub fn to_base64(&self) -> String {
173 let bytes = self.0.to_bytes();
174 crate::suipriv::encode_base64(SignatureScheme::Secp256r1, &bytes)
175 }
176}
177
178impl Signer<Secp256r1Signature> for Secp256r1PrivateKey {
179 fn try_sign(&self, message: &[u8]) -> Result<Secp256r1Signature, SignatureError> {
180 let signature: p256::ecdsa::Signature = self.0.try_sign(message)?;
181 Ok(Secp256r1Signature::new(signature.to_bytes().into()))
182 }
183}
184
185impl Signer<SimpleSignature> for Secp256r1PrivateKey {
186 fn try_sign(&self, msg: &[u8]) -> Result<SimpleSignature, SignatureError> {
187 <Self as Signer<Secp256r1Signature>>::try_sign(self, msg).map(|signature| {
188 SimpleSignature::Secp256r1 {
189 signature,
190 public_key: self.public_key(),
191 }
192 })
193 }
194}
195
196impl Signer<UserSignature> for Secp256r1PrivateKey {
197 fn try_sign(&self, msg: &[u8]) -> Result<UserSignature, SignatureError> {
198 <Self as Signer<SimpleSignature>>::try_sign(self, msg).map(UserSignature::Simple)
199 }
200}
201
202#[derive(Debug, Clone, Eq, PartialEq)]
203pub struct Secp256r1VerifyingKey(VerifyingKey);
204
205impl Secp256r1VerifyingKey {
206 pub fn new(public_key: &Secp256r1PublicKey) -> Result<Self, SignatureError> {
207 VerifyingKey::try_from(public_key.inner().as_ref()).map(Self)
208 }
209
210 pub fn public_key(&self) -> Secp256r1PublicKey {
211 Secp256r1PublicKey::new(self.0.as_ref().to_bytes().into())
212 }
213
214 #[cfg(feature = "pem")]
215 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
216 pub fn from_der(bytes: &[u8]) -> Result<Self, SignatureError> {
218 p256::pkcs8::DecodePublicKey::from_public_key_der(bytes)
219 .map(Self)
220 .map_err(SignatureError::from_source)
221 }
222
223 #[cfg(feature = "pem")]
224 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
225 pub fn to_der(&self) -> Result<Vec<u8>, SignatureError> {
227 use pkcs8::EncodePublicKey;
228
229 self.0
230 .to_public_key_der()
231 .map_err(SignatureError::from_source)
232 .map(|der| der.into_vec())
233 }
234
235 #[cfg(feature = "pem")]
236 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
237 pub fn from_pem(s: &str) -> Result<Self, SignatureError> {
239 p256::pkcs8::DecodePublicKey::from_public_key_pem(s)
240 .map(Self)
241 .map_err(SignatureError::from_source)
242 }
243
244 #[cfg(feature = "pem")]
245 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
246 pub fn to_pem(&self) -> Result<String, SignatureError> {
248 use pkcs8::EncodePublicKey;
249
250 self.0
251 .to_public_key_pem(pkcs8::LineEnding::default())
252 .map_err(SignatureError::from_source)
253 }
254
255 #[cfg(feature = "pem")]
256 pub(crate) fn from_p256(verifying_key: VerifyingKey) -> Self {
257 Self(verifying_key)
258 }
259}
260
261impl Verifier<Secp256r1Signature> for Secp256r1VerifyingKey {
262 fn verify(&self, message: &[u8], signature: &Secp256r1Signature) -> Result<(), SignatureError> {
263 let signature = p256::ecdsa::Signature::from_bytes(signature.inner().into())?;
264 self.0.verify(message, &signature)
265 }
266}
267
268impl Verifier<SimpleSignature> for Secp256r1VerifyingKey {
269 fn verify(&self, message: &[u8], signature: &SimpleSignature) -> Result<(), SignatureError> {
270 let SimpleSignature::Secp256r1 {
271 signature,
272 public_key,
273 } = signature
274 else {
275 return Err(SignatureError::from_source("not a secp256r1 signature"));
276 };
277
278 if public_key.inner() != self.public_key().inner() {
279 return Err(SignatureError::from_source(
280 "public_key in signature does not match",
281 ));
282 }
283
284 <Self as Verifier<Secp256r1Signature>>::verify(self, message, signature)
285 }
286}
287
288impl Verifier<UserSignature> for Secp256r1VerifyingKey {
289 fn verify(&self, message: &[u8], signature: &UserSignature) -> Result<(), SignatureError> {
290 let UserSignature::Simple(signature) = signature else {
291 return Err(SignatureError::from_source("not a secp256r1 signature"));
292 };
293
294 <Self as Verifier<SimpleSignature>>::verify(self, message, signature)
295 }
296}
297
298#[derive(Default, Clone, Debug)]
299pub struct Secp256r1Verifier {}
300
301impl Secp256r1Verifier {
302 pub fn new() -> Self {
303 Self {}
304 }
305}
306
307impl Verifier<SimpleSignature> for Secp256r1Verifier {
308 fn verify(&self, message: &[u8], signature: &SimpleSignature) -> Result<(), SignatureError> {
309 let SimpleSignature::Secp256r1 {
310 signature,
311 public_key,
312 } = signature
313 else {
314 return Err(SignatureError::from_source("not a secp256r1 signature"));
315 };
316
317 let verifying_key = Secp256r1VerifyingKey::new(public_key)?;
318
319 verifying_key.verify(message, signature)
320 }
321}
322
323impl Verifier<UserSignature> for Secp256r1Verifier {
324 fn verify(&self, message: &[u8], signature: &UserSignature) -> Result<(), SignatureError> {
325 let UserSignature::Simple(signature) = signature else {
326 return Err(SignatureError::from_source("not a secp256r1 signature"));
327 };
328
329 <Self as Verifier<SimpleSignature>>::verify(self, message, signature)
330 }
331}
332
333#[cfg(test)]
334mod test {
335 use super::*;
336 use crate::SuiSigner;
337 use crate::SuiVerifier;
338 use sui_sdk_types::PersonalMessage;
339 use test_strategy::proptest;
340
341 #[cfg(target_arch = "wasm32")]
342 use wasm_bindgen_test::wasm_bindgen_test as test;
343
344 #[proptest]
355 fn personal_message_signing(signer: Secp256r1PrivateKey, message: Vec<u8>) {
356 let message = PersonalMessage(message.into());
357 let signature = signer.sign_personal_message(&message).unwrap();
358 let verifying_key = signer.verifying_key();
359 verifying_key
360 .verify_personal_message(&message, &signature)
361 .unwrap();
362
363 let verifier = Secp256r1Verifier::default();
364 verifier
365 .verify_personal_message(&message, &signature)
366 .unwrap();
367 }
368
369 #[test]
370 fn personal_message_signing_fixture() {
371 let key = [
372 167, 44, 116, 0, 51, 221, 254, 179, 210, 44, 93, 196, 125, 155, 85, 94, 29, 41, 13, 60,
373 59, 132, 69, 84, 176, 217, 77, 49, 25, 113, 118, 125,
374 ];
375 let signer = Secp256r1PrivateKey::new(key);
376
377 let message = PersonalMessage(b"hello".into());
378 let sig = signer.sign_personal_message(&message).unwrap();
379 let external_sig = "AlqWPdkIE2bZAUquKv2Tdh9i+Ih+rVSQXH/YsgvwkmeOJR0YLjL/kadivoPtiQkvZBQ1ZI8eDZxe8SaLniwoT88Dh+/vAuGf1UrouFTdefpBEWn3apy8x3EexN5c5ESzGDc=";
380 let b64 = sig.to_base64();
381 assert_eq!(external_sig, b64);
382 }
383}