1use crate::account_address::AccountAddress;
9use anyhow::{ensure, Error, Result};
10use diem_crypto::{
11 bls::{
12 BLSPublicKey, BLSPublicKeyUnchecked, BLSSignature,
13 BLSSignatureUnchecked,
14 },
15 hash::CryptoHash,
16 multi_bls::MultiBLSSignature,
17 traits::Signature,
18 CryptoMaterialError, HashValue, ValidCryptoMaterial,
19 ValidCryptoMaterialStringExt,
20};
21use diem_crypto_derive::{CryptoHasher, DeserializeKey, SerializeKey};
22#[cfg(any(test, feature = "fuzzing"))]
23use proptest_derive::Arbitrary;
24use rand::{rngs::OsRng, Rng};
25use serde::{Deserialize, Serialize};
26use std::{convert::TryFrom, fmt, str::FromStr};
27
28#[derive(Debug)]
44#[repr(u8)]
45pub enum Scheme {
46 BLS = 2,
47 MultiBLS = 3,
48 }
50
51impl fmt::Display for Scheme {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 let display = match self {
54 Scheme::BLS => "bls",
55 Scheme::MultiBLS => "multi_bls",
56 };
57 write!(f, "Scheme::{}", display)
58 }
59}
60
61#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
62pub enum TransactionAuthenticator {
63 _ReservedEd25519,
66 _ReservedMultiEd25519,
69 BLS {
71 public_key: BLSPublicKey,
72 signature: BLSSignature,
73 },
74 MultiBLS {
75 signature: MultiBLSSignature,
76 }, }
78
79#[derive(Deserialize)]
80pub enum TransactionAuthenticatorUnchecked {
81 _ReservedEd25519,
84 _ReservedMultiEd25519,
87 BLS {
88 public_key: BLSPublicKeyUnchecked,
89 signature: BLSSignatureUnchecked,
90 },
91 MultiBLS {
92 signature: MultiBLSSignature,
93 },
94}
95
96impl From<TransactionAuthenticatorUnchecked> for TransactionAuthenticator {
97 fn from(t: TransactionAuthenticatorUnchecked) -> Self {
98 match t {
99 TransactionAuthenticatorUnchecked::_ReservedEd25519 => {
100 Self::_ReservedEd25519
101 }
102 TransactionAuthenticatorUnchecked::_ReservedMultiEd25519 => {
103 Self::_ReservedMultiEd25519
104 }
105 TransactionAuthenticatorUnchecked::BLS {
106 public_key,
107 signature,
108 } => Self::BLS {
109 public_key: public_key.into(),
110 signature: signature.into(),
111 },
112 TransactionAuthenticatorUnchecked::MultiBLS { signature } => {
113 Self::MultiBLS { signature }
114 }
115 }
116 }
117}
118
119impl TransactionAuthenticator {
120 pub fn scheme(&self) -> Scheme {
122 match self {
123 Self::_ReservedEd25519 | Self::_ReservedMultiEd25519 => {
124 unreachable!("reserved variant")
125 }
126 Self::BLS { .. } => Scheme::BLS,
127 Self::MultiBLS { .. } => Scheme::MultiBLS,
128 }
129 }
130
131 pub fn bls(public_key: BLSPublicKey, signature: BLSSignature) -> Self {
132 Self::BLS {
133 public_key,
134 signature,
135 }
136 }
137
138 pub fn multi_bls(signature: MultiBLSSignature) -> Self {
139 Self::MultiBLS { signature }
140 }
141
142 pub fn verify<T: Serialize + CryptoHash>(&self, message: &T) -> Result<()> {
145 match self {
146 Self::_ReservedEd25519 | Self::_ReservedMultiEd25519 => {
147 unreachable!("reserved variant")
148 }
149 Self::BLS {
150 public_key,
151 signature,
152 } => signature.verify(message, public_key),
153 Self::MultiBLS { .. } => {
154 Ok(())
156 }
157 }
158 }
159
160 pub fn public_key_bytes(&self) -> Vec<u8> {
162 match self {
163 Self::_ReservedEd25519 | Self::_ReservedMultiEd25519 => {
164 unreachable!("reserved variant")
165 }
166 Self::BLS { public_key, .. } => public_key.to_bytes().to_vec(),
167 Self::MultiBLS { .. } => todo!(),
168 }
169 }
170
171 pub fn signature_bytes(&self) -> Vec<u8> {
173 match self {
174 Self::_ReservedEd25519 | Self::_ReservedMultiEd25519 => {
175 unreachable!("reserved variant")
176 }
177 Self::BLS { signature, .. } => signature.to_bytes().to_vec(),
178 Self::MultiBLS { .. } => todo!(),
179 }
180 }
181
182 pub fn authentication_key_preimage(&self) -> AuthenticationKeyPreimage {
185 AuthenticationKeyPreimage::new(self.public_key_bytes(), self.scheme())
186 }
187
188 pub fn authentication_key(&self) -> AuthenticationKey {
191 AuthenticationKey::from_preimage(&self.authentication_key_preimage())
192 }
193}
194
195#[derive(
198 Clone,
199 Copy,
200 CryptoHasher,
201 Debug,
202 DeserializeKey,
203 Eq,
204 Hash,
205 Ord,
206 PartialEq,
207 PartialOrd,
208 SerializeKey,
209)]
210#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
211pub struct AuthenticationKey([u8; AuthenticationKey::LENGTH]);
212
213impl AuthenticationKey {
214 pub const LENGTH: usize = 32;
216
217 pub const fn new(bytes: [u8; Self::LENGTH]) -> Self { Self(bytes) }
219
220 pub fn from_preimage(
222 preimage: &AuthenticationKeyPreimage,
223 ) -> AuthenticationKey {
224 AuthenticationKey::new(*HashValue::sha3_256_of(&preimage.0).as_ref())
225 }
226
227 pub fn derived_address(&self) -> AccountAddress {
230 let mut array = [0u8; AccountAddress::LENGTH];
232 array.copy_from_slice(&self.0[Self::LENGTH - AccountAddress::LENGTH..]);
233 AccountAddress::new(array)
234 }
235
236 pub fn prefix(&self) -> [u8; AccountAddress::LENGTH] {
238 let mut array = [0u8; AccountAddress::LENGTH];
239 array.copy_from_slice(&self.0[..AccountAddress::LENGTH]);
240 array
241 }
242
243 pub fn to_vec(&self) -> Vec<u8> { self.0.to_vec() }
245
246 pub fn random() -> Self {
248 let mut rng = OsRng;
249 let buf: [u8; Self::LENGTH] = rng.gen();
250 AuthenticationKey::new(buf)
251 }
252}
253
254impl ValidCryptoMaterial for AuthenticationKey {
255 fn to_bytes(&self) -> Vec<u8> { self.to_vec() }
256}
257
258pub struct AuthenticationKeyPreimage(Vec<u8>);
260
261impl AuthenticationKeyPreimage {
262 fn new(mut public_key_bytes: Vec<u8>, scheme: Scheme) -> Self {
264 public_key_bytes.push(scheme as u8);
265 Self(public_key_bytes)
266 }
267
268 pub fn into_vec(self) -> Vec<u8> { self.0 }
270}
271
272impl fmt::Display for TransactionAuthenticator {
273 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
274 write!(
275 f,
276 "TransactionAuthenticator[scheme id: {:?}, public key: {}, signature: {}]",
277 self.scheme(),
278 hex::encode(&self.public_key_bytes()),
279 hex::encode(&self.signature_bytes())
280 )
281 }
282}
283
284impl TryFrom<&[u8]> for AuthenticationKey {
285 type Error = CryptoMaterialError;
286
287 fn try_from(
288 bytes: &[u8],
289 ) -> std::result::Result<AuthenticationKey, CryptoMaterialError> {
290 if bytes.len() != Self::LENGTH {
291 return Err(CryptoMaterialError::WrongLengthError);
292 }
293 let mut addr = [0u8; Self::LENGTH];
294 addr.copy_from_slice(bytes);
295 Ok(AuthenticationKey(addr))
296 }
297}
298
299impl TryFrom<Vec<u8>> for AuthenticationKey {
300 type Error = CryptoMaterialError;
301
302 fn try_from(
303 bytes: Vec<u8>,
304 ) -> std::result::Result<AuthenticationKey, CryptoMaterialError> {
305 AuthenticationKey::try_from(&bytes[..])
306 }
307}
308
309impl FromStr for AuthenticationKey {
310 type Err = Error;
311
312 fn from_str(s: &str) -> Result<Self> {
313 ensure!(
314 !s.is_empty(),
315 "authentication key string should not be empty.",
316 );
317 let bytes_out = ::hex::decode(s)?;
318 let key = AuthenticationKey::try_from(bytes_out.as_slice())?;
319 Ok(key)
320 }
321}
322
323impl AsRef<[u8]> for AuthenticationKey {
324 fn as_ref(&self) -> &[u8] { &self.0 }
325}
326
327impl fmt::LowerHex for AuthenticationKey {
328 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
329 write!(f, "{}", hex::encode(&self.0))
330 }
331}
332
333impl fmt::Display for AuthenticationKey {
334 fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
335 write!(f, "{:#x}", self)
337 }
338}
339
340#[cfg(test)]
341mod tests {
342 use crate::transaction::authenticator::AuthenticationKey;
343 use std::str::FromStr;
344
345 #[test]
346 fn test_from_str_should_not_panic_by_given_empty_string() {
347 assert!(AuthenticationKey::from_str("").is_err());
348 }
349}