1use crate::account_address::AccountAddress;
9use anyhow::{ensure, Error, Result};
10use diem_crypto::{
11 bls::{
12 BLSPublicKey, BLSPublicKeyUnchecked, BLSSignature,
13 BLSSignatureUnchecked,
14 },
15 ed25519::{Ed25519PublicKey, Ed25519Signature},
16 hash::CryptoHash,
17 multi_bls::MultiBLSSignature,
18 multi_ed25519::{MultiEd25519PublicKey, MultiEd25519Signature},
19 traits::Signature,
20 CryptoMaterialError, HashValue, ValidCryptoMaterial,
21 ValidCryptoMaterialStringExt,
22};
23use diem_crypto_derive::{CryptoHasher, DeserializeKey, SerializeKey};
24#[cfg(any(test, feature = "fuzzing"))]
25use proptest_derive::Arbitrary;
26use rand::{rngs::OsRng, Rng};
27use serde::{Deserialize, Serialize};
28use std::{convert::TryFrom, fmt, str::FromStr};
29
30#[derive(Debug)]
46#[repr(u8)]
47pub enum Scheme {
48 Ed25519 = 0,
49 MultiEd25519 = 1,
50 BLS = 2,
51 MultiBLS = 3,
52 }
54
55impl fmt::Display for Scheme {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 let display = match self {
58 Scheme::Ed25519 => "Ed25519",
59 Scheme::MultiEd25519 => "MultiEd25519",
60 Scheme::BLS => "bls",
61 Scheme::MultiBLS => "multi_bls",
62 };
63 write!(f, "Scheme::{}", display)
64 }
65}
66
67#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
68pub enum TransactionAuthenticator {
69 Ed25519 {
71 public_key: Ed25519PublicKey,
72 signature: Ed25519Signature,
73 },
74 MultiEd25519 {
76 public_key: MultiEd25519PublicKey,
77 signature: MultiEd25519Signature,
78 },
79 BLS {
81 public_key: BLSPublicKey,
82 signature: BLSSignature,
83 },
84 MultiBLS {
85 signature: MultiBLSSignature,
86 }, }
88
89#[derive(Deserialize)]
90pub enum TransactionAuthenticatorUnchecked {
91 Ed25519 {
92 public_key: Ed25519PublicKey,
93 signature: Ed25519Signature,
94 },
95 MultiEd25519 {
96 public_key: MultiEd25519PublicKey,
97 signature: MultiEd25519Signature,
98 },
99 BLS {
100 public_key: BLSPublicKeyUnchecked,
101 signature: BLSSignatureUnchecked,
102 },
103 MultiBLS {
104 signature: MultiBLSSignature,
105 },
106}
107
108impl From<TransactionAuthenticatorUnchecked> for TransactionAuthenticator {
109 fn from(t: TransactionAuthenticatorUnchecked) -> Self {
110 match t {
111 TransactionAuthenticatorUnchecked::BLS {
112 public_key,
113 signature,
114 } => Self::BLS {
115 public_key: public_key.into(),
116 signature: signature.into(),
117 },
118 TransactionAuthenticatorUnchecked::MultiBLS { signature } => {
119 Self::MultiBLS { signature }
120 }
121 TransactionAuthenticatorUnchecked::Ed25519 {
122 public_key,
123 signature,
124 } => Self::Ed25519 {
125 public_key,
126 signature,
127 },
128 TransactionAuthenticatorUnchecked::MultiEd25519 {
129 public_key,
130 signature,
131 } => Self::MultiEd25519 {
132 public_key,
133 signature,
134 },
135 }
136 }
137}
138
139impl TransactionAuthenticator {
140 pub fn scheme(&self) -> Scheme {
142 match self {
143 Self::Ed25519 { .. } => Scheme::Ed25519,
144 Self::MultiEd25519 { .. } => Scheme::MultiEd25519,
145 Self::BLS { .. } => Scheme::BLS,
146 Self::MultiBLS { .. } => Scheme::MultiBLS,
147 }
148 }
149
150 pub fn ed25519(
152 public_key: Ed25519PublicKey, signature: Ed25519Signature,
153 ) -> Self {
154 Self::Ed25519 {
155 public_key,
156 signature,
157 }
158 }
159
160 pub fn multi_ed25519(
162 public_key: MultiEd25519PublicKey, signature: MultiEd25519Signature,
163 ) -> Self {
164 Self::MultiEd25519 {
165 public_key,
166 signature,
167 }
168 }
169
170 pub fn bls(public_key: BLSPublicKey, signature: BLSSignature) -> Self {
171 Self::BLS {
172 public_key,
173 signature,
174 }
175 }
176
177 pub fn multi_bls(signature: MultiBLSSignature) -> Self {
178 Self::MultiBLS { signature }
179 }
180
181 pub fn verify<T: Serialize + CryptoHash>(&self, message: &T) -> Result<()> {
184 match self {
185 Self::Ed25519 {
186 public_key,
187 signature,
188 } => signature.verify(message, public_key),
189 Self::MultiEd25519 {
190 public_key,
191 signature,
192 } => signature.verify(message, public_key),
193 Self::BLS {
194 public_key,
195 signature,
196 } => signature.verify(message, public_key),
197 Self::MultiBLS { .. } => {
198 Ok(())
200 }
201 }
202 }
203
204 pub fn public_key_bytes(&self) -> Vec<u8> {
206 match self {
207 Self::Ed25519 { public_key, .. } => public_key.to_bytes().to_vec(),
208 Self::MultiEd25519 { public_key, .. } => {
209 public_key.to_bytes().to_vec()
210 }
211 Self::BLS { public_key, .. } => public_key.to_bytes().to_vec(),
212 Self::MultiBLS { .. } => todo!(),
213 }
214 }
215
216 pub fn signature_bytes(&self) -> Vec<u8> {
218 match self {
219 Self::Ed25519 { signature, .. } => signature.to_bytes().to_vec(),
220 Self::MultiEd25519 { signature, .. } => {
221 signature.to_bytes().to_vec()
222 }
223 Self::BLS { signature, .. } => signature.to_bytes().to_vec(),
224 Self::MultiBLS { .. } => todo!(),
225 }
226 }
227
228 pub fn authentication_key_preimage(&self) -> AuthenticationKeyPreimage {
231 AuthenticationKeyPreimage::new(self.public_key_bytes(), self.scheme())
232 }
233
234 pub fn authentication_key(&self) -> AuthenticationKey {
237 AuthenticationKey::from_preimage(&self.authentication_key_preimage())
238 }
239}
240
241#[derive(
244 Clone,
245 Copy,
246 CryptoHasher,
247 Debug,
248 DeserializeKey,
249 Eq,
250 Hash,
251 Ord,
252 PartialEq,
253 PartialOrd,
254 SerializeKey,
255)]
256#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
257pub struct AuthenticationKey([u8; AuthenticationKey::LENGTH]);
258
259impl AuthenticationKey {
260 pub const LENGTH: usize = 32;
262
263 pub const fn new(bytes: [u8; Self::LENGTH]) -> Self { Self(bytes) }
265
266 pub fn from_preimage(
268 preimage: &AuthenticationKeyPreimage,
269 ) -> AuthenticationKey {
270 AuthenticationKey::new(*HashValue::sha3_256_of(&preimage.0).as_ref())
271 }
272
273 pub fn ed25519(public_key: &Ed25519PublicKey) -> AuthenticationKey {
275 Self::from_preimage(&AuthenticationKeyPreimage::ed25519(public_key))
276 }
277
278 pub fn multi_ed25519(public_key: &MultiEd25519PublicKey) -> Self {
280 Self::from_preimage(&AuthenticationKeyPreimage::multi_ed25519(
281 public_key,
282 ))
283 }
284
285 pub fn derived_address(&self) -> AccountAddress {
288 let mut array = [0u8; AccountAddress::LENGTH];
290 array.copy_from_slice(&self.0[Self::LENGTH - AccountAddress::LENGTH..]);
291 AccountAddress::new(array)
292 }
293
294 pub fn prefix(&self) -> [u8; AccountAddress::LENGTH] {
296 let mut array = [0u8; AccountAddress::LENGTH];
297 array.copy_from_slice(&self.0[..AccountAddress::LENGTH]);
298 array
299 }
300
301 pub fn to_vec(&self) -> Vec<u8> { self.0.to_vec() }
303
304 pub fn random() -> Self {
306 let mut rng = OsRng;
307 let buf: [u8; Self::LENGTH] = rng.gen();
308 AuthenticationKey::new(buf)
309 }
310}
311
312impl ValidCryptoMaterial for AuthenticationKey {
313 fn to_bytes(&self) -> Vec<u8> { self.to_vec() }
314}
315
316pub struct AuthenticationKeyPreimage(Vec<u8>);
318
319impl AuthenticationKeyPreimage {
320 fn new(mut public_key_bytes: Vec<u8>, scheme: Scheme) -> Self {
322 public_key_bytes.push(scheme as u8);
323 Self(public_key_bytes)
324 }
325
326 pub fn ed25519(public_key: &Ed25519PublicKey) -> AuthenticationKeyPreimage {
328 Self::new(public_key.to_bytes().to_vec(), Scheme::Ed25519)
329 }
330
331 pub fn multi_ed25519(
333 public_key: &MultiEd25519PublicKey,
334 ) -> AuthenticationKeyPreimage {
335 Self::new(public_key.to_bytes(), Scheme::MultiEd25519)
336 }
337
338 pub fn into_vec(self) -> Vec<u8> { self.0 }
340}
341
342impl fmt::Display for TransactionAuthenticator {
343 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
344 write!(
345 f,
346 "TransactionAuthenticator[scheme id: {:?}, public key: {}, signature: {}]",
347 self.scheme(),
348 hex::encode(&self.public_key_bytes()),
349 hex::encode(&self.signature_bytes())
350 )
351 }
352}
353
354impl TryFrom<&[u8]> for AuthenticationKey {
355 type Error = CryptoMaterialError;
356
357 fn try_from(
358 bytes: &[u8],
359 ) -> std::result::Result<AuthenticationKey, CryptoMaterialError> {
360 if bytes.len() != Self::LENGTH {
361 return Err(CryptoMaterialError::WrongLengthError);
362 }
363 let mut addr = [0u8; Self::LENGTH];
364 addr.copy_from_slice(bytes);
365 Ok(AuthenticationKey(addr))
366 }
367}
368
369impl TryFrom<Vec<u8>> for AuthenticationKey {
370 type Error = CryptoMaterialError;
371
372 fn try_from(
373 bytes: Vec<u8>,
374 ) -> std::result::Result<AuthenticationKey, CryptoMaterialError> {
375 AuthenticationKey::try_from(&bytes[..])
376 }
377}
378
379impl FromStr for AuthenticationKey {
380 type Err = Error;
381
382 fn from_str(s: &str) -> Result<Self> {
383 ensure!(
384 !s.is_empty(),
385 "authentication key string should not be empty.",
386 );
387 let bytes_out = ::hex::decode(s)?;
388 let key = AuthenticationKey::try_from(bytes_out.as_slice())?;
389 Ok(key)
390 }
391}
392
393impl AsRef<[u8]> for AuthenticationKey {
394 fn as_ref(&self) -> &[u8] { &self.0 }
395}
396
397impl fmt::LowerHex for AuthenticationKey {
398 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
399 write!(f, "{}", hex::encode(&self.0))
400 }
401}
402
403impl fmt::Display for AuthenticationKey {
404 fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
405 write!(f, "{:#x}", self)
407 }
408}
409
410#[cfg(test)]
411mod tests {
412 use crate::transaction::authenticator::AuthenticationKey;
413 use std::str::FromStr;
414
415 #[test]
416 fn test_from_str_should_not_panic_by_given_empty_string() {
417 assert!(AuthenticationKey::from_str("").is_err());
418 }
419}