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
13pub struct Secp256k1PrivateKey(SigningKey);
14
15impl std::fmt::Debug for Secp256k1PrivateKey {
16 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17 f.debug_tuple("Secp256k1PrivateKey")
18 .field(&"__elided__")
19 .finish()
20 }
21}
22
23#[cfg(test)]
24impl proptest::arbitrary::Arbitrary for Secp256k1PrivateKey {
25 type Parameters = ();
26 type Strategy = proptest::strategy::BoxedStrategy<Self>;
27 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
28 use proptest::strategy::Strategy;
29
30 proptest::arbitrary::any::<[u8; Self::LENGTH]>()
31 .prop_filter_map("invalid secp256k1 private key", |bytes| {
32 Self::new(bytes).ok()
33 })
34 .boxed()
35 }
36}
37
38impl Secp256k1PrivateKey {
39 pub const LENGTH: usize = 32;
41
42 pub fn new(bytes: [u8; Self::LENGTH]) -> Result<Self, SignatureError> {
43 SigningKey::from_bytes(&bytes.into()).map(Self)
44 }
45
46 pub fn scheme(&self) -> SignatureScheme {
47 SignatureScheme::Secp256k1
48 }
49
50 pub fn verifying_key(&self) -> Secp256k1VerifyingKey {
51 let verifying_key = self.0.verifying_key();
52 Secp256k1VerifyingKey(*verifying_key)
53 }
54
55 pub fn public_key(&self) -> Secp256k1PublicKey {
56 Secp256k1PublicKey::new(self.0.verifying_key().as_ref().to_bytes().into())
57 }
58
59 pub fn generate<R>(mut rng: R) -> Self
60 where
61 R: rand_core::RngCore + rand_core::CryptoRng,
62 {
63 Self(SigningKey::random(&mut rng))
64 }
65
66 #[cfg(feature = "pem")]
67 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
68 pub fn from_der(bytes: &[u8]) -> Result<Self, SignatureError> {
70 k256::pkcs8::DecodePrivateKey::from_pkcs8_der(bytes)
71 .map(Self)
72 .map_err(SignatureError::from_source)
73 }
74
75 #[cfg(feature = "pem")]
76 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
77 pub fn to_der(&self) -> Result<Vec<u8>, SignatureError> {
79 use k256::pkcs8::EncodePrivateKey;
80
81 self.0
82 .to_pkcs8_der()
83 .map_err(SignatureError::from_source)
84 .map(|der| der.as_bytes().to_owned())
85 }
86
87 #[cfg(feature = "pem")]
88 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
89 pub fn from_pem(s: &str) -> Result<Self, SignatureError> {
91 k256::pkcs8::DecodePrivateKey::from_pkcs8_pem(s)
92 .map(Self)
93 .map_err(SignatureError::from_source)
94 }
95
96 #[cfg(feature = "pem")]
97 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
98 pub fn to_pem(&self) -> Result<String, SignatureError> {
100 use pkcs8::EncodePrivateKey;
101
102 self.0
103 .to_pkcs8_pem(pkcs8::LineEnding::default())
104 .map_err(SignatureError::from_source)
105 .map(|pem| (*pem).to_owned())
106 }
107
108 #[cfg(feature = "pem")]
109 pub(crate) fn from_k256(private_key: SigningKey) -> Self {
110 Self(private_key)
111 }
112}
113
114impl Signer<Secp256k1Signature> for Secp256k1PrivateKey {
115 fn try_sign(&self, message: &[u8]) -> Result<Secp256k1Signature, SignatureError> {
116 let signature: k256::ecdsa::Signature = self.0.try_sign(message)?;
117 Ok(Secp256k1Signature::new(signature.to_bytes().into()))
118 }
119}
120
121impl Signer<SimpleSignature> for Secp256k1PrivateKey {
122 fn try_sign(&self, msg: &[u8]) -> Result<SimpleSignature, SignatureError> {
123 <Self as Signer<Secp256k1Signature>>::try_sign(self, msg).map(|signature| {
124 SimpleSignature::Secp256k1 {
125 signature,
126 public_key: self.public_key(),
127 }
128 })
129 }
130}
131
132impl Signer<UserSignature> for Secp256k1PrivateKey {
133 fn try_sign(&self, msg: &[u8]) -> Result<UserSignature, SignatureError> {
134 <Self as Signer<SimpleSignature>>::try_sign(self, msg).map(UserSignature::Simple)
135 }
136}
137
138#[derive(Debug)]
139pub struct Secp256k1VerifyingKey(VerifyingKey);
140
141impl Secp256k1VerifyingKey {
142 pub fn new(public_key: &Secp256k1PublicKey) -> Result<Self, SignatureError> {
143 VerifyingKey::try_from(public_key.inner().as_ref()).map(Self)
144 }
145
146 pub fn public_key(&self) -> Secp256k1PublicKey {
147 Secp256k1PublicKey::new(self.0.as_ref().to_bytes().into())
148 }
149
150 #[cfg(feature = "pem")]
151 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
152 pub fn from_der(bytes: &[u8]) -> Result<Self, SignatureError> {
154 k256::pkcs8::DecodePublicKey::from_public_key_der(bytes)
155 .map(Self)
156 .map_err(SignatureError::from_source)
157 }
158
159 #[cfg(feature = "pem")]
160 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
161 pub fn to_der(&self) -> Result<Vec<u8>, SignatureError> {
163 use pkcs8::EncodePublicKey;
164
165 self.0
166 .to_public_key_der()
167 .map_err(SignatureError::from_source)
168 .map(|der| der.into_vec())
169 }
170
171 #[cfg(feature = "pem")]
172 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
173 pub fn from_pem(s: &str) -> Result<Self, SignatureError> {
175 k256::pkcs8::DecodePublicKey::from_public_key_pem(s)
176 .map(Self)
177 .map_err(SignatureError::from_source)
178 }
179
180 #[cfg(feature = "pem")]
181 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
182 pub fn to_pem(&self) -> Result<String, SignatureError> {
184 use pkcs8::EncodePublicKey;
185
186 self.0
187 .to_public_key_pem(pkcs8::LineEnding::default())
188 .map_err(SignatureError::from_source)
189 }
190
191 #[cfg(feature = "pem")]
192 pub(crate) fn from_k256(verifying_key: VerifyingKey) -> Self {
193 Self(verifying_key)
194 }
195}
196
197impl Verifier<Secp256k1Signature> for Secp256k1VerifyingKey {
198 fn verify(&self, message: &[u8], signature: &Secp256k1Signature) -> Result<(), SignatureError> {
199 let signature = k256::ecdsa::Signature::from_bytes(signature.inner().into())?;
200 self.0.verify(message, &signature)
201 }
202}
203
204impl Verifier<SimpleSignature> for Secp256k1VerifyingKey {
205 fn verify(&self, message: &[u8], signature: &SimpleSignature) -> Result<(), SignatureError> {
206 let SimpleSignature::Secp256k1 {
207 signature,
208 public_key,
209 } = signature
210 else {
211 return Err(SignatureError::from_source("not a secp256k1 signature"));
212 };
213
214 if public_key.inner() != self.public_key().inner() {
215 return Err(SignatureError::from_source(
216 "public_key in signature does not match",
217 ));
218 }
219
220 <Self as Verifier<Secp256k1Signature>>::verify(self, message, signature)
221 }
222}
223
224impl Verifier<UserSignature> for Secp256k1VerifyingKey {
225 fn verify(&self, message: &[u8], signature: &UserSignature) -> Result<(), SignatureError> {
226 let UserSignature::Simple(signature) = signature else {
227 return Err(SignatureError::from_source("not a secp256k1 signature"));
228 };
229
230 <Self as Verifier<SimpleSignature>>::verify(self, message, signature)
231 }
232}
233
234#[derive(Default, Clone, Debug)]
235pub struct Secp256k1Verifier {}
236
237impl Secp256k1Verifier {
238 pub fn new() -> Self {
239 Self {}
240 }
241}
242
243impl Verifier<SimpleSignature> for Secp256k1Verifier {
244 fn verify(&self, message: &[u8], signature: &SimpleSignature) -> Result<(), SignatureError> {
245 let SimpleSignature::Secp256k1 {
246 signature,
247 public_key,
248 } = signature
249 else {
250 return Err(SignatureError::from_source("not a secp256k1 signature"));
251 };
252
253 let verifying_key = Secp256k1VerifyingKey::new(public_key)?;
254
255 verifying_key.verify(message, signature)
256 }
257}
258
259impl Verifier<UserSignature> for Secp256k1Verifier {
260 fn verify(&self, message: &[u8], signature: &UserSignature) -> Result<(), SignatureError> {
261 let UserSignature::Simple(signature) = signature else {
262 return Err(SignatureError::from_source("not a secp256k1 signature"));
263 };
264
265 <Self as Verifier<SimpleSignature>>::verify(self, message, signature)
266 }
267}
268
269#[cfg(test)]
270mod test {
271 use super::*;
272 use crate::SuiSigner;
273 use crate::SuiVerifier;
274 use sui_sdk_types::PersonalMessage;
275 use test_strategy::proptest;
276
277 #[cfg(target_arch = "wasm32")]
278 use wasm_bindgen_test::wasm_bindgen_test as test;
279
280 #[proptest]
291 fn personal_message_signing(signer: Secp256k1PrivateKey, message: Vec<u8>) {
292 let message = PersonalMessage(message.into());
293 let signature = signer.sign_personal_message(&message).unwrap();
294 let verifying_key = signer.verifying_key();
295 verifying_key
296 .verify_personal_message(&message, &signature)
297 .unwrap();
298
299 let verifier = Secp256k1Verifier::default();
300 verifier
301 .verify_personal_message(&message, &signature)
302 .unwrap();
303 }
304
305 #[test]
306 fn personal_message_signing_fixture() {
307 let key = [
308 172, 12, 96, 180, 207, 143, 111, 151, 81, 57, 242, 89, 74, 5, 150, 51, 56, 111, 245,
309 150, 182, 30, 149, 178, 29, 255, 188, 27, 48, 241, 151, 193,
310 ];
311
312 let signer = Secp256k1PrivateKey::new(key).unwrap();
313
314 let message = PersonalMessage(b"hello".into());
315 let sig = signer.sign_personal_message(&message).unwrap();
316 let external_sig = "AVFAWGjuD8+xUoc6jMC0lKqMtT+4ukln7vz+8Nuv+EbYKl47jwzOWn39maDsqu81kezLPgLzz6o/AfSE0M9+jVwClcrtiuyUggEt/6CEZi8+JQ+NS9TmOhPBZV2X1KjhGCw=";
317 let b64 = sig.to_base64();
318 assert_eq!(external_sig, b64);
319 }
320}