aptos_crypto_link/ed25519/
ed25519_keys.rs1use crate::{
7 ed25519::{Ed25519Signature, ED25519_PRIVATE_KEY_LENGTH, ED25519_PUBLIC_KEY_LENGTH},
8 hash::CryptoHash,
9 traits::*,
10};
11use aptos_crypto_derive::{DeserializeKey, SerializeKey, SilentDebug, SilentDisplay};
12use core::convert::TryFrom;
13use serde::Serialize;
14use std::fmt;
15
16#[cfg(any(test, feature = "fuzzing"))]
17use crate::test_utils::{self, KeyPair};
18#[cfg(any(test, feature = "fuzzing"))]
19use proptest::prelude::*;
20
21#[derive(DeserializeKey, SerializeKey, SilentDebug, SilentDisplay)]
23pub struct Ed25519PrivateKey(pub(crate) ed25519_dalek::SecretKey);
24
25#[cfg(feature = "assert-private-keys-not-cloneable")]
26static_assertions::assert_not_impl_any!(Ed25519PrivateKey: Clone);
27
28#[cfg(any(test, feature = "cloneable-private-keys"))]
29impl Clone for Ed25519PrivateKey {
30 fn clone(&self) -> Self {
31 let serialized: &[u8] = &(self.to_bytes());
32 Ed25519PrivateKey::try_from(serialized).unwrap()
33 }
34}
35
36#[derive(DeserializeKey, Clone, SerializeKey)]
38pub struct Ed25519PublicKey(pub(crate) ed25519_dalek::PublicKey);
39
40impl Ed25519PrivateKey {
41 pub const LENGTH: usize = ed25519_dalek::SECRET_KEY_LENGTH;
43
44 pub fn to_bytes(&self) -> [u8; ED25519_PRIVATE_KEY_LENGTH] {
46 self.0.to_bytes()
47 }
48
49 fn from_bytes_unchecked(
51 bytes: &[u8],
52 ) -> std::result::Result<Ed25519PrivateKey, CryptoMaterialError> {
53 match ed25519_dalek::SecretKey::from_bytes(bytes) {
54 Ok(dalek_secret_key) => Ok(Ed25519PrivateKey(dalek_secret_key)),
55 Err(_) => Err(CryptoMaterialError::DeserializationError),
56 }
57 }
58
59 fn sign_arbitrary_message(&self, message: &[u8]) -> Ed25519Signature {
62 let secret_key: &ed25519_dalek::SecretKey = &self.0;
63 let public_key: Ed25519PublicKey = self.into();
64 let expanded_secret_key: ed25519_dalek::ExpandedSecretKey =
65 ed25519_dalek::ExpandedSecretKey::from(secret_key);
66 let sig = expanded_secret_key.sign(message.as_ref(), &public_key.0);
67 Ed25519Signature(sig)
68 }
69}
70
71impl Ed25519PublicKey {
72 pub fn to_bytes(&self) -> [u8; ED25519_PUBLIC_KEY_LENGTH] {
74 self.0.to_bytes()
75 }
76
77 pub(crate) fn from_bytes_unchecked(
82 bytes: &[u8],
83 ) -> std::result::Result<Ed25519PublicKey, CryptoMaterialError> {
84 match ed25519_dalek::PublicKey::from_bytes(bytes) {
85 Ok(dalek_public_key) => Ok(Ed25519PublicKey(dalek_public_key)),
86 Err(_) => Err(CryptoMaterialError::DeserializationError),
87 }
88 }
89
90 #[cfg(test)]
107 pub(crate) fn from_x25519_public_bytes(
108 x25519_bytes: &[u8],
109 negative: bool,
110 ) -> Result<Self, CryptoMaterialError> {
111 if x25519_bytes.len() != 32 {
112 return Err(CryptoMaterialError::DeserializationError);
113 }
114 let key_bits = {
115 let mut bits = [0u8; 32];
116 bits.copy_from_slice(x25519_bytes);
117 bits
118 };
119 let mtg_point = curve25519_dalek::montgomery::MontgomeryPoint(key_bits);
120 let sign = if negative { 1u8 } else { 0u8 };
121 let ed_point = mtg_point
122 .to_edwards(sign)
123 .ok_or(CryptoMaterialError::DeserializationError)?;
124 Ed25519PublicKey::try_from(&ed_point.compress().as_bytes()[..])
125 }
126}
127
128impl PrivateKey for Ed25519PrivateKey {
133 type PublicKeyMaterial = Ed25519PublicKey;
134}
135
136impl SigningKey for Ed25519PrivateKey {
137 type VerifyingKeyMaterial = Ed25519PublicKey;
138 type SignatureMaterial = Ed25519Signature;
139
140 fn sign<T: CryptoHash + Serialize>(
141 &self,
142 message: &T,
143 ) -> Result<Ed25519Signature, CryptoMaterialError> {
144 Ok(Ed25519PrivateKey::sign_arbitrary_message(
145 self,
146 signing_message(message)?.as_ref(),
147 ))
148 }
149
150 #[cfg(any(test, feature = "fuzzing"))]
151 fn sign_arbitrary_message(&self, message: &[u8]) -> Ed25519Signature {
152 Ed25519PrivateKey::sign_arbitrary_message(self, message)
153 }
154}
155
156impl Uniform for Ed25519PrivateKey {
157 fn generate<R>(rng: &mut R) -> Self
158 where
159 R: ::rand::RngCore + ::rand::CryptoRng + ::rand_core::CryptoRng + ::rand_core::RngCore,
160 {
161 Ed25519PrivateKey(ed25519_dalek::SecretKey::generate(rng))
162 }
163}
164
165impl PartialEq<Self> for Ed25519PrivateKey {
166 fn eq(&self, other: &Self) -> bool {
167 self.to_bytes() == other.to_bytes()
168 }
169}
170
171impl Eq for Ed25519PrivateKey {}
172
173impl TryFrom<&[u8]> for Ed25519PrivateKey {
176 type Error = CryptoMaterialError;
177
178 fn try_from(bytes: &[u8]) -> std::result::Result<Ed25519PrivateKey, CryptoMaterialError> {
181 Ed25519PrivateKey::from_bytes_unchecked(bytes)
188 }
189}
190
191impl Length for Ed25519PrivateKey {
192 fn length(&self) -> usize {
193 Self::LENGTH
194 }
195}
196
197impl ValidCryptoMaterial for Ed25519PrivateKey {
198 fn to_bytes(&self) -> Vec<u8> {
199 self.to_bytes().to_vec()
200 }
201}
202
203impl Genesis for Ed25519PrivateKey {
204 fn genesis() -> Self {
205 let mut buf = [0u8; ED25519_PRIVATE_KEY_LENGTH];
206 buf[ED25519_PRIVATE_KEY_LENGTH - 1] = 1;
207 Self::try_from(buf.as_ref()).unwrap()
208 }
209}
210
211impl From<&Ed25519PrivateKey> for Ed25519PublicKey {
217 fn from(private_key: &Ed25519PrivateKey) -> Self {
218 let secret: &ed25519_dalek::SecretKey = &private_key.0;
219 let public: ed25519_dalek::PublicKey = secret.into();
220 Ed25519PublicKey(public)
221 }
222}
223
224impl PublicKey for Ed25519PublicKey {
226 type PrivateKeyMaterial = Ed25519PrivateKey;
227}
228
229impl std::hash::Hash for Ed25519PublicKey {
230 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
231 let encoded_pubkey = self.to_bytes();
232 state.write(&encoded_pubkey);
233 }
234}
235
236impl PartialEq for Ed25519PublicKey {
238 fn eq(&self, other: &Ed25519PublicKey) -> bool {
239 self.to_bytes() == other.to_bytes()
240 }
241}
242
243impl Eq for Ed25519PublicKey {}
244
245impl VerifyingKey for Ed25519PublicKey {
248 type SigningKeyMaterial = Ed25519PrivateKey;
249 type SignatureMaterial = Ed25519Signature;
250}
251
252impl fmt::Display for Ed25519PublicKey {
253 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
254 write!(f, "{}", hex::encode(&self.0.as_bytes()))
255 }
256}
257
258impl fmt::Debug for Ed25519PublicKey {
259 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
260 write!(f, "Ed25519PublicKey({})", self)
261 }
262}
263
264impl TryFrom<&[u8]> for Ed25519PublicKey {
265 type Error = CryptoMaterialError;
266
267 fn try_from(bytes: &[u8]) -> std::result::Result<Ed25519PublicKey, CryptoMaterialError> {
272 Ed25519PublicKey::from_bytes_unchecked(bytes)
273 }
274}
275
276impl Length for Ed25519PublicKey {
277 fn length(&self) -> usize {
278 ED25519_PUBLIC_KEY_LENGTH
279 }
280}
281
282impl ValidCryptoMaterial for Ed25519PublicKey {
283 fn to_bytes(&self) -> Vec<u8> {
284 self.0.to_bytes().to_vec()
285 }
286}
287
288#[cfg(any(test, feature = "fuzzing"))]
294pub fn keypair_strategy() -> impl Strategy<Value = KeyPair<Ed25519PrivateKey, Ed25519PublicKey>> {
295 test_utils::uniform_keypair_strategy::<Ed25519PrivateKey, Ed25519PublicKey>()
296}
297
298#[cfg(any(test, feature = "fuzzing"))]
300impl proptest::arbitrary::Arbitrary for Ed25519PublicKey {
301 type Parameters = ();
302 type Strategy = BoxedStrategy<Self>;
303
304 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
305 crate::test_utils::uniform_keypair_strategy::<Ed25519PrivateKey, Ed25519PublicKey>()
306 .prop_map(|v| v.public_key)
307 .boxed()
308 }
309}