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
115impl Signer<Secp256k1Signature> for Secp256k1PrivateKey {
116 fn try_sign(&self, message: &[u8]) -> Result<Secp256k1Signature, SignatureError> {
117 let signature: k256::ecdsa::Signature = self.0.try_sign(message)?;
118 Ok(Secp256k1Signature::new(signature.to_bytes().into()))
119 }
120}
121
122impl Signer<SimpleSignature> for Secp256k1PrivateKey {
123 fn try_sign(&self, msg: &[u8]) -> Result<SimpleSignature, SignatureError> {
124 <Self as Signer<Secp256k1Signature>>::try_sign(self, msg).map(|signature| {
125 SimpleSignature::Secp256k1 {
126 signature,
127 public_key: self.public_key(),
128 }
129 })
130 }
131}
132
133impl Signer<UserSignature> for Secp256k1PrivateKey {
134 fn try_sign(&self, msg: &[u8]) -> Result<UserSignature, SignatureError> {
135 <Self as Signer<SimpleSignature>>::try_sign(self, msg).map(UserSignature::Simple)
136 }
137}
138
139#[derive(Debug, Clone, Eq, PartialEq)]
140pub struct Secp256k1VerifyingKey(VerifyingKey);
141
142impl Secp256k1VerifyingKey {
143 pub fn new(public_key: &Secp256k1PublicKey) -> Result<Self, SignatureError> {
144 VerifyingKey::try_from(public_key.inner().as_ref()).map(Self)
145 }
146
147 pub fn public_key(&self) -> Secp256k1PublicKey {
148 Secp256k1PublicKey::new(self.0.as_ref().to_bytes().into())
149 }
150
151 #[cfg(feature = "pem")]
152 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
153 pub fn from_der(bytes: &[u8]) -> Result<Self, SignatureError> {
155 k256::pkcs8::DecodePublicKey::from_public_key_der(bytes)
156 .map(Self)
157 .map_err(SignatureError::from_source)
158 }
159
160 #[cfg(feature = "pem")]
161 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
162 pub fn to_der(&self) -> Result<Vec<u8>, SignatureError> {
164 use pkcs8::EncodePublicKey;
165
166 self.0
167 .to_public_key_der()
168 .map_err(SignatureError::from_source)
169 .map(|der| der.into_vec())
170 }
171
172 #[cfg(feature = "pem")]
173 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
174 pub fn from_pem(s: &str) -> Result<Self, SignatureError> {
176 k256::pkcs8::DecodePublicKey::from_public_key_pem(s)
177 .map(Self)
178 .map_err(SignatureError::from_source)
179 }
180
181 #[cfg(feature = "pem")]
182 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
183 pub fn to_pem(&self) -> Result<String, SignatureError> {
185 use pkcs8::EncodePublicKey;
186
187 self.0
188 .to_public_key_pem(pkcs8::LineEnding::default())
189 .map_err(SignatureError::from_source)
190 }
191
192 #[cfg(feature = "pem")]
193 pub(crate) fn from_k256(verifying_key: VerifyingKey) -> Self {
194 Self(verifying_key)
195 }
196}
197
198impl Verifier<Secp256k1Signature> for Secp256k1VerifyingKey {
199 fn verify(&self, message: &[u8], signature: &Secp256k1Signature) -> Result<(), SignatureError> {
200 let signature = k256::ecdsa::Signature::from_bytes(signature.inner().into())?;
201 self.0.verify(message, &signature)
202 }
203}
204
205impl Verifier<SimpleSignature> for Secp256k1VerifyingKey {
206 fn verify(&self, message: &[u8], signature: &SimpleSignature) -> Result<(), SignatureError> {
207 let SimpleSignature::Secp256k1 {
208 signature,
209 public_key,
210 } = signature
211 else {
212 return Err(SignatureError::from_source("not a secp256k1 signature"));
213 };
214
215 if public_key.inner() != self.public_key().inner() {
216 return Err(SignatureError::from_source(
217 "public_key in signature does not match",
218 ));
219 }
220
221 <Self as Verifier<Secp256k1Signature>>::verify(self, message, signature)
222 }
223}
224
225impl Verifier<UserSignature> for Secp256k1VerifyingKey {
226 fn verify(&self, message: &[u8], signature: &UserSignature) -> Result<(), SignatureError> {
227 let UserSignature::Simple(signature) = signature else {
228 return Err(SignatureError::from_source("not a secp256k1 signature"));
229 };
230
231 <Self as Verifier<SimpleSignature>>::verify(self, message, signature)
232 }
233}
234
235#[derive(Default, Clone, Debug)]
236pub struct Secp256k1Verifier {}
237
238impl Secp256k1Verifier {
239 pub fn new() -> Self {
240 Self {}
241 }
242}
243
244impl Verifier<SimpleSignature> for Secp256k1Verifier {
245 fn verify(&self, message: &[u8], signature: &SimpleSignature) -> Result<(), SignatureError> {
246 let SimpleSignature::Secp256k1 {
247 signature,
248 public_key,
249 } = signature
250 else {
251 return Err(SignatureError::from_source("not a secp256k1 signature"));
252 };
253
254 let verifying_key = Secp256k1VerifyingKey::new(public_key)?;
255
256 verifying_key.verify(message, signature)
257 }
258}
259
260impl Verifier<UserSignature> for Secp256k1Verifier {
261 fn verify(&self, message: &[u8], signature: &UserSignature) -> Result<(), SignatureError> {
262 let UserSignature::Simple(signature) = signature else {
263 return Err(SignatureError::from_source("not a secp256k1 signature"));
264 };
265
266 <Self as Verifier<SimpleSignature>>::verify(self, message, signature)
267 }
268}
269
270#[cfg(test)]
271mod test {
272 use super::*;
273 use crate::SuiSigner;
274 use crate::SuiVerifier;
275 use sui_sdk_types::PersonalMessage;
276 use test_strategy::proptest;
277
278 #[cfg(target_arch = "wasm32")]
279 use wasm_bindgen_test::wasm_bindgen_test as test;
280
281 #[proptest]
292 fn personal_message_signing(signer: Secp256k1PrivateKey, message: Vec<u8>) {
293 let message = PersonalMessage(message.into());
294 let signature = signer.sign_personal_message(&message).unwrap();
295 let verifying_key = signer.verifying_key();
296 verifying_key
297 .verify_personal_message(&message, &signature)
298 .unwrap();
299
300 let verifier = Secp256k1Verifier::default();
301 verifier
302 .verify_personal_message(&message, &signature)
303 .unwrap();
304 }
305
306 #[test]
307 fn personal_message_signing_fixture() {
308 let key = [
309 172, 12, 96, 180, 207, 143, 111, 151, 81, 57, 242, 89, 74, 5, 150, 51, 56, 111, 245,
310 150, 182, 30, 149, 178, 29, 255, 188, 27, 48, 241, 151, 193,
311 ];
312
313 let signer = Secp256k1PrivateKey::new(key).unwrap();
314
315 let message = PersonalMessage(b"hello".into());
316 let sig = signer.sign_personal_message(&message).unwrap();
317 let external_sig = "AVFAWGjuD8+xUoc6jMC0lKqMtT+4ukln7vz+8Nuv+EbYKl47jwzOWn39maDsqu81kezLPgLzz6o/AfSE0M9+jVwClcrtiuyUggEt/6CEZi8+JQ+NS9TmOhPBZV2X1KjhGCw=";
318 let b64 = sig.to_base64();
319 assert_eq!(external_sig, b64);
320 }
321}