1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
pub use ed25519_consensus::SigningKey as Ed25519;
use ed25519_consensus::VerificationKey;
use serde::{de, ser, Deserialize, Serialize};
use subtle_encoding::{Base64, Encoding};
use zeroize::Zeroizing;
use crate::{prelude::*, public_key::PublicKey};
pub const ED25519_KEYPAIR_SIZE: usize = 64;
#[derive(Serialize, Deserialize, Clone)]
#[non_exhaustive]
#[serde(tag = "type", content = "value")]
pub enum PrivateKey {
#[serde(
rename = "tendermint/PrivKeyEd25519",
serialize_with = "serialize_ed25519_keypair",
deserialize_with = "deserialize_ed25519_keypair"
)]
Ed25519(Ed25519),
}
impl PrivateKey {
pub fn public_key(&self) -> PublicKey {
match self {
PrivateKey::Ed25519(signing_key) => PublicKey::Ed25519(signing_key.verification_key()),
}
}
pub fn ed25519_signing_key(&self) -> Option<&Ed25519> {
match self {
PrivateKey::Ed25519(signing_key) => Some(signing_key),
}
}
}
fn serialize_ed25519_keypair<S>(signing_key: &Ed25519, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
let mut keypair_bytes = Zeroizing::new([0u8; ED25519_KEYPAIR_SIZE]);
keypair_bytes[0..32].copy_from_slice(signing_key.as_bytes());
keypair_bytes[32..64].copy_from_slice(signing_key.verification_key().as_bytes());
Zeroizing::new(String::from_utf8(Base64::default().encode(&keypair_bytes[..])).unwrap())
.serialize(serializer)
}
fn deserialize_ed25519_keypair<'de, D>(deserializer: D) -> Result<Ed25519, D::Error>
where
D: de::Deserializer<'de>,
{
use de::Error;
let string = Zeroizing::new(String::deserialize(deserializer)?);
let mut keypair_bytes = Zeroizing::new([0u8; ED25519_KEYPAIR_SIZE]);
let decoded_len = Base64::default()
.decode_to_slice(string.as_bytes(), &mut *keypair_bytes)
.map_err(D::Error::custom)?;
if decoded_len != ED25519_KEYPAIR_SIZE {
return Err(D::Error::custom("invalid Ed25519 keypair size"));
}
let signing_key = Ed25519::try_from(&keypair_bytes[0..32])
.map_err(|_| D::Error::custom("invalid signing key"))?;
let verification_key = VerificationKey::from(&signing_key);
if &keypair_bytes[32..64] != verification_key.as_bytes() {
return Err(D::Error::custom("keypair mismatch"));
}
Ok(signing_key)
}