1use iota_types::{
6 Secp256r1PublicKey, Secp256r1Signature, SignatureScheme, SimpleSignature, UserSignature,
7};
8use p256::{
9 ecdsa::{SigningKey, VerifyingKey},
10 elliptic_curve::group::GroupEncoding,
11};
12use signature::{Signer, Verifier};
13
14use crate::SignatureError;
15
16#[derive(Clone, Eq, PartialEq)]
17pub struct Secp256r1PrivateKey(SigningKey);
18
19impl std::fmt::Debug for Secp256r1PrivateKey {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 f.debug_tuple("Secp256r1PrivateKey")
22 .field(&"__elided__")
23 .finish()
24 }
25}
26
27#[cfg(test)]
28impl proptest::arbitrary::Arbitrary for Secp256r1PrivateKey {
29 type Parameters = ();
30 type Strategy = proptest::strategy::BoxedStrategy<Self>;
31 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
32 use proptest::strategy::Strategy;
33
34 proptest::arbitrary::any::<[u8; Self::LENGTH]>()
35 .prop_map(Self::new)
36 .boxed()
37 }
38}
39
40impl Secp256r1PrivateKey {
41 pub const LENGTH: usize = 32;
43
44 pub fn new(bytes: [u8; Self::LENGTH]) -> Self {
45 Self(SigningKey::from_bytes(&bytes.into()).unwrap())
46 }
47
48 pub fn scheme(&self) -> SignatureScheme {
49 SignatureScheme::Secp256r1
50 }
51
52 pub fn verifying_key(&self) -> Secp256r1VerifyingKey {
53 let verifying_key = self.0.verifying_key();
54 Secp256r1VerifyingKey(*verifying_key)
55 }
56
57 pub fn public_key(&self) -> Secp256r1PublicKey {
58 Secp256r1PublicKey::new(self.0.verifying_key().as_ref().to_bytes().into())
59 }
60
61 pub fn generate<R>(mut rng: R) -> Self
62 where
63 R: rand_core::RngCore + rand_core::CryptoRng,
64 {
65 let mut buf: [u8; Self::LENGTH] = [0; Self::LENGTH];
66 rng.fill_bytes(&mut buf);
67 Self::new(buf)
68 }
69
70 #[cfg(feature = "pem")]
71 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
72 pub fn from_der(bytes: &[u8]) -> Result<Self, SignatureError> {
75 p256::pkcs8::DecodePrivateKey::from_pkcs8_der(bytes)
76 .map(Self)
77 .map_err(SignatureError::from_source)
78 }
79
80 #[cfg(feature = "pem")]
81 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
82 pub fn to_der(&self) -> Result<Vec<u8>, SignatureError> {
84 use p256::pkcs8::EncodePrivateKey;
85
86 self.0
87 .to_pkcs8_der()
88 .map_err(SignatureError::from_source)
89 .map(|der| der.as_bytes().to_owned())
90 }
91
92 #[cfg(feature = "pem")]
93 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
94 pub fn from_pem(s: &str) -> Result<Self, SignatureError> {
96 p256::pkcs8::DecodePrivateKey::from_pkcs8_pem(s)
97 .map(Self)
98 .map_err(SignatureError::from_source)
99 }
100
101 #[cfg(feature = "pem")]
102 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
103 pub fn to_pem(&self) -> Result<String, SignatureError> {
105 use pkcs8::EncodePrivateKey;
106
107 self.0
108 .to_pkcs8_pem(pkcs8::LineEnding::default())
109 .map_err(SignatureError::from_source)
110 .map(|pem| (*pem).to_owned())
111 }
112
113 #[cfg(feature = "pem")]
114 pub(crate) fn from_p256(private_key: SigningKey) -> Self {
115 Self(private_key)
116 }
117}
118
119impl crate::ToFromBytes for Secp256r1PrivateKey {
120 type Error = crate::PrivateKeyError;
121 type ByteArray = [u8; Self::LENGTH];
122
123 fn to_bytes(&self) -> Self::ByteArray {
125 self.0.to_bytes().into()
126 }
127
128 fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
129 if bytes.len() != Self::LENGTH {
130 return Err(crate::PrivateKeyError::InvalidScheme(
131 "invalid secp256r1 key length".to_string(),
132 ));
133 }
134
135 let mut arr = [0u8; Self::LENGTH];
136 arr.copy_from_slice(bytes);
137 Ok(Self::new(arr))
138 }
139}
140
141impl crate::PrivateKeyScheme for Secp256r1PrivateKey {
142 const SCHEME: SignatureScheme = SignatureScheme::Secp256r1;
143}
144
145#[cfg(feature = "mnemonic")]
146impl crate::FromMnemonic for Secp256r1PrivateKey {
147 type Error = crate::PrivateKeyError;
148
149 fn from_mnemonic(
150 phrase: &str,
151 account_index: impl Into<Option<u64>>,
152 password: impl Into<Option<String>>,
153 ) -> Result<Self, Self::Error>
154 where
155 Self: Sized,
156 {
157 let path = format!(
158 "m/{}'/{}'/0'/0/{}",
159 crate::DERIVATION_PATH_PURPOSE_SECP256R1,
160 crate::DERIVATION_PATH_COIN_TYPE,
161 account_index.into().unwrap_or_default()
162 );
163 Self::from_mnemonic_with_path(phrase, path, password)
164 }
165
166 fn from_mnemonic_with_path(
167 phrase: &str,
168 path: String,
169 password: impl Into<Option<String>>,
170 ) -> Result<Self, Self::Error>
171 where
172 Self: Sized,
173 {
174 use std::str::FromStr;
175
176 use crate::ToFromBytes;
177
178 let mnemonic = bip39::Mnemonic::parse_in_normalized(bip39::Language::English, phrase)?;
179 let seed = mnemonic.to_seed(password.into().unwrap_or_default());
180 let child_xprv =
181 bip32::XPrv::derive_from_path(seed, &bip32::DerivationPath::from_str(&path)?)?;
182 Self::from_bytes(&child_xprv.private_key().to_bytes())
183 }
184}
185
186impl Signer<Secp256r1Signature> for Secp256r1PrivateKey {
187 fn try_sign(&self, message: &[u8]) -> Result<Secp256r1Signature, SignatureError> {
188 let signature: p256::ecdsa::Signature = self.0.try_sign(message)?;
189 Ok(Secp256r1Signature::new(signature.to_bytes().into()))
190 }
191}
192
193impl Signer<SimpleSignature> for Secp256r1PrivateKey {
194 fn try_sign(&self, msg: &[u8]) -> Result<SimpleSignature, SignatureError> {
195 <Self as Signer<Secp256r1Signature>>::try_sign(self, msg).map(|signature| {
196 SimpleSignature::Secp256r1 {
197 signature,
198 public_key: self.public_key(),
199 }
200 })
201 }
202}
203
204impl Signer<UserSignature> for Secp256r1PrivateKey {
205 fn try_sign(&self, msg: &[u8]) -> Result<UserSignature, SignatureError> {
206 <Self as Signer<SimpleSignature>>::try_sign(self, msg).map(UserSignature::Simple)
207 }
208}
209
210#[derive(Debug, Clone, Eq, PartialEq)]
211pub struct Secp256r1VerifyingKey(VerifyingKey);
212
213impl Secp256r1VerifyingKey {
214 pub fn new(public_key: &Secp256r1PublicKey) -> Result<Self, SignatureError> {
215 VerifyingKey::try_from(public_key.inner().as_ref()).map(Self)
216 }
217
218 pub fn public_key(&self) -> Secp256r1PublicKey {
219 Secp256r1PublicKey::new(self.0.as_ref().to_bytes().into())
220 }
221
222 #[cfg(feature = "pem")]
223 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
224 pub fn from_der(bytes: &[u8]) -> Result<Self, SignatureError> {
226 p256::pkcs8::DecodePublicKey::from_public_key_der(bytes)
227 .map(Self)
228 .map_err(SignatureError::from_source)
229 }
230
231 #[cfg(feature = "pem")]
232 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
233 pub fn to_der(&self) -> Result<Vec<u8>, SignatureError> {
235 use pkcs8::EncodePublicKey;
236
237 self.0
238 .to_public_key_der()
239 .map_err(SignatureError::from_source)
240 .map(|der| der.into_vec())
241 }
242
243 #[cfg(feature = "pem")]
244 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
245 pub fn from_pem(s: &str) -> Result<Self, SignatureError> {
247 p256::pkcs8::DecodePublicKey::from_public_key_pem(s)
248 .map(Self)
249 .map_err(SignatureError::from_source)
250 }
251
252 #[cfg(feature = "pem")]
253 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
254 pub fn to_pem(&self) -> Result<String, SignatureError> {
256 use pkcs8::EncodePublicKey;
257
258 self.0
259 .to_public_key_pem(pkcs8::LineEnding::default())
260 .map_err(SignatureError::from_source)
261 }
262
263 #[cfg(feature = "pem")]
264 pub(crate) fn from_p256(verifying_key: VerifyingKey) -> Self {
265 Self(verifying_key)
266 }
267}
268
269impl Verifier<Secp256r1Signature> for Secp256r1VerifyingKey {
270 fn verify(&self, message: &[u8], signature: &Secp256r1Signature) -> Result<(), SignatureError> {
271 let signature = p256::ecdsa::Signature::from_bytes(signature.inner().into())?;
272 self.0.verify(message, &signature)
273 }
274}
275
276impl Verifier<SimpleSignature> for Secp256r1VerifyingKey {
277 fn verify(&self, message: &[u8], signature: &SimpleSignature) -> Result<(), SignatureError> {
278 let SimpleSignature::Secp256r1 {
279 signature,
280 public_key,
281 } = signature
282 else {
283 return Err(SignatureError::from_source("not a secp256r1 signature"));
284 };
285
286 if public_key.inner() != self.public_key().inner() {
287 return Err(SignatureError::from_source(
288 "public_key in signature does not match",
289 ));
290 }
291
292 <Self as Verifier<Secp256r1Signature>>::verify(self, message, signature)
293 }
294}
295
296impl Verifier<UserSignature> for Secp256r1VerifyingKey {
297 fn verify(&self, message: &[u8], signature: &UserSignature) -> Result<(), SignatureError> {
298 let UserSignature::Simple(signature) = signature else {
299 return Err(SignatureError::from_source("not a secp256r1 signature"));
300 };
301
302 <Self as Verifier<SimpleSignature>>::verify(self, message, signature)
303 }
304}
305
306#[derive(Default, Clone, Debug)]
307pub struct Secp256r1Verifier {}
308
309impl Secp256r1Verifier {
310 pub fn new() -> Self {
311 Self {}
312 }
313}
314
315impl Verifier<SimpleSignature> for Secp256r1Verifier {
316 fn verify(&self, message: &[u8], signature: &SimpleSignature) -> Result<(), SignatureError> {
317 let SimpleSignature::Secp256r1 {
318 signature,
319 public_key,
320 } = signature
321 else {
322 return Err(SignatureError::from_source("not a secp256r1 signature"));
323 };
324
325 let verifying_key = Secp256r1VerifyingKey::new(public_key)?;
326
327 verifying_key.verify(message, signature)
328 }
329}
330
331impl Verifier<UserSignature> for Secp256r1Verifier {
332 fn verify(&self, message: &[u8], signature: &UserSignature) -> Result<(), SignatureError> {
333 let UserSignature::Simple(signature) = signature else {
334 return Err(SignatureError::from_source("not a secp256r1 signature"));
335 };
336
337 <Self as Verifier<SimpleSignature>>::verify(self, message, signature)
338 }
339}
340
341#[cfg(test)]
342mod tests {
343 use iota_types::PersonalMessage;
344 use test_strategy::proptest;
345 #[cfg(target_arch = "wasm32")]
346 use wasm_bindgen_test::wasm_bindgen_test as test;
347
348 use super::*;
349 use crate::{IotaSigner, IotaVerifier};
350
351 #[proptest]
362 fn personal_message_signing(signer: Secp256r1PrivateKey, message: Vec<u8>) {
363 let message = PersonalMessage(message.into());
364 let signature = signer.sign_personal_message(&message).unwrap();
365 let verifying_key = signer.verifying_key();
366 verifying_key
367 .verify_personal_message(&message, &signature)
368 .unwrap();
369
370 let verifier = Secp256r1Verifier::default();
371 verifier
372 .verify_personal_message(&message, &signature)
373 .unwrap();
374 }
375
376 #[test]
377 fn personal_message_signing_fixture() {
378 let key = [
379 167, 44, 116, 0, 51, 221, 254, 179, 210, 44, 93, 196, 125, 155, 85, 94, 29, 41, 13, 60,
380 59, 132, 69, 84, 176, 217, 77, 49, 25, 113, 118, 125,
381 ];
382 let signer = Secp256r1PrivateKey::new(key);
383
384 let message = PersonalMessage(b"hello".into());
385 let sig = signer.sign_personal_message(&message).unwrap();
386 let external_sig = "AlqWPdkIE2bZAUquKv2Tdh9i+Ih+rVSQXH/YsgvwkmeOJR0YLjL/kadivoPtiQkvZBQ1ZI8eDZxe8SaLniwoT88Dh+/vAuGf1UrouFTdefpBEWn3apy8x3EexN5c5ESzGDc=";
387 let b64 = sig.to_base64();
388 assert_eq!(external_sig, b64);
389 }
390}