1#![deny(missing_docs)]
3#![deny(warnings)]
4
5use anyhow::{Context, Result};
6use ecdsa::hazmat::SignPrimitive;
7use ecdsa::signature::hazmat::PrehashSigner;
8use ecdsa::signature::{Signer as _, Verifier as _};
9use ecdsa::RecoveryId;
10use ed25519_dalek::{Signer as _, Verifier as _};
11use sha2::Digest;
12
13pub mod address;
14pub mod bip32;
15pub use bip39;
16pub mod bip44;
17
18#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
20pub enum Algorithm {
21 EcdsaSecp256k1,
23 EcdsaRecoverableSecp256k1,
25 EcdsaSecp256r1,
27 Ed25519,
29 Sr25519,
31}
32
33impl Algorithm {
34 pub fn is_recoverable(&self) -> bool {
36 matches!(self, Algorithm::EcdsaRecoverableSecp256k1)
37 }
38}
39
40pub enum SecretKey {
42 EcdsaSecp256k1(ecdsa::SigningKey<k256::Secp256k1>),
44 EcdsaRecoverableSecp256k1(ecdsa::SigningKey<k256::Secp256k1>),
46 EcdsaSecp256r1(ecdsa::SigningKey<p256::NistP256>),
48 Ed25519(ed25519_dalek::Keypair),
50 Sr25519(schnorrkel::Keypair, Option<schnorrkel::MiniSecretKey>),
52}
53
54impl Clone for SecretKey {
55 fn clone(&self) -> Self {
56 Self::from_bytes(self.algorithm(), &self.to_bytes()).unwrap()
57 }
58}
59
60impl SecretKey {
61 pub fn algorithm(&self) -> Algorithm {
63 match self {
64 SecretKey::EcdsaSecp256k1(_) => Algorithm::EcdsaSecp256k1,
65 SecretKey::EcdsaRecoverableSecp256k1(_) => Algorithm::EcdsaRecoverableSecp256k1,
66 SecretKey::EcdsaSecp256r1(_) => Algorithm::EcdsaSecp256r1,
67 SecretKey::Ed25519(_) => Algorithm::Ed25519,
68 SecretKey::Sr25519(_, _) => Algorithm::Sr25519,
69 }
70 }
71
72 pub fn from_bytes(algorithm: Algorithm, bytes: &[u8]) -> Result<Self> {
74 Ok(match algorithm {
75 Algorithm::EcdsaSecp256k1 => {
76 SecretKey::EcdsaSecp256k1(ecdsa::SigningKey::from_bytes(bytes.try_into()?)?)
77 }
78 Algorithm::EcdsaRecoverableSecp256k1 => SecretKey::EcdsaRecoverableSecp256k1(
79 ecdsa::SigningKey::from_bytes(bytes.try_into()?)?,
80 ),
81 Algorithm::EcdsaSecp256r1 => {
82 SecretKey::EcdsaSecp256r1(ecdsa::SigningKey::from_bytes(bytes.try_into()?)?)
83 }
84 Algorithm::Ed25519 => {
85 let secret = ed25519_dalek::SecretKey::from_bytes(bytes)?;
86 let public = ed25519_dalek::PublicKey::from(&secret);
87 let keypair = ed25519_dalek::Keypair { secret, public };
88 SecretKey::Ed25519(keypair)
89 }
90 Algorithm::Sr25519 => {
91 if bytes.len() == 32 {
92 let minisecret = schnorrkel::MiniSecretKey::from_bytes(bytes)
93 .map_err(|err| anyhow::anyhow!("{}", err))?;
94 let secret =
95 minisecret.expand_to_keypair(schnorrkel::MiniSecretKey::ED25519_MODE);
96 SecretKey::Sr25519(secret, Some(minisecret))
97 } else {
98 let secret = schnorrkel::SecretKey::from_bytes(bytes)
99 .map_err(|err| anyhow::anyhow!("{}", err))?;
100 SecretKey::Sr25519(secret.to_keypair(), None)
101 }
102 }
103 })
104 }
105
106 pub fn to_bytes(&self) -> Vec<u8> {
108 match self {
109 SecretKey::EcdsaSecp256k1(secret) => secret.to_bytes().to_vec(),
110 SecretKey::EcdsaRecoverableSecp256k1(secret) => secret.to_bytes().to_vec(),
111 SecretKey::EcdsaSecp256r1(secret) => secret.to_bytes().to_vec(),
112 SecretKey::Ed25519(secret) => secret.secret.to_bytes().to_vec(),
113 SecretKey::Sr25519(_, Some(minisecret)) => minisecret.as_bytes().to_vec(),
114 SecretKey::Sr25519(secret, None) => secret.secret.to_bytes().to_vec(),
115 }
116 }
117
118 pub fn public_key(&self) -> PublicKey {
120 match self {
121 SecretKey::EcdsaSecp256k1(secret) => PublicKey::EcdsaSecp256k1(*secret.verifying_key()),
122 SecretKey::EcdsaRecoverableSecp256k1(secret) => {
123 PublicKey::EcdsaRecoverableSecp256k1(*secret.verifying_key())
124 }
125 SecretKey::EcdsaSecp256r1(secret) => PublicKey::EcdsaSecp256r1(*secret.verifying_key()),
126 SecretKey::Ed25519(secret) => PublicKey::Ed25519(secret.public),
127 SecretKey::Sr25519(secret, _) => PublicKey::Sr25519(secret.public),
128 }
129 }
130
131 pub fn sign(&self, msg: &[u8], context_param: &str) -> Signature {
133 match self {
134 SecretKey::EcdsaSecp256k1(secret) => Signature::EcdsaSecp256k1(secret.sign(msg)),
135 SecretKey::EcdsaRecoverableSecp256k1(_) => {
136 let digest = sha2::Sha256::digest(msg);
137 self.sign_prehashed(&digest).unwrap()
138 }
139 SecretKey::EcdsaSecp256r1(secret) => Signature::EcdsaSecp256r1(secret.sign(msg)),
140 SecretKey::Ed25519(secret) => Signature::Ed25519(secret.sign(msg)),
141 SecretKey::Sr25519(secret, _) => {
142 let context = schnorrkel::signing_context(context_param.as_bytes());
144 Signature::Sr25519(secret.sign(context.bytes(msg)))
145 }
146 }
147 }
148
149 pub fn sign_prehashed(&self, hash: &[u8]) -> Result<Signature> {
151 Ok(match self {
152 SecretKey::EcdsaSecp256k1(secret) => {
153 Signature::EcdsaSecp256k1(secret.sign_prehash(hash)?)
154 }
155 SecretKey::EcdsaRecoverableSecp256k1(secret) => {
156 let (sig, recid) = secret
157 .as_nonzero_scalar()
158 .try_sign_prehashed_rfc6979::<sha2::Sha256>(hash.try_into()?, b"")?;
159 Signature::EcdsaRecoverableSecp256k1(sig, recid.context("no recovery id")?)
160 }
161 SecretKey::EcdsaSecp256r1(secret) => {
162 Signature::EcdsaSecp256r1(secret.sign_prehash(hash)?)
163 }
164 SecretKey::Ed25519(_) => anyhow::bail!("unimplemented"),
165 SecretKey::Sr25519(_, _) => {
166 anyhow::bail!("unsupported")
167 }
168 })
169 }
170}
171
172#[derive(Clone, Copy, Debug, Eq, PartialEq)]
174pub enum PublicKey {
175 EcdsaSecp256k1(ecdsa::VerifyingKey<k256::Secp256k1>),
177 EcdsaRecoverableSecp256k1(ecdsa::VerifyingKey<k256::Secp256k1>),
179 EcdsaSecp256r1(ecdsa::VerifyingKey<p256::NistP256>),
181 Ed25519(ed25519_dalek::PublicKey),
183 Sr25519(schnorrkel::PublicKey),
185}
186
187impl PublicKey {
188 pub fn algorithm(&self) -> Algorithm {
190 match self {
191 PublicKey::EcdsaSecp256k1(_) => Algorithm::EcdsaSecp256k1,
192 PublicKey::EcdsaRecoverableSecp256k1(_) => Algorithm::EcdsaRecoverableSecp256k1,
193 PublicKey::EcdsaSecp256r1(_) => Algorithm::EcdsaSecp256r1,
194 PublicKey::Ed25519(_) => Algorithm::Ed25519,
195 PublicKey::Sr25519(_) => Algorithm::Sr25519,
196 }
197 }
198
199 pub fn from_bytes(algorithm: Algorithm, bytes: &[u8]) -> Result<Self> {
201 Ok(match algorithm {
202 Algorithm::EcdsaSecp256k1 => {
203 PublicKey::EcdsaSecp256k1(ecdsa::VerifyingKey::from_sec1_bytes(bytes)?)
204 }
205 Algorithm::EcdsaRecoverableSecp256k1 => {
206 PublicKey::EcdsaRecoverableSecp256k1(ecdsa::VerifyingKey::from_sec1_bytes(bytes)?)
207 }
208 Algorithm::EcdsaSecp256r1 => {
209 PublicKey::EcdsaSecp256r1(ecdsa::VerifyingKey::from_sec1_bytes(bytes)?)
210 }
211 Algorithm::Ed25519 => PublicKey::Ed25519(ed25519_dalek::PublicKey::from_bytes(bytes)?),
212 Algorithm::Sr25519 => {
213 let public = schnorrkel::PublicKey::from_bytes(bytes)
214 .map_err(|err| anyhow::anyhow!("{}", err))?;
215 PublicKey::Sr25519(public)
216 }
217 })
218 }
219
220 pub fn to_bytes(&self) -> Vec<u8> {
222 match self {
223 PublicKey::EcdsaSecp256k1(public) => public.to_encoded_point(true).as_bytes().to_vec(),
224 PublicKey::EcdsaRecoverableSecp256k1(public) => {
225 public.to_encoded_point(true).as_bytes().to_vec()
226 }
227 PublicKey::EcdsaSecp256r1(public) => public.to_encoded_point(true).as_bytes().to_vec(),
228 PublicKey::Ed25519(public) => public.to_bytes().to_vec(),
229 PublicKey::Sr25519(public) => public.to_bytes().to_vec(),
230 }
231 }
232
233 pub fn to_uncompressed_bytes(&self) -> Vec<u8> {
235 match self {
236 PublicKey::EcdsaSecp256k1(public) => public.to_encoded_point(false).as_bytes().to_vec(),
237 PublicKey::EcdsaRecoverableSecp256k1(public) => {
238 public.to_encoded_point(false).as_bytes().to_vec()
239 }
240 PublicKey::EcdsaSecp256r1(public) => public.to_encoded_point(false).as_bytes().to_vec(),
241 PublicKey::Ed25519(public) => public.to_bytes().to_vec(),
242 PublicKey::Sr25519(public) => public.to_bytes().to_vec(),
243 }
244 }
245
246 pub fn verify(&self, msg: &[u8], sig: &Signature) -> Result<()> {
248 match (self, &sig) {
249 (PublicKey::EcdsaSecp256k1(public), Signature::EcdsaSecp256k1(sig)) => {
250 public.verify(msg, sig)?
251 }
252 (
253 PublicKey::EcdsaRecoverableSecp256k1(public),
254 Signature::EcdsaRecoverableSecp256k1(sig, _),
255 ) => public.verify(msg, sig)?,
256 (PublicKey::EcdsaSecp256r1(public), Signature::EcdsaSecp256r1(sig)) => {
257 public.verify(msg, sig)?
258 }
259 (PublicKey::Ed25519(public), Signature::Ed25519(sig)) => public.verify(msg, sig)?,
260 (PublicKey::Sr25519(public), Signature::Sr25519(sig)) => {
261 public
262 .verify_simple(&[], msg, sig)
263 .map_err(|err| anyhow::anyhow!("{}", err))?;
264 }
265 (_, _) => anyhow::bail!("unsupported signature scheme"),
266 };
267 Ok(())
268 }
269}
270
271#[derive(Clone, Copy, Debug, Eq, PartialEq)]
273pub enum Signature {
274 EcdsaSecp256k1(ecdsa::Signature<k256::Secp256k1>),
276 EcdsaRecoverableSecp256k1(ecdsa::Signature<k256::Secp256k1>, RecoveryId),
278 EcdsaSecp256r1(ecdsa::Signature<p256::NistP256>),
280 Ed25519(ed25519_dalek::Signature),
282 Sr25519(schnorrkel::Signature),
284}
285
286impl Signature {
287 pub fn algorithm(&self) -> Algorithm {
289 match self {
290 Signature::EcdsaSecp256k1(_) => Algorithm::EcdsaSecp256k1,
291 Signature::EcdsaRecoverableSecp256k1(_, _) => Algorithm::EcdsaRecoverableSecp256k1,
292 Signature::EcdsaSecp256r1(_) => Algorithm::EcdsaSecp256r1,
293 Signature::Ed25519(_) => Algorithm::Ed25519,
294 Signature::Sr25519(_) => Algorithm::Sr25519,
295 }
296 }
297
298 pub fn from_bytes(algorithm: Algorithm, bytes: &[u8]) -> Result<Self> {
300 Ok(match algorithm {
301 Algorithm::EcdsaSecp256k1 => {
302 Signature::EcdsaSecp256k1(ecdsa::Signature::try_from(bytes)?)
303 }
304 Algorithm::EcdsaRecoverableSecp256k1 => Signature::EcdsaRecoverableSecp256k1(
305 ecdsa::Signature::try_from(&bytes[..64])?,
306 RecoveryId::from_byte(bytes[64]).context("invalid signature")?,
307 ),
308 Algorithm::EcdsaSecp256r1 => {
309 Signature::EcdsaSecp256r1(ecdsa::Signature::try_from(bytes)?)
310 }
311 Algorithm::Ed25519 => Signature::Ed25519(ed25519_dalek::Signature::from_bytes(bytes)?),
312 Algorithm::Sr25519 => {
313 let sig = schnorrkel::Signature::from_bytes(bytes)
314 .map_err(|err| anyhow::anyhow!("{}", err))?;
315 Signature::Sr25519(sig)
316 }
317 })
318 }
319
320 pub fn to_bytes(&self) -> Vec<u8> {
322 match self {
323 Signature::EcdsaSecp256k1(sig) => sig.to_vec(),
324 Signature::EcdsaRecoverableSecp256k1(sig, recovery_id) => {
325 let mut bytes = Vec::with_capacity(65);
326 bytes.extend(sig.to_bytes());
327 bytes.push(recovery_id.to_byte());
328 bytes
329 }
330 Signature::EcdsaSecp256r1(sig) => sig.to_vec(),
331 Signature::Ed25519(sig) => sig.to_bytes().to_vec(),
332 Signature::Sr25519(sig) => sig.to_bytes().to_vec(),
333 }
334 }
335
336 pub fn recover(&self, msg: &[u8]) -> Result<Option<PublicKey>> {
338 if let Signature::EcdsaRecoverableSecp256k1(signature, recovery_id) = self {
339 let recovered_key =
340 ecdsa::VerifyingKey::recover_from_msg(msg, signature, *recovery_id)?;
341 Ok(Some(PublicKey::EcdsaRecoverableSecp256k1(recovered_key)))
342 } else {
343 Ok(None)
344 }
345 }
346
347 pub fn recover_prehashed(&self, hash: &[u8]) -> Result<Option<PublicKey>> {
349 if let Signature::EcdsaRecoverableSecp256k1(signature, recovery_id) = self {
350 let recovered_key =
351 ecdsa::VerifyingKey::recover_from_prehash(hash, signature, *recovery_id)?;
352 Ok(Some(PublicKey::EcdsaRecoverableSecp256k1(recovered_key)))
353 } else {
354 Ok(None)
355 }
356 }
357}
358
359#[cfg(test)]
360mod tests {
361 use super::*;
362 use rand::{thread_rng, RngCore};
363
364 const ALGORITHMS: &[Algorithm] = &[
365 Algorithm::EcdsaSecp256k1,
366 Algorithm::EcdsaRecoverableSecp256k1,
367 Algorithm::EcdsaSecp256r1,
368 Algorithm::Ed25519,
369 Algorithm::Sr25519,
370 ];
371
372 #[test]
373 fn secret_key_bytes() -> Result<()> {
374 let mut rng = thread_rng();
375 let mut secret = [0; 32];
376 rng.fill_bytes(&mut secret);
377 for curve in ALGORITHMS {
378 let secret_key = SecretKey::from_bytes(*curve, &secret[..])?;
379 let secret2 = secret_key.to_bytes();
380 assert_eq!(&secret[..], secret2);
381 }
382 Ok(())
383 }
384
385 #[test]
386 fn public_key_bytes() -> Result<()> {
387 let mut rng = thread_rng();
388 let mut secret = [0; 32];
389 rng.fill_bytes(&mut secret);
390 for algorithm in ALGORITHMS {
391 let secret_key = SecretKey::from_bytes(*algorithm, &secret[..])?;
392 let public_key = secret_key.public_key();
393 let public = public_key.to_bytes();
394 let public_key2 = PublicKey::from_bytes(*algorithm, &public)?;
395 assert_eq!(public_key, public_key2);
396 }
397 Ok(())
398 }
399
400 #[test]
401 fn signature_bytes() -> Result<()> {
402 let mut rng = thread_rng();
403 let mut secret = [0; 32];
404 rng.fill_bytes(&mut secret);
405 let mut msg = [0; 32];
406 rng.fill_bytes(&mut msg);
407 for algorithm in ALGORITHMS {
408 let secret_key = SecretKey::from_bytes(*algorithm, &secret[..])?;
409 let signature = secret_key.sign(&msg, "");
410 let sig = signature.to_bytes();
411 let signature2 = Signature::from_bytes(*algorithm, &sig[..])?;
412 assert_eq!(signature, signature2);
413 }
414 Ok(())
415 }
416
417 #[test]
418 fn sign_verify() -> Result<()> {
419 let mut rng = thread_rng();
420 let mut secret = [0; 32];
421 rng.fill_bytes(&mut secret);
422 let mut msg = [0; 32];
423 rng.fill_bytes(&mut msg);
424 for algorithm in ALGORITHMS {
425 let secret_key = SecretKey::from_bytes(*algorithm, &secret[..])?;
426 let public_key = secret_key.public_key();
427 let signature = secret_key.sign(&msg, "");
428 public_key.verify(&msg, &signature)?;
429 }
430 Ok(())
431 }
432
433 #[test]
434 fn sign_recover_pubkey() -> Result<()> {
435 let mut rng = thread_rng();
436 let mut secret = [0; 32];
437 rng.fill_bytes(&mut secret);
438 let mut msg = [0; 32];
439 rng.fill_bytes(&mut msg);
440 let secret_key = SecretKey::from_bytes(Algorithm::EcdsaRecoverableSecp256k1, &secret[..])?;
441 let public_key = secret_key.public_key();
442 let signature = secret_key.sign(&msg, "");
443 let recovered_key = signature.recover(&msg)?.unwrap();
444 assert_eq!(public_key, recovered_key);
445 Ok(())
446 }
447}