1use crate::{
5 account_address::AccountAddress,
6 transaction::{RawTransaction, RawTransactionWithData},
7};
8use anyhow::{ensure, Error, Result};
9use diem_crypto::{
10 ed25519::{Ed25519PublicKey, Ed25519Signature},
11 hash::CryptoHash,
12 multi_ed25519::{MultiEd25519PublicKey, MultiEd25519Signature},
13 traits::Signature,
14 validatable::Validatable,
15 CryptoMaterialError, HashValue, ValidCryptoMaterial, ValidCryptoMaterialStringExt,
16};
17use diem_crypto_derive::{CryptoHasher, DeserializeKey, SerializeKey};
18#[cfg(any(test, feature = "fuzzing"))]
19use proptest_derive::Arbitrary;
20use rand::{rngs::OsRng, Rng};
21use serde::{Deserialize, Serialize};
22use std::{convert::TryFrom, fmt, str::FromStr};
23use thiserror::Error;
24
25pub const MAX_NUM_OF_SIGS: usize = 32;
28
29#[derive(Clone, Debug, PartialEq, Eq, Error)]
31#[error("{:?}", self)]
32pub enum AuthenticationError {
33 MaxSignaturesExceeded,
35}
36
37#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
44pub enum TransactionAuthenticator {
45 Ed25519 {
47 public_key: Validatable<Ed25519PublicKey>,
48 signature: Ed25519Signature,
49 },
50 MultiEd25519 {
52 public_key: MultiEd25519PublicKey,
53 signature: MultiEd25519Signature,
54 },
55 MultiAgent {
57 sender: AccountAuthenticator,
58 secondary_signer_addresses: Vec<AccountAddress>,
59 secondary_signers: Vec<AccountAuthenticator>,
60 },
61}
62
63impl TransactionAuthenticator {
64 pub fn ed25519(public_key: Ed25519PublicKey, signature: Ed25519Signature) -> Self {
66 Self::Ed25519 {
67 public_key: Validatable::new_valid(public_key),
68 signature,
69 }
70 }
71
72 pub fn multi_ed25519(
74 public_key: MultiEd25519PublicKey,
75 signature: MultiEd25519Signature,
76 ) -> Self {
77 Self::MultiEd25519 {
78 public_key,
79 signature,
80 }
81 }
82
83 pub fn multi_agent(
85 sender: AccountAuthenticator,
86 secondary_signer_addresses: Vec<AccountAddress>,
87 secondary_signers: Vec<AccountAuthenticator>,
88 ) -> Self {
89 Self::MultiAgent {
90 sender,
91 secondary_signer_addresses,
92 secondary_signers,
93 }
94 }
95
96 pub fn verify(&self, raw_txn: &RawTransaction) -> Result<()> {
98 let num_sigs: usize = self.sender().number_of_signatures()
99 + self
100 .secondary_signers()
101 .iter()
102 .map(|auth| auth.number_of_signatures())
103 .sum::<usize>();
104 if num_sigs > MAX_NUM_OF_SIGS {
105 return Err(Error::new(AuthenticationError::MaxSignaturesExceeded));
106 }
107 match self {
108 Self::Ed25519 {
109 public_key,
110 signature,
111 } => signature.verify(raw_txn, public_key.validate()?),
112 Self::MultiEd25519 {
113 public_key,
114 signature,
115 } => signature.verify(raw_txn, public_key),
116 Self::MultiAgent {
117 sender,
118 secondary_signer_addresses,
119 secondary_signers,
120 } => {
121 let message = RawTransactionWithData::new_multi_agent(
122 raw_txn.clone(),
123 secondary_signer_addresses.clone(),
124 );
125 sender.verify(&message)?;
126 for signer in secondary_signers {
127 signer.verify(&message)?;
128 }
129 Ok(())
130 }
131 }
132 }
133
134 pub fn sender(&self) -> AccountAuthenticator {
135 match self {
136 Self::Ed25519 {
137 public_key,
138 signature,
139 } => AccountAuthenticator::Ed25519 {
140 public_key: public_key.clone(),
141 signature: signature.clone(),
142 },
143 Self::MultiEd25519 {
144 public_key,
145 signature,
146 } => AccountAuthenticator::multi_ed25519(public_key.clone(), signature.clone()),
147 Self::MultiAgent { sender, .. } => sender.clone(),
148 }
149 }
150
151 pub fn secondary_signer_addreses(&self) -> Vec<AccountAddress> {
152 match self {
153 Self::Ed25519 { .. }
154 | Self::MultiEd25519 {
155 public_key: _,
156 signature: _,
157 } => vec![],
158 Self::MultiAgent {
159 sender: _,
160 secondary_signer_addresses,
161 ..
162 } => secondary_signer_addresses.to_vec(),
163 }
164 }
165
166 pub fn secondary_signers(&self) -> Vec<AccountAuthenticator> {
167 match self {
168 Self::Ed25519 { .. }
169 | Self::MultiEd25519 {
170 public_key: _,
171 signature: _,
172 } => vec![],
173 Self::MultiAgent {
174 sender: _,
175 secondary_signer_addresses: _,
176 secondary_signers,
177 } => secondary_signers.to_vec(),
178 }
179 }
180}
181
182impl fmt::Display for TransactionAuthenticator {
183 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184 match self {
185 Self::Ed25519 {
186 public_key: _,
187 signature: _,
188 } => {
189 write!(
190 f,
191 "TransactionAuthenticator[scheme: Ed25519, sender: {}]",
192 self.sender()
193 )
194 }
195 Self::MultiEd25519 {
196 public_key: _,
197 signature: _,
198 } => {
199 write!(
200 f,
201 "TransactionAuthenticator[scheme: MultiEd25519, sender: {}]",
202 self.sender()
203 )
204 }
205 Self::MultiAgent {
206 sender,
207 secondary_signer_addresses,
208 secondary_signers,
209 } => {
210 let mut sec_addrs: String = "".to_string();
211 for sec_addr in secondary_signer_addresses {
212 sec_addrs = format!("{}\n\t\t\t{:#?},", sec_addrs, sec_addr);
213 }
214 let mut sec_signers: String = "".to_string();
215 for sec_signer in secondary_signers {
216 sec_signers = format!("{}\n\t\t\t{:#?},", sec_signers, sec_signer);
217 }
218 write!(
219 f,
220 "TransactionAuthenticator[\n\
221 \tscheme: MultiAgent, \n\
222 \tsender: {}\n\
223 \tsecondary signer addresses: {}\n\
224 \tsecondary signers: {}]",
225 sender, sec_addrs, sec_signers,
226 )
227 }
228 }
229 }
230}
231
232#[derive(Debug)]
241#[repr(u8)]
242pub enum Scheme {
243 Ed25519 = 0,
244 MultiEd25519 = 1,
245 }
247
248impl fmt::Display for Scheme {
249 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
250 let display = match self {
251 Scheme::Ed25519 => "Ed25519",
252 Scheme::MultiEd25519 => "MultiEd25519",
253 };
254 write!(f, "Scheme::{}", display)
255 }
256}
257
258#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
259pub enum AccountAuthenticator {
260 Ed25519 {
262 public_key: Validatable<Ed25519PublicKey>,
263 signature: Ed25519Signature,
264 },
265 MultiEd25519 {
267 public_key: MultiEd25519PublicKey,
268 signature: MultiEd25519Signature,
269 },
270 }
272
273impl AccountAuthenticator {
274 pub fn scheme(&self) -> Scheme {
276 match self {
277 Self::Ed25519 { .. } => Scheme::Ed25519,
278 Self::MultiEd25519 { .. } => Scheme::MultiEd25519,
279 }
280 }
281
282 pub fn ed25519(public_key: Ed25519PublicKey, signature: Ed25519Signature) -> Self {
284 Self::Ed25519 {
285 public_key: Validatable::new_valid(public_key),
286 signature,
287 }
288 }
289
290 pub fn multi_ed25519(
292 public_key: MultiEd25519PublicKey,
293 signature: MultiEd25519Signature,
294 ) -> Self {
295 Self::MultiEd25519 {
296 public_key,
297 signature,
298 }
299 }
300
301 pub fn verify<T: Serialize + CryptoHash>(&self, message: &T) -> Result<()> {
303 match self {
304 Self::Ed25519 {
305 public_key,
306 signature,
307 } => signature.verify(message, public_key.validate()?),
308 Self::MultiEd25519 {
309 public_key,
310 signature,
311 } => signature.verify(message, public_key),
312 }
313 }
314
315 pub fn public_key_bytes(&self) -> Vec<u8> {
317 match self {
318 Self::Ed25519 { public_key, .. } => public_key.unvalidated().to_bytes().to_vec(),
319 Self::MultiEd25519 { public_key, .. } => public_key.to_bytes().to_vec(),
320 }
321 }
322
323 pub fn signature_bytes(&self) -> Vec<u8> {
325 match self {
326 Self::Ed25519 { signature, .. } => signature.to_bytes().to_vec(),
327 Self::MultiEd25519 { signature, .. } => signature.to_bytes().to_vec(),
328 }
329 }
330
331 pub fn authentication_key_preimage(&self) -> AuthenticationKeyPreimage {
333 AuthenticationKeyPreimage::new(self.public_key_bytes(), self.scheme())
334 }
335
336 pub fn authentication_key(&self) -> AuthenticationKey {
338 AuthenticationKey::from_preimage(&self.authentication_key_preimage())
339 }
340
341 pub fn number_of_signatures(&self) -> usize {
343 match self {
344 Self::Ed25519 { .. } => 1,
345 Self::MultiEd25519 { signature, .. } => signature.signatures().len(),
346 }
347 }
348}
349
350#[derive(
353 Clone,
354 Copy,
355 CryptoHasher,
356 Debug,
357 DeserializeKey,
358 Eq,
359 Hash,
360 Ord,
361 PartialEq,
362 PartialOrd,
363 SerializeKey,
364)]
365#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
366pub struct AuthenticationKey([u8; AuthenticationKey::LENGTH]);
367
368impl AuthenticationKey {
369 pub const fn new(bytes: [u8; Self::LENGTH]) -> Self {
371 Self(bytes)
372 }
373
374 pub const fn zero() -> Self {
377 Self([0; 32])
378 }
379
380 pub const LENGTH: usize = 32;
382
383 pub fn from_preimage(preimage: &AuthenticationKeyPreimage) -> AuthenticationKey {
385 AuthenticationKey::new(*HashValue::sha3_256_of(&preimage.0).as_ref())
386 }
387
388 pub fn ed25519(public_key: &Ed25519PublicKey) -> AuthenticationKey {
390 Self::from_preimage(&AuthenticationKeyPreimage::ed25519(public_key))
391 }
392
393 pub fn multi_ed25519(public_key: &MultiEd25519PublicKey) -> Self {
395 Self::from_preimage(&AuthenticationKeyPreimage::multi_ed25519(public_key))
396 }
397
398 pub fn derived_address(&self) -> AccountAddress {
401 let mut array = [0u8; AccountAddress::LENGTH];
403 array.copy_from_slice(&self.0[Self::LENGTH - AccountAddress::LENGTH..]);
404 AccountAddress::new(array)
405 }
406
407 pub fn prefix(&self) -> [u8; AccountAddress::LENGTH] {
409 let mut array = [0u8; AccountAddress::LENGTH];
410 array.copy_from_slice(&self.0[..AccountAddress::LENGTH]);
411 array
412 }
413
414 pub fn to_vec(&self) -> Vec<u8> {
416 self.0.to_vec()
417 }
418
419 pub fn random() -> Self {
421 let mut rng = OsRng;
422 let buf: [u8; Self::LENGTH] = rng.gen();
423 AuthenticationKey::new(buf)
424 }
425}
426
427impl ValidCryptoMaterial for AuthenticationKey {
428 fn to_bytes(&self) -> Vec<u8> {
429 self.to_vec()
430 }
431}
432
433pub struct AuthenticationKeyPreimage(Vec<u8>);
435
436impl AuthenticationKeyPreimage {
437 fn new(mut public_key_bytes: Vec<u8>, scheme: Scheme) -> Self {
439 public_key_bytes.push(scheme as u8);
440 Self(public_key_bytes)
441 }
442
443 pub fn ed25519(public_key: &Ed25519PublicKey) -> AuthenticationKeyPreimage {
445 Self::new(public_key.to_bytes().to_vec(), Scheme::Ed25519)
446 }
447
448 pub fn multi_ed25519(public_key: &MultiEd25519PublicKey) -> AuthenticationKeyPreimage {
450 Self::new(public_key.to_bytes(), Scheme::MultiEd25519)
451 }
452
453 pub fn into_vec(self) -> Vec<u8> {
455 self.0
456 }
457}
458
459impl fmt::Display for AccountAuthenticator {
460 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
461 write!(
462 f,
463 "AccountAuthenticator[scheme id: {:?}, public key: {}, signature: {}]",
464 self.scheme(),
465 hex::encode(&self.public_key_bytes()),
466 hex::encode(&self.signature_bytes())
467 )
468 }
469}
470
471impl TryFrom<&[u8]> for AuthenticationKey {
472 type Error = CryptoMaterialError;
473
474 fn try_from(bytes: &[u8]) -> std::result::Result<AuthenticationKey, CryptoMaterialError> {
475 if bytes.len() != Self::LENGTH {
476 return Err(CryptoMaterialError::WrongLengthError);
477 }
478 let mut addr = [0u8; Self::LENGTH];
479 addr.copy_from_slice(bytes);
480 Ok(AuthenticationKey(addr))
481 }
482}
483
484impl TryFrom<Vec<u8>> for AuthenticationKey {
485 type Error = CryptoMaterialError;
486
487 fn try_from(bytes: Vec<u8>) -> std::result::Result<AuthenticationKey, CryptoMaterialError> {
488 AuthenticationKey::try_from(&bytes[..])
489 }
490}
491
492impl FromStr for AuthenticationKey {
493 type Err = Error;
494
495 fn from_str(s: &str) -> Result<Self> {
496 ensure!(
497 !s.is_empty(),
498 "authentication key string should not be empty.",
499 );
500 let bytes_out = ::hex::decode(s)?;
501 let key = AuthenticationKey::try_from(bytes_out.as_slice())?;
502 Ok(key)
503 }
504}
505
506impl AsRef<[u8]> for AuthenticationKey {
507 fn as_ref(&self) -> &[u8] {
508 &self.0
509 }
510}
511
512impl fmt::LowerHex for AuthenticationKey {
513 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
514 write!(f, "{}", hex::encode(&self.0))
515 }
516}
517
518impl fmt::Display for AuthenticationKey {
519 fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
520 write!(f, "{:#x}", self)
522 }
523}
524
525#[cfg(test)]
526mod tests {
527 use crate::transaction::authenticator::AuthenticationKey;
528 use std::str::FromStr;
529
530 #[test]
531 fn test_from_str_should_not_panic_by_given_empty_string() {
532 assert!(AuthenticationKey::from_str("").is_err());
533 }
534}