1use crate::SignatureError;
2use k256::ecdsa::SigningKey;
3use k256::ecdsa::VerifyingKey;
4use k256::elliptic_curve::group::GroupEncoding;
5use signature::Signer;
6use signature::Verifier;
7use sui_sdk_types::Secp256k1PublicKey;
8use sui_sdk_types::Secp256k1Signature;
9use sui_sdk_types::SignatureScheme;
10use sui_sdk_types::SimpleSignature;
11use sui_sdk_types::UserSignature;
12
13#[derive(Clone)]
14pub struct Secp256k1PrivateKey(SigningKey);
15
16impl std::fmt::Debug for Secp256k1PrivateKey {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 f.debug_tuple("Secp256k1PrivateKey")
19 .field(&"__elided__")
20 .finish()
21 }
22}
23
24#[cfg(test)]
25impl proptest::arbitrary::Arbitrary for Secp256k1PrivateKey {
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_filter_map("invalid secp256k1 private key", |bytes| {
33 Self::new(bytes).ok()
34 })
35 .boxed()
36 }
37}
38
39impl Secp256k1PrivateKey {
40 pub const LENGTH: usize = 32;
42
43 pub fn new(bytes: [u8; Self::LENGTH]) -> Result<Self, SignatureError> {
44 SigningKey::from_bytes(&bytes.into()).map(Self)
45 }
46
47 pub fn scheme(&self) -> SignatureScheme {
48 SignatureScheme::Secp256k1
49 }
50
51 pub fn verifying_key(&self) -> Secp256k1VerifyingKey {
52 let verifying_key = self.0.verifying_key();
53 Secp256k1VerifyingKey(*verifying_key)
54 }
55
56 pub fn public_key(&self) -> Secp256k1PublicKey {
57 Secp256k1PublicKey::new(self.0.verifying_key().as_ref().to_bytes().into())
58 }
59
60 pub fn generate<R>(mut rng: R) -> Self
61 where
62 R: rand_core::RngCore + rand_core::CryptoRng,
63 {
64 Self(SigningKey::random(&mut rng))
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 k256::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 k256::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 k256::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_k256(private_key: SigningKey) -> Self {
111 Self(private_key)
112 }
113
114 fn from_flagged_key_bytes(
117 scheme: SignatureScheme,
118 key: Vec<u8>,
119 ) -> Result<Self, SignatureError> {
120 if scheme != SignatureScheme::Secp256k1 {
121 return Err(SignatureError::from_source(format!(
122 "private key scheme flag is `{}`, expected `secp256k1`",
123 scheme.name(),
124 )));
125 }
126 let bytes: [u8; Self::LENGTH] = key.try_into().map_err(|_: Vec<u8>| {
127 SignatureError::from_source("private key has invalid length for secp256k1")
128 })?;
129 Self::new(bytes)
130 }
131
132 #[cfg(feature = "bech32")]
133 #[cfg_attr(doc_cfg, doc(cfg(feature = "bech32")))]
134 pub fn from_suiprivkey(s: &str) -> Result<Self, SignatureError> {
141 let (scheme, key) = crate::suipriv::decode(s)?;
142 Self::from_flagged_key_bytes(scheme, key)
143 }
144
145 #[cfg(feature = "bech32")]
146 #[cfg_attr(doc_cfg, doc(cfg(feature = "bech32")))]
147 pub fn to_suiprivkey(&self) -> Result<String, SignatureError> {
149 let bytes = self.0.to_bytes();
150 crate::suipriv::encode(SignatureScheme::Secp256k1, &bytes)
151 }
152
153 pub fn from_base64(s: &str) -> Result<Self, SignatureError> {
160 let (scheme, key) = crate::suipriv::decode_base64(s)?;
161 Self::from_flagged_key_bytes(scheme, key)
162 }
163
164 pub fn to_base64(&self) -> String {
168 let bytes = self.0.to_bytes();
169 crate::suipriv::encode_base64(SignatureScheme::Secp256k1, &bytes)
170 }
171}
172
173impl Signer<Secp256k1Signature> for Secp256k1PrivateKey {
174 fn try_sign(&self, message: &[u8]) -> Result<Secp256k1Signature, SignatureError> {
175 let signature: k256::ecdsa::Signature = self.0.try_sign(message)?;
176 Ok(Secp256k1Signature::new(signature.to_bytes().into()))
177 }
178}
179
180impl Signer<SimpleSignature> for Secp256k1PrivateKey {
181 fn try_sign(&self, msg: &[u8]) -> Result<SimpleSignature, SignatureError> {
182 <Self as Signer<Secp256k1Signature>>::try_sign(self, msg).map(|signature| {
183 SimpleSignature::Secp256k1 {
184 signature,
185 public_key: self.public_key(),
186 }
187 })
188 }
189}
190
191impl Signer<UserSignature> for Secp256k1PrivateKey {
192 fn try_sign(&self, msg: &[u8]) -> Result<UserSignature, SignatureError> {
193 <Self as Signer<SimpleSignature>>::try_sign(self, msg).map(UserSignature::Simple)
194 }
195}
196
197#[derive(Debug, Clone, Eq, PartialEq)]
198pub struct Secp256k1VerifyingKey(VerifyingKey);
199
200impl Secp256k1VerifyingKey {
201 pub fn new(public_key: &Secp256k1PublicKey) -> Result<Self, SignatureError> {
202 VerifyingKey::try_from(public_key.inner().as_ref()).map(Self)
203 }
204
205 pub fn public_key(&self) -> Secp256k1PublicKey {
206 Secp256k1PublicKey::new(self.0.as_ref().to_bytes().into())
207 }
208
209 #[cfg(feature = "pem")]
210 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
211 pub fn from_der(bytes: &[u8]) -> Result<Self, SignatureError> {
213 k256::pkcs8::DecodePublicKey::from_public_key_der(bytes)
214 .map(Self)
215 .map_err(SignatureError::from_source)
216 }
217
218 #[cfg(feature = "pem")]
219 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
220 pub fn to_der(&self) -> Result<Vec<u8>, SignatureError> {
222 use pkcs8::EncodePublicKey;
223
224 self.0
225 .to_public_key_der()
226 .map_err(SignatureError::from_source)
227 .map(|der| der.into_vec())
228 }
229
230 #[cfg(feature = "pem")]
231 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
232 pub fn from_pem(s: &str) -> Result<Self, SignatureError> {
234 k256::pkcs8::DecodePublicKey::from_public_key_pem(s)
235 .map(Self)
236 .map_err(SignatureError::from_source)
237 }
238
239 #[cfg(feature = "pem")]
240 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
241 pub fn to_pem(&self) -> Result<String, SignatureError> {
243 use pkcs8::EncodePublicKey;
244
245 self.0
246 .to_public_key_pem(pkcs8::LineEnding::default())
247 .map_err(SignatureError::from_source)
248 }
249
250 #[cfg(feature = "pem")]
251 pub(crate) fn from_k256(verifying_key: VerifyingKey) -> Self {
252 Self(verifying_key)
253 }
254}
255
256impl Verifier<Secp256k1Signature> for Secp256k1VerifyingKey {
257 fn verify(&self, message: &[u8], signature: &Secp256k1Signature) -> Result<(), SignatureError> {
258 let signature = k256::ecdsa::Signature::from_bytes(signature.inner().into())?;
259 self.0.verify(message, &signature)
260 }
261}
262
263impl Verifier<SimpleSignature> for Secp256k1VerifyingKey {
264 fn verify(&self, message: &[u8], signature: &SimpleSignature) -> Result<(), SignatureError> {
265 let SimpleSignature::Secp256k1 {
266 signature,
267 public_key,
268 } = signature
269 else {
270 return Err(SignatureError::from_source("not a secp256k1 signature"));
271 };
272
273 if public_key.inner() != self.public_key().inner() {
274 return Err(SignatureError::from_source(
275 "public_key in signature does not match",
276 ));
277 }
278
279 <Self as Verifier<Secp256k1Signature>>::verify(self, message, signature)
280 }
281}
282
283impl Verifier<UserSignature> for Secp256k1VerifyingKey {
284 fn verify(&self, message: &[u8], signature: &UserSignature) -> Result<(), SignatureError> {
285 let UserSignature::Simple(signature) = signature else {
286 return Err(SignatureError::from_source("not a secp256k1 signature"));
287 };
288
289 <Self as Verifier<SimpleSignature>>::verify(self, message, signature)
290 }
291}
292
293#[derive(Default, Clone, Debug)]
294pub struct Secp256k1Verifier {}
295
296impl Secp256k1Verifier {
297 pub fn new() -> Self {
298 Self {}
299 }
300}
301
302impl Verifier<SimpleSignature> for Secp256k1Verifier {
303 fn verify(&self, message: &[u8], signature: &SimpleSignature) -> Result<(), SignatureError> {
304 let SimpleSignature::Secp256k1 {
305 signature,
306 public_key,
307 } = signature
308 else {
309 return Err(SignatureError::from_source("not a secp256k1 signature"));
310 };
311
312 let verifying_key = Secp256k1VerifyingKey::new(public_key)?;
313
314 verifying_key.verify(message, signature)
315 }
316}
317
318impl Verifier<UserSignature> for Secp256k1Verifier {
319 fn verify(&self, message: &[u8], signature: &UserSignature) -> Result<(), SignatureError> {
320 let UserSignature::Simple(signature) = signature else {
321 return Err(SignatureError::from_source("not a secp256k1 signature"));
322 };
323
324 <Self as Verifier<SimpleSignature>>::verify(self, message, signature)
325 }
326}
327
328#[cfg(test)]
329mod test {
330 use super::*;
331 use crate::SuiSigner;
332 use crate::SuiVerifier;
333 use sui_sdk_types::PersonalMessage;
334 use test_strategy::proptest;
335
336 #[cfg(target_arch = "wasm32")]
337 use wasm_bindgen_test::wasm_bindgen_test as test;
338
339 #[proptest]
350 fn personal_message_signing(signer: Secp256k1PrivateKey, message: Vec<u8>) {
351 let message = PersonalMessage(message.into());
352 let signature = signer.sign_personal_message(&message).unwrap();
353 let verifying_key = signer.verifying_key();
354 verifying_key
355 .verify_personal_message(&message, &signature)
356 .unwrap();
357
358 let verifier = Secp256k1Verifier::default();
359 verifier
360 .verify_personal_message(&message, &signature)
361 .unwrap();
362 }
363
364 #[test]
365 fn personal_message_signing_fixture() {
366 let key = [
367 172, 12, 96, 180, 207, 143, 111, 151, 81, 57, 242, 89, 74, 5, 150, 51, 56, 111, 245,
368 150, 182, 30, 149, 178, 29, 255, 188, 27, 48, 241, 151, 193,
369 ];
370
371 let signer = Secp256k1PrivateKey::new(key).unwrap();
372
373 let message = PersonalMessage(b"hello".into());
374 let sig = signer.sign_personal_message(&message).unwrap();
375 let external_sig = "AVFAWGjuD8+xUoc6jMC0lKqMtT+4ukln7vz+8Nuv+EbYKl47jwzOWn39maDsqu81kezLPgLzz6o/AfSE0M9+jVwClcrtiuyUggEt/6CEZi8+JQ+NS9TmOhPBZV2X1KjhGCw=";
376 let b64 = sig.to_base64();
377 assert_eq!(external_sig, b64);
378 }
379}