tendermint/
private_key.rs1pub use crate::crypto::ed25519::SigningKey as Ed25519;
4#[cfg(feature = "secp256k1")]
5pub use k256::ecdsa::SigningKey as Secp256k1;
6
7use crate::prelude::*;
8
9#[cfg(feature = "rust-crypto")]
10use crate::public_key::PublicKey;
11
12#[cfg(feature = "rust-crypto")]
13use serde::{de, ser, Deserialize, Serialize};
14#[cfg(feature = "rust-crypto")]
15use subtle_encoding::{Base64, Encoding};
16#[cfg(feature = "rust-crypto")]
17use zeroize::Zeroizing;
18
19pub const ED25519_KEYPAIR_SIZE: usize = 64;
20pub const SECP256K1_KEY_SIZE: usize = 32;
21
22#[cfg_attr(feature = "rust-crypto", derive(Serialize, Deserialize))]
24#[cfg_attr(feature = "rust-crypto", serde(tag = "type", content = "value"))] #[non_exhaustive]
26pub enum PrivateKey {
27 #[cfg_attr(
29 feature = "rust-crypto",
30 serde(
31 rename = "tendermint/PrivKeyEd25519",
32 serialize_with = "serialize_ed25519_keypair",
33 deserialize_with = "deserialize_ed25519_keypair"
34 )
35 )]
36 Ed25519(Ed25519),
37
38 #[cfg(feature = "secp256k1")]
39 #[cfg_attr(docsrs, doc(cfg(feature = "secp256k1")))]
40 #[serde(
41 rename = "tendermint/PrivKeySecp256k1",
42 serialize_with = "serialize_secp256k1_privkey",
43 deserialize_with = "deserialize_secp256k1_privkey"
44 )]
45 Secp256k1(Secp256k1),
46}
47
48impl PrivateKey {
49 #[cfg(feature = "rust-crypto")]
51 pub fn public_key(&self) -> PublicKey {
52 match self {
53 PrivateKey::Ed25519(signing_key) => PublicKey::Ed25519(signing_key.verification_key()),
54
55 #[cfg(feature = "secp256k1")]
56 PrivateKey::Secp256k1(signing_key) => {
57 PublicKey::Secp256k1(*signing_key.verifying_key())
58 },
59 }
60 }
61
62 pub fn ed25519_signing_key(&self) -> Option<&Ed25519> {
64 match self {
65 PrivateKey::Ed25519(signing_key) => Some(signing_key),
66
67 #[cfg(feature = "secp256k1")]
68 PrivateKey::Secp256k1(_signing_key) => None,
69 }
70 }
71
72 #[cfg(feature = "rust-crypto")]
74 pub fn from_ed25519_consensus(sk: ed25519_consensus::SigningKey) -> Self {
75 Self::Ed25519(sk.into())
76 }
77}
78
79#[cfg(feature = "rust-crypto")]
80impl From<ed25519_consensus::SigningKey> for PrivateKey {
81 fn from(sk: ed25519_consensus::SigningKey) -> Self {
82 Self::Ed25519(sk.into())
83 }
84}
85
86#[cfg(feature = "secp256k1")]
88fn serialize_secp256k1_privkey<S>(signing_key: &Secp256k1, serializer: S) -> Result<S::Ok, S::Error>
89where
90 S: ser::Serializer,
91{
92 Zeroizing::new(String::from_utf8(Base64::default().encode(signing_key.to_bytes())).unwrap())
93 .serialize(serializer)
94}
95
96#[cfg(feature = "secp256k1")]
98fn deserialize_secp256k1_privkey<'de, D>(deserializer: D) -> Result<Secp256k1, D::Error>
99where
100 D: de::Deserializer<'de>,
101{
102 use de::Error;
103 let string = Zeroizing::new(String::deserialize(deserializer)?);
104 let mut privkey_bytes = Zeroizing::new([0u8; SECP256K1_KEY_SIZE]);
105 let decoded_len = Base64::default()
106 .decode_to_slice(string.as_bytes(), &mut *privkey_bytes)
107 .map_err(D::Error::custom)?;
108
109 if decoded_len != SECP256K1_KEY_SIZE {
110 return Err(D::Error::custom("invalid sepc256k1 privkey size"));
111 }
112
113 let signing_key = Secp256k1::try_from(&privkey_bytes[0..SECP256K1_KEY_SIZE])
114 .map_err(|_| D::Error::custom("invalid signing key"))?;
115
116 Ok(signing_key)
117}
118
119#[cfg(feature = "rust-crypto")]
121fn serialize_ed25519_keypair<S>(signing_key: &Ed25519, serializer: S) -> Result<S::Ok, S::Error>
122where
123 S: ser::Serializer,
124{
125 let mut keypair_bytes = Zeroizing::new([0u8; ED25519_KEYPAIR_SIZE]);
128 keypair_bytes[0..32].copy_from_slice(signing_key.as_bytes());
129 keypair_bytes[32..64].copy_from_slice(signing_key.verification_key().as_bytes());
130 Zeroizing::new(String::from_utf8(Base64::default().encode(&keypair_bytes[..])).unwrap())
131 .serialize(serializer)
132}
133
134#[cfg(feature = "rust-crypto")]
136fn deserialize_ed25519_keypair<'de, D>(deserializer: D) -> Result<Ed25519, D::Error>
137where
138 D: de::Deserializer<'de>,
139{
140 use de::Error;
141 let string = Zeroizing::new(String::deserialize(deserializer)?);
142 let mut keypair_bytes = Zeroizing::new([0u8; ED25519_KEYPAIR_SIZE]);
143 let decoded_len = Base64::default()
144 .decode_to_slice(string.as_bytes(), &mut *keypair_bytes)
145 .map_err(D::Error::custom)?;
146
147 if decoded_len != ED25519_KEYPAIR_SIZE {
148 return Err(D::Error::custom("invalid Ed25519 keypair size"));
149 }
150
151 let signing_key = Ed25519::try_from(&keypair_bytes[0..32])
157 .map_err(|_| D::Error::custom("invalid signing key"))?;
158 let verification_key = signing_key.verification_key();
159 if &keypair_bytes[32..64] != verification_key.as_bytes() {
160 return Err(D::Error::custom("keypair mismatch"));
161 }
162
163 Ok(signing_key)
164}