iota_types/
crypto.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5// This module broadly handles cryptographic types and operations.
6// Deprecated zkLogin types are intentionally retained for serialization
7// compatibility.
8
9use std::{
10    collections::BTreeMap,
11    fmt::{Debug, Display, Formatter},
12    hash::{Hash, Hasher},
13    str::FromStr,
14};
15
16use anyhow::{Error, anyhow};
17use derive_more::{AsMut, AsRef, From};
18pub use enum_dispatch::enum_dispatch;
19use eyre::eyre;
20pub use fastcrypto::traits::{
21    AggregateAuthenticator, Authenticator, EncodeDecodeBase64, KeyPair as KeypairTraits, Signer,
22    SigningKey, ToFromBytes, VerifyingKey,
23};
24use fastcrypto::{
25    bls12381::min_sig::{
26        BLS12381AggregateSignature, BLS12381AggregateSignatureAsBytes, BLS12381KeyPair,
27        BLS12381PrivateKey, BLS12381PublicKey, BLS12381Signature,
28    },
29    ed25519::{
30        Ed25519KeyPair, Ed25519PrivateKey, Ed25519PublicKey, Ed25519PublicKeyAsBytes,
31        Ed25519Signature, Ed25519SignatureAsBytes,
32    },
33    encoding::{Base64, Bech32, Encoding, Hex},
34    error::{FastCryptoError, FastCryptoResult},
35    hash::{Blake2b256, HashFunction},
36    secp256k1::{
37        Secp256k1KeyPair, Secp256k1PublicKey, Secp256k1PublicKeyAsBytes, Secp256k1Signature,
38        Secp256k1SignatureAsBytes,
39    },
40    secp256r1::{
41        Secp256r1KeyPair, Secp256r1PublicKey, Secp256r1PublicKeyAsBytes, Secp256r1Signature,
42        Secp256r1SignatureAsBytes,
43    },
44};
45pub use iota_sdk_types::RandomnessRound;
46use iota_sdk_types::crypto::{Intent, IntentMessage, IntentScope};
47use rand::{
48    SeedableRng,
49    rngs::{OsRng, StdRng},
50};
51use roaring::RoaringBitmap;
52use serde::{Deserialize, Deserializer, Serialize, ser::Serializer};
53use serde_with::{Bytes, serde_as};
54use strum::EnumString;
55use tracing::{instrument, warn};
56
57use crate::{
58    base_types::{AuthorityName, ConciseableName, IotaAddress, address_from_iota_pub_key},
59    committee::{Committee, CommitteeTrait, EpochId, StakeUnit},
60    error::{IotaError, IotaResult},
61    iota_serde::{IotaBitmap, Readable},
62    signature::GenericSignature,
63};
64
65#[cfg(test)]
66#[path = "unit_tests/crypto_tests.rs"]
67mod crypto_tests;
68
69#[cfg(test)]
70#[path = "unit_tests/intent_tests.rs"]
71mod intent_tests;
72
73////////////////////////////////////////////////////////////////////////
74// Type aliases selecting the signature algorithm for the code base.
75////////////////////////////////////////////////////////////////////////
76// Here we select the types that are used by default in the code base.
77// The whole code base should only:
78// - refer to those aliases and not use the individual scheme implementations
79// - not use the schemes in a way that break genericity (e.g. using their Struct
80//   impl functions)
81// - swap one of those aliases to point to another type if necessary
82//
83// Beware: if you change those aliases to point to another scheme
84// implementation, you will have to change all related aliases to point to
85// concrete types that work with each other. Failure to do so will result in a
86// ton of compilation errors, and worse: it will not make sense!
87
88// Authority Objects
89pub type AuthorityKeyPair = BLS12381KeyPair;
90pub type AuthorityPublicKey = BLS12381PublicKey;
91pub type AuthorityPrivateKey = BLS12381PrivateKey;
92pub type AuthoritySignature = BLS12381Signature;
93pub type AggregateAuthoritySignature = BLS12381AggregateSignature;
94pub type AggregateAuthoritySignatureAsBytes = BLS12381AggregateSignatureAsBytes;
95
96// TODO(joyqvq): prefix these types with Default, DefaultAccountKeyPair etc
97pub type AccountKeyPair = Ed25519KeyPair;
98pub type AccountPublicKey = Ed25519PublicKey;
99pub type AccountPrivateKey = Ed25519PrivateKey;
100
101pub type NetworkKeyPair = Ed25519KeyPair;
102pub type NetworkPublicKey = Ed25519PublicKey;
103pub type NetworkPrivateKey = Ed25519PrivateKey;
104
105pub type DefaultHash = Blake2b256;
106
107pub const DEFAULT_EPOCH_ID: EpochId = 0;
108pub const IOTA_PRIV_KEY_PREFIX: &str = "iotaprivkey";
109
110/// Creates a proof of that the authority account address is owned by the
111/// holder of authority key, and also ensures that the authority
112/// public key exists. A proof of possession is an authority
113/// signature committed over the intent message `intent || message || epoch`
114/// (See more at [struct IntentMessage] and [struct Intent]) where the message
115/// is constructed as `authority_pubkey_bytes || authority_account_address`.
116pub fn generate_proof_of_possession(
117    keypair: &AuthorityKeyPair,
118    address: IotaAddress,
119) -> AuthoritySignature {
120    let mut msg: Vec<u8> = Vec::new();
121    msg.extend_from_slice(keypair.public().as_bytes());
122    msg.extend_from_slice(address.as_ref());
123    AuthoritySignature::new_secure(
124        &IntentMessage::new(Intent::iota_app(IntentScope::ProofOfPossession), msg),
125        &DEFAULT_EPOCH_ID,
126        keypair,
127    )
128}
129
130/// Verify proof of possession against the expected intent message,
131/// consisting of the authority pubkey and the authority account address.
132pub fn verify_proof_of_possession(
133    pop: &AuthoritySignature,
134    authority_pubkey: &AuthorityPublicKey,
135    iota_address: IotaAddress,
136) -> Result<(), IotaError> {
137    authority_pubkey
138        .validate()
139        .map_err(|_| IotaError::InvalidSignature {
140            error: "Fail to validate pubkey".to_string(),
141        })?;
142    let mut msg = authority_pubkey.as_bytes().to_vec();
143    msg.extend_from_slice(iota_address.as_ref());
144    pop.verify_secure(
145        &IntentMessage::new(Intent::iota_app(IntentScope::ProofOfPossession), msg),
146        DEFAULT_EPOCH_ID,
147        authority_pubkey.into(),
148    )
149}
150
151// Account Keys
152//
153// * The following section defines the keypairs that are used by
154// * accounts to interact with Iota.
155// * Currently we support eddsa and ecdsa on Iota.
156
157#[expect(clippy::large_enum_variant)]
158#[derive(Debug, From, PartialEq, Eq)]
159pub enum IotaKeyPair {
160    Ed25519(Ed25519KeyPair),
161    Secp256k1(Secp256k1KeyPair),
162    Secp256r1(Secp256r1KeyPair),
163}
164
165impl IotaKeyPair {
166    pub fn public(&self) -> PublicKey {
167        match self {
168            IotaKeyPair::Ed25519(kp) => PublicKey::Ed25519(kp.public().into()),
169            IotaKeyPair::Secp256k1(kp) => PublicKey::Secp256k1(kp.public().into()),
170            IotaKeyPair::Secp256r1(kp) => PublicKey::Secp256r1(kp.public().into()),
171        }
172    }
173}
174
175impl Clone for IotaKeyPair {
176    fn clone(&self) -> Self {
177        match self {
178            IotaKeyPair::Ed25519(kp) => kp.copy().into(),
179            IotaKeyPair::Secp256k1(kp) => kp.copy().into(),
180            IotaKeyPair::Secp256r1(kp) => kp.copy().into(),
181        }
182    }
183}
184
185impl Signer<Signature> for IotaKeyPair {
186    fn sign(&self, msg: &[u8]) -> Signature {
187        match self {
188            IotaKeyPair::Ed25519(kp) => kp.sign(msg),
189            IotaKeyPair::Secp256k1(kp) => kp.sign(msg),
190            IotaKeyPair::Secp256r1(kp) => kp.sign(msg),
191        }
192    }
193}
194
195impl EncodeDecodeBase64 for IotaKeyPair {
196    fn encode_base64(&self) -> String {
197        Base64::encode(self.to_bytes())
198    }
199
200    fn decode_base64(value: &str) -> FastCryptoResult<Self> {
201        let bytes = Base64::decode(value)?;
202        Self::from_bytes(&bytes).map_err(|_| FastCryptoError::InvalidInput)
203    }
204}
205
206impl IotaKeyPair {
207    pub fn to_bytes(&self) -> Vec<u8> {
208        let mut bytes: Vec<u8> = Vec::new();
209        bytes.push(self.public().flag());
210
211        match self {
212            IotaKeyPair::Ed25519(kp) => {
213                bytes.extend_from_slice(kp.as_bytes());
214            }
215            IotaKeyPair::Secp256k1(kp) => {
216                bytes.extend_from_slice(kp.as_bytes());
217            }
218            IotaKeyPair::Secp256r1(kp) => {
219                bytes.extend_from_slice(kp.as_bytes());
220            }
221        }
222        bytes
223    }
224
225    pub fn from_bytes(bytes: &[u8]) -> Result<Self, eyre::Report> {
226        match SignatureScheme::from_flag_byte(bytes.first().ok_or_else(|| eyre!("Invalid length"))?)
227        {
228            Ok(x) => match x {
229                SignatureScheme::ED25519 => Ok(IotaKeyPair::Ed25519(Ed25519KeyPair::from_bytes(
230                    bytes.get(1..).ok_or_else(|| eyre!("Invalid length"))?,
231                )?)),
232                SignatureScheme::Secp256k1 => {
233                    Ok(IotaKeyPair::Secp256k1(Secp256k1KeyPair::from_bytes(
234                        bytes.get(1..).ok_or_else(|| eyre!("Invalid length"))?,
235                    )?))
236                }
237                SignatureScheme::Secp256r1 => {
238                    Ok(IotaKeyPair::Secp256r1(Secp256r1KeyPair::from_bytes(
239                        bytes.get(1..).ok_or_else(|| eyre!("Invalid length"))?,
240                    )?))
241                }
242                _ => Err(eyre!("Invalid flag byte")),
243            },
244            _ => Err(eyre!("Invalid bytes")),
245        }
246    }
247
248    pub fn to_bytes_no_flag(&self) -> Vec<u8> {
249        match self {
250            IotaKeyPair::Ed25519(kp) => kp.as_bytes().to_vec(),
251            IotaKeyPair::Secp256k1(kp) => kp.as_bytes().to_vec(),
252            IotaKeyPair::Secp256r1(kp) => kp.as_bytes().to_vec(),
253        }
254    }
255
256    /// Encode a IotaKeyPair as `flag || privkey` in Bech32 starting with
257    /// "iotaprivkey" to a string. Note that the pubkey is not encoded.
258    pub fn encode(&self) -> Result<String, eyre::Report> {
259        Bech32::encode(self.to_bytes(), IOTA_PRIV_KEY_PREFIX).map_err(|e| eyre!(e))
260    }
261
262    /// Decode a IotaKeyPair from `flag || privkey` in Bech32 starting with
263    /// "iotaprivkey" to IotaKeyPair. The public key is computed directly from
264    /// the private key bytes.
265    pub fn decode(value: &str) -> Result<Self, eyre::Report> {
266        let bytes = Bech32::decode(value, IOTA_PRIV_KEY_PREFIX)?;
267        Self::from_bytes(&bytes)
268    }
269}
270
271impl Serialize for IotaKeyPair {
272    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
273    where
274        S: Serializer,
275    {
276        let s = self.encode_base64();
277        serializer.serialize_str(&s)
278    }
279}
280
281impl<'de> Deserialize<'de> for IotaKeyPair {
282    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
283    where
284        D: Deserializer<'de>,
285    {
286        use serde::de::Error;
287        let s = String::deserialize(deserializer)?;
288        IotaKeyPair::decode_base64(&s).map_err(|e| Error::custom(e.to_string()))
289    }
290}
291
292#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
293pub enum PublicKey {
294    Ed25519(Ed25519PublicKeyAsBytes),
295    Secp256k1(Secp256k1PublicKeyAsBytes),
296    Secp256r1(Secp256r1PublicKeyAsBytes),
297    #[deprecated(note = "zkLogin is deprecated and was never enabled on IOTA")]
298    ZkLoginDeprecated,
299    Passkey(Secp256r1PublicKeyAsBytes),
300}
301
302impl AsRef<[u8]> for PublicKey {
303    fn as_ref(&self) -> &[u8] {
304        match self {
305            PublicKey::Ed25519(pk) => &pk.0,
306            PublicKey::Secp256k1(pk) => &pk.0,
307            PublicKey::Secp256r1(pk) => &pk.0,
308            #[allow(deprecated)]
309            PublicKey::ZkLoginDeprecated => &[],
310            PublicKey::Passkey(pk) => &pk.0,
311        }
312    }
313}
314
315impl EncodeDecodeBase64 for PublicKey {
316    fn encode_base64(&self) -> String {
317        let mut bytes: Vec<u8> = Vec::new();
318        bytes.extend_from_slice(&[self.flag()]);
319        bytes.extend_from_slice(self.as_ref());
320        Base64::encode(&bytes[..])
321    }
322
323    fn decode_base64(value: &str) -> FastCryptoResult<Self> {
324        let bytes = Base64::decode(value)?;
325        match bytes.first() {
326            Some(x) => {
327                if x == &SignatureScheme::ED25519.flag() {
328                    let pk: Ed25519PublicKey =
329                        Ed25519PublicKey::from_bytes(bytes.get(1..).ok_or(
330                            FastCryptoError::InputLengthWrong(Ed25519PublicKey::LENGTH + 1),
331                        )?)?;
332                    Ok(PublicKey::Ed25519((&pk).into()))
333                } else if x == &SignatureScheme::Secp256k1.flag() {
334                    let pk = Secp256k1PublicKey::from_bytes(bytes.get(1..).ok_or(
335                        FastCryptoError::InputLengthWrong(Secp256k1PublicKey::LENGTH + 1),
336                    )?)?;
337                    Ok(PublicKey::Secp256k1((&pk).into()))
338                } else if x == &SignatureScheme::Secp256r1.flag() {
339                    let pk = Secp256r1PublicKey::from_bytes(bytes.get(1..).ok_or(
340                        FastCryptoError::InputLengthWrong(Secp256r1PublicKey::LENGTH + 1),
341                    )?)?;
342                    Ok(PublicKey::Secp256r1((&pk).into()))
343                } else if x == &SignatureScheme::PasskeyAuthenticator.flag() {
344                    let pk = Secp256r1PublicKey::from_bytes(bytes.get(1..).ok_or(
345                        FastCryptoError::InputLengthWrong(Secp256r1PublicKey::LENGTH + 1),
346                    )?)?;
347                    Ok(PublicKey::Passkey((&pk).into()))
348                } else {
349                    Err(FastCryptoError::InvalidInput)
350                }
351            }
352            _ => Err(FastCryptoError::InvalidInput),
353        }
354    }
355}
356
357impl PublicKey {
358    pub fn flag(&self) -> u8 {
359        self.scheme().flag()
360    }
361
362    pub fn try_from_bytes(
363        curve: SignatureScheme,
364        key_bytes: &[u8],
365    ) -> Result<PublicKey, eyre::Report> {
366        match curve {
367            SignatureScheme::ED25519 => Ok(PublicKey::Ed25519(
368                (&Ed25519PublicKey::from_bytes(key_bytes)?).into(),
369            )),
370            SignatureScheme::Secp256k1 => Ok(PublicKey::Secp256k1(
371                (&Secp256k1PublicKey::from_bytes(key_bytes)?).into(),
372            )),
373            SignatureScheme::Secp256r1 => Ok(PublicKey::Secp256r1(
374                (&Secp256r1PublicKey::from_bytes(key_bytes)?).into(),
375            )),
376            SignatureScheme::PasskeyAuthenticator => Ok(PublicKey::Passkey(
377                (&Secp256r1PublicKey::from_bytes(key_bytes)?).into(),
378            )),
379            _ => Err(eyre!("Unsupported curve")),
380        }
381    }
382
383    pub fn scheme(&self) -> SignatureScheme {
384        match self {
385            PublicKey::Ed25519(_) => Ed25519IotaSignature::SCHEME,
386            PublicKey::Secp256k1(_) => Secp256k1IotaSignature::SCHEME,
387            PublicKey::Secp256r1(_) => Secp256r1IotaSignature::SCHEME,
388            #[allow(deprecated)]
389            PublicKey::ZkLoginDeprecated => SignatureScheme::ZkLoginAuthenticatorDeprecated,
390            PublicKey::Passkey(_) => SignatureScheme::PasskeyAuthenticator,
391        }
392    }
393}
394
395/// Defines the compressed version of the public key that we pass around
396/// in IOTA.
397#[serde_as]
398#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, AsRef)]
399#[as_ref(forward)]
400pub struct AuthorityPublicKeyBytes(
401    #[serde_as(as = "Readable<Base64, Bytes>")] pub [u8; AuthorityPublicKey::LENGTH],
402);
403
404impl AuthorityPublicKeyBytes {
405    fn fmt_impl(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
406        let s = Hex::encode(self.0);
407        write!(f, "k#{s}")?;
408        Ok(())
409    }
410}
411
412impl<'a> ConciseableName<'a> for AuthorityPublicKeyBytes {
413    type ConciseTypeRef = ConciseAuthorityPublicKeyBytesRef<'a>;
414    type ConciseType = ConciseAuthorityPublicKeyBytes;
415
416    /// Get a ConciseAuthorityPublicKeyBytesRef. Usage:
417    ///
418    ///   debug!(name = ?authority.concise());
419    ///   format!("{:?}", authority.concise());
420    fn concise(&'a self) -> ConciseAuthorityPublicKeyBytesRef<'a> {
421        ConciseAuthorityPublicKeyBytesRef(self)
422    }
423
424    fn concise_owned(&self) -> ConciseAuthorityPublicKeyBytes {
425        ConciseAuthorityPublicKeyBytes(*self)
426    }
427}
428
429/// A wrapper around AuthorityPublicKeyBytes that provides a concise Debug impl.
430pub struct ConciseAuthorityPublicKeyBytesRef<'a>(&'a AuthorityPublicKeyBytes);
431
432impl Debug for ConciseAuthorityPublicKeyBytesRef<'_> {
433    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
434        let s = Hex::encode(self.0.0.get(0..4).ok_or(std::fmt::Error)?);
435        write!(f, "k#{s}..")
436    }
437}
438
439impl Display for ConciseAuthorityPublicKeyBytesRef<'_> {
440    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
441        Debug::fmt(self, f)
442    }
443}
444
445/// A wrapper around AuthorityPublicKeyBytes but owns it.
446#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
447pub struct ConciseAuthorityPublicKeyBytes(AuthorityPublicKeyBytes);
448
449impl Debug for ConciseAuthorityPublicKeyBytes {
450    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
451        let s = Hex::encode(self.0.0.get(0..4).ok_or(std::fmt::Error)?);
452        write!(f, "k#{s}..")
453    }
454}
455
456impl Display for ConciseAuthorityPublicKeyBytes {
457    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
458        Debug::fmt(self, f)
459    }
460}
461
462impl TryFrom<AuthorityPublicKeyBytes> for AuthorityPublicKey {
463    type Error = FastCryptoError;
464
465    fn try_from(bytes: AuthorityPublicKeyBytes) -> Result<AuthorityPublicKey, Self::Error> {
466        AuthorityPublicKey::from_bytes(bytes.as_ref())
467    }
468}
469
470impl From<&AuthorityPublicKey> for AuthorityPublicKeyBytes {
471    fn from(pk: &AuthorityPublicKey) -> AuthorityPublicKeyBytes {
472        AuthorityPublicKeyBytes::from_bytes(pk.as_ref()).unwrap()
473    }
474}
475
476impl Debug for AuthorityPublicKeyBytes {
477    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
478        self.fmt_impl(f)
479    }
480}
481
482impl Display for AuthorityPublicKeyBytes {
483    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
484        self.fmt_impl(f)
485    }
486}
487
488impl ToFromBytes for AuthorityPublicKeyBytes {
489    fn from_bytes(bytes: &[u8]) -> Result<Self, fastcrypto::error::FastCryptoError> {
490        let bytes: [u8; AuthorityPublicKey::LENGTH] = bytes
491            .try_into()
492            .map_err(|_| fastcrypto::error::FastCryptoError::InvalidInput)?;
493        Ok(AuthorityPublicKeyBytes(bytes))
494    }
495}
496
497impl AuthorityPublicKeyBytes {
498    pub const ZERO: Self = Self::new([0u8; AuthorityPublicKey::LENGTH]);
499
500    /// This ensures it's impossible to construct an instance with other than
501    /// registered lengths
502    pub const fn new(bytes: [u8; AuthorityPublicKey::LENGTH]) -> AuthorityPublicKeyBytes
503where {
504        AuthorityPublicKeyBytes(bytes)
505    }
506}
507
508impl FromStr for AuthorityPublicKeyBytes {
509    type Err = Error;
510
511    fn from_str(s: &str) -> Result<Self, Self::Err> {
512        let value = Hex::decode(s).map_err(|e| anyhow!(e))?;
513        Self::from_bytes(&value[..]).map_err(|e| anyhow!(e))
514    }
515}
516
517impl Default for AuthorityPublicKeyBytes {
518    fn default() -> Self {
519        Self::ZERO
520    }
521}
522
523// Add helper calls for Authority Signature
524//
525
526pub trait IotaAuthoritySignature {
527    fn verify_secure<T>(
528        &self,
529        value: &IntentMessage<T>,
530        epoch_id: EpochId,
531        author: AuthorityPublicKeyBytes,
532    ) -> Result<(), IotaError>
533    where
534        T: Serialize;
535
536    fn new_secure<T>(
537        value: &IntentMessage<T>,
538        epoch_id: &EpochId,
539        secret: &dyn Signer<Self>,
540    ) -> Self
541    where
542        T: Serialize;
543}
544
545impl IotaAuthoritySignature for AuthoritySignature {
546    #[instrument(level = "trace", skip_all)]
547    fn new_secure<T>(value: &IntentMessage<T>, epoch: &EpochId, secret: &dyn Signer<Self>) -> Self
548    where
549        T: Serialize,
550    {
551        let mut intent_msg_bytes =
552            bcs::to_bytes(&value).expect("Message serialization should not fail");
553        epoch.write(&mut intent_msg_bytes);
554        secret.sign(&intent_msg_bytes)
555    }
556
557    #[instrument(level = "trace", skip_all)]
558    fn verify_secure<T>(
559        &self,
560        value: &IntentMessage<T>,
561        epoch: EpochId,
562        author: AuthorityPublicKeyBytes,
563    ) -> Result<(), IotaError>
564    where
565        T: Serialize,
566    {
567        let mut message = bcs::to_bytes(&value).expect("Message serialization should not fail");
568        epoch.write(&mut message);
569
570        let public_key = AuthorityPublicKey::try_from(author).map_err(|_| {
571            IotaError::KeyConversion(
572                "Failed to serialize public key bytes to valid public key".to_string(),
573            )
574        })?;
575        public_key
576            .verify(&message[..], self)
577            .map_err(|e| IotaError::InvalidSignature {
578                error: format!(
579                    "Fail to verify auth sig {} epoch: {} author: {}",
580                    e,
581                    epoch,
582                    author.concise()
583                ),
584            })
585    }
586}
587
588// TODO: get_key_pair() and get_key_pair_from_bytes() should return KeyPair
589// only. TODO: rename to random_key_pair
590pub fn get_key_pair<KP: KeypairTraits>() -> (IotaAddress, KP)
591where
592    <KP as KeypairTraits>::PubKey: IotaPublicKey,
593{
594    get_key_pair_from_rng(&mut OsRng)
595}
596
597/// Generate a random committee key pairs with a given committee size
598pub fn random_committee_key_pairs_of_size(size: usize) -> Vec<AuthorityKeyPair> {
599    let mut rng = StdRng::from_seed([0; 32]);
600    (0..size)
601        .map(|_| {
602            // TODO: We are generating the keys 4 times to match exactly as how we generate
603            // keys in ConfigBuilder::build (iota-config/src/network_config_builder). This
604            // is because we are using these key generation functions as
605            // fixtures and we call them independently in different paths and
606            // exact the results to be the same. We should eliminate them.
607            let key_pair = get_key_pair_from_rng::<AuthorityKeyPair, _>(&mut rng);
608            get_key_pair_from_rng::<AuthorityKeyPair, _>(&mut rng);
609            get_key_pair_from_rng::<AccountKeyPair, _>(&mut rng);
610            get_key_pair_from_rng::<AccountKeyPair, _>(&mut rng);
611            key_pair.1
612        })
613        .collect()
614}
615
616pub fn deterministic_random_account_key() -> (IotaAddress, AccountKeyPair) {
617    let mut rng = StdRng::from_seed([0; 32]);
618    get_key_pair_from_rng(&mut rng)
619}
620
621pub fn get_account_key_pair() -> (IotaAddress, AccountKeyPair) {
622    get_key_pair()
623}
624
625pub fn get_authority_key_pair() -> (IotaAddress, AuthorityKeyPair) {
626    get_key_pair()
627}
628
629/// Generate a keypair from the specified RNG (useful for testing with seedable
630/// rngs).
631pub fn get_key_pair_from_rng<KP: KeypairTraits, R>(csprng: &mut R) -> (IotaAddress, KP)
632where
633    R: rand::CryptoRng + rand::RngCore,
634    <KP as KeypairTraits>::PubKey: IotaPublicKey,
635{
636    let kp = KP::generate(&mut StdRng::from_rng(csprng).unwrap());
637    (address_from_iota_pub_key(kp.public()), kp)
638}
639
640// TODO: C-GETTER
641pub fn get_key_pair_from_bytes<KP: KeypairTraits>(bytes: &[u8]) -> IotaResult<(IotaAddress, KP)>
642where
643    <KP as KeypairTraits>::PubKey: IotaPublicKey,
644{
645    let priv_length = <KP as KeypairTraits>::PrivKey::LENGTH;
646    let pub_key_length = <KP as KeypairTraits>::PubKey::LENGTH;
647    if bytes.len() != priv_length + pub_key_length {
648        return Err(IotaError::KeyConversion(format!(
649            "Invalid input byte length, expected {}: {}",
650            priv_length + pub_key_length,
651            bytes.len()
652        )));
653    }
654    let sk = <KP as KeypairTraits>::PrivKey::from_bytes(
655        bytes
656            .get(..priv_length)
657            .ok_or(IotaError::InvalidPrivateKey)?,
658    )
659    .map_err(|_| IotaError::InvalidPrivateKey)?;
660    let kp: KP = sk.into();
661    Ok((address_from_iota_pub_key(kp.public()), kp))
662}
663
664// Account Signatures
665//
666
667// Enums for signature scheme signatures
668#[enum_dispatch]
669#[derive(Clone, Debug, PartialEq, Eq, Hash)]
670pub enum Signature {
671    Ed25519IotaSignature,
672    Secp256k1IotaSignature,
673    Secp256r1IotaSignature,
674}
675
676impl Serialize for Signature {
677    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
678    where
679        S: Serializer,
680    {
681        let bytes = self.as_ref();
682
683        if serializer.is_human_readable() {
684            let s = Base64::encode(bytes);
685            serializer.serialize_str(&s)
686        } else {
687            serializer.serialize_bytes(bytes)
688        }
689    }
690}
691
692impl<'de> Deserialize<'de> for Signature {
693    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
694    where
695        D: Deserializer<'de>,
696    {
697        use serde::de::Error;
698
699        let bytes = if deserializer.is_human_readable() {
700            let s = String::deserialize(deserializer)?;
701            Base64::decode(&s).map_err(|e| Error::custom(e.to_string()))?
702        } else {
703            let data: Vec<u8> = Vec::deserialize(deserializer)?;
704            data
705        };
706
707        Self::from_bytes(&bytes).map_err(|e| Error::custom(e.to_string()))
708    }
709}
710
711impl Signature {
712    /// The messaged passed in is already hashed form.
713    pub fn new_hashed(hashed_msg: &[u8], secret: &dyn Signer<Signature>) -> Self {
714        Signer::sign(secret, hashed_msg)
715    }
716
717    #[instrument(level = "trace", skip_all)]
718    pub fn new_secure<T>(value: &IntentMessage<T>, secret: &dyn Signer<Signature>) -> Self
719    where
720        T: Serialize,
721    {
722        // Compute the BCS hash of the value in intent message. In the case of
723        // transaction data, this is the BCS hash of `struct TransactionData`,
724        // different from the transaction digest itself that computes the BCS
725        // hash of the Rust type prefix and `struct TransactionData`.
726        // (See `fn digest` in `impl Message for SenderSignedData`).
727        let mut hasher = DefaultHash::default();
728        hasher.update(bcs::to_bytes(&value).expect("Message serialization should not fail"));
729
730        Signer::sign(secret, &hasher.finalize().digest)
731    }
732}
733
734impl AsRef<[u8]> for Signature {
735    fn as_ref(&self) -> &[u8] {
736        match self {
737            Signature::Ed25519IotaSignature(sig) => sig.as_ref(),
738            Signature::Secp256k1IotaSignature(sig) => sig.as_ref(),
739            Signature::Secp256r1IotaSignature(sig) => sig.as_ref(),
740        }
741    }
742}
743impl AsMut<[u8]> for Signature {
744    fn as_mut(&mut self) -> &mut [u8] {
745        match self {
746            Signature::Ed25519IotaSignature(sig) => sig.as_mut(),
747            Signature::Secp256k1IotaSignature(sig) => sig.as_mut(),
748            Signature::Secp256r1IotaSignature(sig) => sig.as_mut(),
749        }
750    }
751}
752
753impl ToFromBytes for Signature {
754    fn from_bytes(bytes: &[u8]) -> Result<Self, FastCryptoError> {
755        match bytes.first() {
756            Some(x) => {
757                if x == &Ed25519IotaSignature::SCHEME.flag() {
758                    Ok(<Ed25519IotaSignature as ToFromBytes>::from_bytes(bytes)?.into())
759                } else if x == &Secp256k1IotaSignature::SCHEME.flag() {
760                    Ok(<Secp256k1IotaSignature as ToFromBytes>::from_bytes(bytes)?.into())
761                } else if x == &Secp256r1IotaSignature::SCHEME.flag() {
762                    Ok(<Secp256r1IotaSignature as ToFromBytes>::from_bytes(bytes)?.into())
763                } else {
764                    Err(FastCryptoError::InvalidInput)
765                }
766            }
767            _ => Err(FastCryptoError::InvalidInput),
768        }
769    }
770}
771
772// BLS Port
773//
774
775impl IotaPublicKey for BLS12381PublicKey {
776    const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::BLS12381;
777}
778
779// Ed25519 Iota Signature port
780//
781
782#[serde_as]
783#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash, AsRef, AsMut)]
784#[as_ref(forward)]
785#[as_mut(forward)]
786pub struct Ed25519IotaSignature(
787    #[serde_as(as = "Readable<Base64, Bytes>")]
788    [u8; Ed25519PublicKey::LENGTH + Ed25519Signature::LENGTH + 1],
789);
790
791// Implementation useful for simplify testing when mock signature is needed
792impl Default for Ed25519IotaSignature {
793    fn default() -> Self {
794        Self([0; Ed25519PublicKey::LENGTH + Ed25519Signature::LENGTH + 1])
795    }
796}
797
798impl IotaSignatureInner for Ed25519IotaSignature {
799    type Sig = Ed25519Signature;
800    type PubKey = Ed25519PublicKey;
801    type KeyPair = Ed25519KeyPair;
802    const LENGTH: usize = Ed25519PublicKey::LENGTH + Ed25519Signature::LENGTH + 1;
803}
804
805impl IotaPublicKey for Ed25519PublicKey {
806    const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::ED25519;
807}
808
809impl ToFromBytes for Ed25519IotaSignature {
810    fn from_bytes(bytes: &[u8]) -> Result<Self, FastCryptoError> {
811        if bytes.len() != Self::LENGTH {
812            return Err(FastCryptoError::InputLengthWrong(Self::LENGTH));
813        }
814        let mut sig_bytes = [0; Self::LENGTH];
815        sig_bytes.copy_from_slice(bytes);
816        Ok(Self(sig_bytes))
817    }
818}
819
820impl Signer<Signature> for Ed25519KeyPair {
821    fn sign(&self, msg: &[u8]) -> Signature {
822        Ed25519IotaSignature::new(self, msg).into()
823    }
824}
825
826// Secp256k1 Iota Signature port
827//
828#[serde_as]
829#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash, AsRef, AsMut)]
830#[as_ref(forward)]
831#[as_mut(forward)]
832pub struct Secp256k1IotaSignature(
833    #[serde_as(as = "Readable<Base64, Bytes>")]
834    [u8; Secp256k1PublicKey::LENGTH + Secp256k1Signature::LENGTH + 1],
835);
836
837impl IotaSignatureInner for Secp256k1IotaSignature {
838    type Sig = Secp256k1Signature;
839    type PubKey = Secp256k1PublicKey;
840    type KeyPair = Secp256k1KeyPair;
841    const LENGTH: usize = Secp256k1PublicKey::LENGTH + Secp256k1Signature::LENGTH + 1;
842}
843
844impl IotaPublicKey for Secp256k1PublicKey {
845    const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::Secp256k1;
846}
847
848impl ToFromBytes for Secp256k1IotaSignature {
849    fn from_bytes(bytes: &[u8]) -> Result<Self, FastCryptoError> {
850        if bytes.len() != Self::LENGTH {
851            return Err(FastCryptoError::InputLengthWrong(Self::LENGTH));
852        }
853        let mut sig_bytes = [0; Self::LENGTH];
854        sig_bytes.copy_from_slice(bytes);
855        Ok(Self(sig_bytes))
856    }
857}
858
859impl Signer<Signature> for Secp256k1KeyPair {
860    fn sign(&self, msg: &[u8]) -> Signature {
861        Secp256k1IotaSignature::new(self, msg).into()
862    }
863}
864
865// Secp256r1 Iota Signature port
866//
867#[serde_as]
868#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash, AsRef, AsMut)]
869#[as_ref(forward)]
870#[as_mut(forward)]
871pub struct Secp256r1IotaSignature(
872    #[serde_as(as = "Readable<Base64, Bytes>")]
873    [u8; Secp256r1PublicKey::LENGTH + Secp256r1Signature::LENGTH + 1],
874);
875
876impl IotaSignatureInner for Secp256r1IotaSignature {
877    type Sig = Secp256r1Signature;
878    type PubKey = Secp256r1PublicKey;
879    type KeyPair = Secp256r1KeyPair;
880    const LENGTH: usize = Secp256r1PublicKey::LENGTH + Secp256r1Signature::LENGTH + 1;
881}
882
883impl IotaPublicKey for Secp256r1PublicKey {
884    const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::Secp256r1;
885}
886
887impl ToFromBytes for Secp256r1IotaSignature {
888    fn from_bytes(bytes: &[u8]) -> Result<Self, FastCryptoError> {
889        if bytes.len() != Self::LENGTH {
890            return Err(FastCryptoError::InputLengthWrong(Self::LENGTH));
891        }
892        let mut sig_bytes = [0; Self::LENGTH];
893        sig_bytes.copy_from_slice(bytes);
894        Ok(Self(sig_bytes))
895    }
896}
897
898impl Signer<Signature> for Secp256r1KeyPair {
899    fn sign(&self, msg: &[u8]) -> Signature {
900        Secp256r1IotaSignature::new(self, msg).into()
901    }
902}
903
904// This struct exists due to the limitations of the `enum_dispatch` library.
905//
906pub trait IotaSignatureInner: Sized + ToFromBytes + PartialEq + Eq + Hash {
907    type Sig: Authenticator<PubKey = Self::PubKey>;
908    type PubKey: VerifyingKey<Sig = Self::Sig> + IotaPublicKey;
909    type KeyPair: KeypairTraits<PubKey = Self::PubKey, Sig = Self::Sig>;
910
911    const LENGTH: usize = Self::Sig::LENGTH + Self::PubKey::LENGTH + 1;
912    const SCHEME: SignatureScheme = Self::PubKey::SIGNATURE_SCHEME;
913
914    /// Returns the deserialized signature and deserialized pubkey.
915    fn get_verification_inputs(&self) -> IotaResult<(Self::Sig, Self::PubKey)> {
916        let pk = Self::PubKey::from_bytes(self.public_key_bytes())
917            .map_err(|_| IotaError::KeyConversion("Invalid public key".to_string()))?;
918
919        // deserialize the signature
920        let signature = Self::Sig::from_bytes(self.signature_bytes()).map_err(|_| {
921            IotaError::InvalidSignature {
922                error: "Fail to get pubkey and sig".to_string(),
923            }
924        })?;
925
926        Ok((signature, pk))
927    }
928
929    fn new(kp: &Self::KeyPair, message: &[u8]) -> Self {
930        let sig = Signer::sign(kp, message);
931
932        let mut signature_bytes: Vec<u8> = Vec::new();
933        signature_bytes
934            .extend_from_slice(&[<Self::PubKey as IotaPublicKey>::SIGNATURE_SCHEME.flag()]);
935        signature_bytes.extend_from_slice(sig.as_ref());
936        signature_bytes.extend_from_slice(kp.public().as_ref());
937        Self::from_bytes(&signature_bytes[..])
938            .expect("Serialized signature did not have expected size")
939    }
940}
941
942pub trait IotaPublicKey: VerifyingKey {
943    const SIGNATURE_SCHEME: SignatureScheme;
944}
945
946#[enum_dispatch(Signature)]
947pub trait IotaSignature: Sized + ToFromBytes {
948    fn signature_bytes(&self) -> &[u8];
949    fn public_key_bytes(&self) -> &[u8];
950    fn scheme(&self) -> SignatureScheme;
951
952    fn verify_secure<T>(
953        &self,
954        value: &IntentMessage<T>,
955        author: IotaAddress,
956        scheme: SignatureScheme,
957    ) -> IotaResult<()>
958    where
959        T: Serialize;
960}
961
962impl<S: IotaSignatureInner + Sized> IotaSignature for S {
963    fn signature_bytes(&self) -> &[u8] {
964        // Access array slice is safe because the array bytes is initialized as
965        // flag || signature || pubkey with its defined length.
966        &self.as_ref()[1..1 + S::Sig::LENGTH]
967    }
968
969    fn public_key_bytes(&self) -> &[u8] {
970        // Access array slice is safe because the array bytes is initialized as
971        // flag || signature || pubkey with its defined length.
972        &self.as_ref()[S::Sig::LENGTH + 1..]
973    }
974
975    fn scheme(&self) -> SignatureScheme {
976        S::PubKey::SIGNATURE_SCHEME
977    }
978
979    #[instrument(level = "trace", skip_all)]
980    fn verify_secure<T>(
981        &self,
982        value: &IntentMessage<T>,
983        author: IotaAddress,
984        _scheme: SignatureScheme,
985    ) -> Result<(), IotaError>
986    where
987        T: Serialize,
988    {
989        let mut hasher = DefaultHash::default();
990        hasher.update(bcs::to_bytes(&value).expect("Message serialization should not fail"));
991        let digest = hasher.finalize().digest;
992
993        let (sig, pk) = &self.get_verification_inputs()?;
994        let address = address_from_iota_pub_key(pk);
995        if author != address {
996            return Err(IotaError::IncorrectSigner {
997                error: format!("Incorrect signer, expected {author:?}, got {address:?}"),
998            });
999        }
1000
1001        pk.verify(&digest, sig)
1002            .map_err(|e| IotaError::InvalidSignature {
1003                error: format!("Fail to verify user sig {e}"),
1004            })
1005    }
1006}
1007
1008/// AuthoritySignInfoTrait is a trait used specifically for a few structs in
1009/// messages.rs to template on whether the struct is signed by an authority. We
1010/// want to limit how those structs can be instantiated on, hence the sealed
1011/// trait. TODO: We could also add the aggregated signature as another impl of
1012/// the trait.       This will make CertifiedTransaction also an instance of the
1013/// same struct.
1014pub trait AuthoritySignInfoTrait: private::SealedAuthoritySignInfoTrait {
1015    fn verify_secure<T: Serialize>(
1016        &self,
1017        data: &T,
1018        intent: Intent,
1019        committee: &Committee,
1020    ) -> IotaResult;
1021
1022    fn add_to_verification_obligation<'a>(
1023        &self,
1024        committee: &'a Committee,
1025        obligation: &mut VerificationObligation<'a>,
1026        message_index: usize,
1027    ) -> IotaResult<()>;
1028}
1029
1030#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
1031pub struct EmptySignInfo {}
1032impl AuthoritySignInfoTrait for EmptySignInfo {
1033    fn verify_secure<T: Serialize>(
1034        &self,
1035        _data: &T,
1036        _intent: Intent,
1037        _committee: &Committee,
1038    ) -> IotaResult {
1039        Ok(())
1040    }
1041
1042    fn add_to_verification_obligation<'a>(
1043        &self,
1044        _committee: &'a Committee,
1045        _obligation: &mut VerificationObligation<'a>,
1046        _message_index: usize,
1047    ) -> IotaResult<()> {
1048        Ok(())
1049    }
1050}
1051
1052#[derive(Clone, Debug, Eq, Serialize, Deserialize)]
1053pub struct AuthoritySignInfo {
1054    pub epoch: EpochId,
1055    pub authority: AuthorityName,
1056    pub signature: AuthoritySignature,
1057}
1058
1059impl AuthoritySignInfoTrait for AuthoritySignInfo {
1060    #[instrument(level = "trace", skip_all)]
1061    fn verify_secure<T: Serialize>(
1062        &self,
1063        data: &T,
1064        intent: Intent,
1065        committee: &Committee,
1066    ) -> IotaResult<()> {
1067        let mut obligation = VerificationObligation::default();
1068        let idx = obligation.add_message(data, self.epoch, intent);
1069        self.add_to_verification_obligation(committee, &mut obligation, idx)?;
1070        obligation.verify_all()?;
1071        Ok(())
1072    }
1073
1074    fn add_to_verification_obligation<'a>(
1075        &self,
1076        committee: &'a Committee,
1077        obligation: &mut VerificationObligation<'a>,
1078        message_index: usize,
1079    ) -> IotaResult<()> {
1080        fp_ensure!(
1081            self.epoch == committee.epoch(),
1082            IotaError::WrongEpoch {
1083                expected_epoch: committee.epoch(),
1084                actual_epoch: self.epoch,
1085            }
1086        );
1087        let weight = committee.weight(&self.authority);
1088        fp_ensure!(
1089            weight > 0,
1090            IotaError::UnknownSigner {
1091                signer: Some(self.authority.concise().to_string()),
1092                index: None,
1093                committee: Box::new(committee.clone())
1094            }
1095        );
1096
1097        obligation
1098            .public_keys
1099            .get_mut(message_index)
1100            .ok_or(IotaError::InvalidAddress)?
1101            .push(committee.public_key(&self.authority)?);
1102        obligation
1103            .signatures
1104            .get_mut(message_index)
1105            .ok_or(IotaError::InvalidAddress)?
1106            .add_signature(self.signature.clone())
1107            .map_err(|_| IotaError::InvalidSignature {
1108                error: "Fail to aggregator auth sig".to_string(),
1109            })?;
1110        Ok(())
1111    }
1112}
1113
1114impl AuthoritySignInfo {
1115    pub fn new<T>(
1116        epoch: EpochId,
1117        value: &T,
1118        intent: Intent,
1119        name: AuthorityName,
1120        secret: &dyn Signer<AuthoritySignature>,
1121    ) -> Self
1122    where
1123        T: Serialize,
1124    {
1125        Self {
1126            epoch,
1127            authority: name,
1128            signature: AuthoritySignature::new_secure(
1129                &IntentMessage::new(intent, value),
1130                &epoch,
1131                secret,
1132            ),
1133        }
1134    }
1135}
1136
1137impl Hash for AuthoritySignInfo {
1138    fn hash<H: Hasher>(&self, state: &mut H) {
1139        self.epoch.hash(state);
1140        self.authority.hash(state);
1141    }
1142}
1143
1144impl Display for AuthoritySignInfo {
1145    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1146        write!(
1147            f,
1148            "AuthoritySignInfo {{ epoch: {:?}, authority: {} }}",
1149            self.epoch, self.authority,
1150        )
1151    }
1152}
1153
1154impl PartialEq for AuthoritySignInfo {
1155    fn eq(&self, other: &Self) -> bool {
1156        // We do not compare the signature, because there can be multiple
1157        // valid signatures for the same epoch and authority.
1158        self.epoch == other.epoch && self.authority == other.authority
1159    }
1160}
1161
1162/// Represents at least a quorum (could be more) of authority signatures.
1163/// STRONG_THRESHOLD indicates whether to use the quorum threshold for quorum
1164/// check. When STRONG_THRESHOLD is true, the quorum is valid when the total
1165/// stake is at least the quorum threshold (2f+1) of the committee; when
1166/// STRONG_THRESHOLD is false, the quorum is valid when the total stake is at
1167/// least the validity threshold (f+1) of the committee.
1168#[serde_as]
1169#[derive(Clone, Debug, Serialize, Deserialize)]
1170pub struct AuthorityQuorumSignInfo<const STRONG_THRESHOLD: bool> {
1171    pub epoch: EpochId,
1172    pub signature: AggregateAuthoritySignature,
1173    #[serde_as(as = "IotaBitmap")]
1174    pub signers_map: RoaringBitmap,
1175}
1176
1177pub type AuthorityStrongQuorumSignInfo = AuthorityQuorumSignInfo<true>;
1178
1179// Variant of [AuthorityStrongQuorumSignInfo] but with a serialized signature,
1180// to be used in external APIs.
1181#[serde_as]
1182#[derive(Clone, Debug, Serialize, Deserialize)]
1183pub struct IotaAuthorityStrongQuorumSignInfo {
1184    pub epoch: EpochId,
1185    pub signature: AggregateAuthoritySignatureAsBytes,
1186    #[serde_as(as = "IotaBitmap")]
1187    pub signers_map: RoaringBitmap,
1188}
1189
1190impl From<&AuthorityStrongQuorumSignInfo> for IotaAuthorityStrongQuorumSignInfo {
1191    fn from(info: &AuthorityStrongQuorumSignInfo) -> Self {
1192        Self {
1193            epoch: info.epoch,
1194            signature: (&info.signature).into(),
1195            signers_map: info.signers_map.clone(),
1196        }
1197    }
1198}
1199
1200impl TryFrom<&IotaAuthorityStrongQuorumSignInfo> for AuthorityStrongQuorumSignInfo {
1201    type Error = FastCryptoError;
1202
1203    fn try_from(info: &IotaAuthorityStrongQuorumSignInfo) -> Result<Self, Self::Error> {
1204        Ok(Self {
1205            epoch: info.epoch,
1206            signature: (&info.signature).try_into()?,
1207            signers_map: info.signers_map.clone(),
1208        })
1209    }
1210}
1211
1212// Note: if you meet an error due to this line it may be because you need an Eq
1213// implementation for `CertifiedTransaction`, or one of the structs that include
1214// it, i.e. `ConfirmationTransaction`, `TransactionInfoResponse` or
1215// `ObjectInfoResponse`.
1216//
1217// Please note that any such implementation must be agnostic to the exact set of
1218// signatures in the certificate, as clients are allowed to equivocate on the
1219// exact nature of valid certificates they send to the system. This assertion is
1220// a simple tool to make sure certificates are accounted for correctly - should
1221// you remove it, you're on your own to maintain the invariant that valid
1222// certificates with distinct signatures are equivalent, but yet-unchecked
1223// certificates that differ on signers aren't.
1224//
1225// see also https://github.com/iotaledger/iota/issues/266
1226static_assertions::assert_not_impl_any!(AuthorityStrongQuorumSignInfo: Hash, Eq, PartialEq);
1227
1228impl<const STRONG_THRESHOLD: bool> AuthoritySignInfoTrait
1229    for AuthorityQuorumSignInfo<STRONG_THRESHOLD>
1230{
1231    #[instrument(level = "trace", skip_all)]
1232    fn verify_secure<T: Serialize>(
1233        &self,
1234        data: &T,
1235        intent: Intent,
1236        committee: &Committee,
1237    ) -> IotaResult {
1238        let mut obligation = VerificationObligation::default();
1239        let idx = obligation.add_message(data, self.epoch, intent);
1240        self.add_to_verification_obligation(committee, &mut obligation, idx)?;
1241        obligation.verify_all()?;
1242        Ok(())
1243    }
1244
1245    fn add_to_verification_obligation<'a>(
1246        &self,
1247        committee: &'a Committee,
1248        obligation: &mut VerificationObligation<'a>,
1249        message_index: usize,
1250    ) -> IotaResult<()> {
1251        // Check epoch
1252        fp_ensure!(
1253            self.epoch == committee.epoch(),
1254            IotaError::WrongEpoch {
1255                expected_epoch: committee.epoch(),
1256                actual_epoch: self.epoch,
1257            }
1258        );
1259
1260        let mut weight = 0;
1261
1262        // Create obligations for the committee signatures
1263        obligation
1264            .signatures
1265            .get_mut(message_index)
1266            .ok_or(IotaError::InvalidAuthenticator)?
1267            .add_aggregate(self.signature.clone())
1268            .map_err(|_| IotaError::InvalidSignature {
1269                error: "Signature Aggregation failed".to_string(),
1270            })?;
1271
1272        let selected_public_keys = obligation
1273            .public_keys
1274            .get_mut(message_index)
1275            .ok_or(IotaError::InvalidAuthenticator)?;
1276
1277        for authority_index in self.signers_map.iter() {
1278            let authority = committee
1279                .authority_by_index(authority_index)
1280                .ok_or_else(|| IotaError::UnknownSigner {
1281                    signer: None,
1282                    index: Some(authority_index),
1283                    committee: Box::new(committee.clone()),
1284                })?;
1285            let voting_rights = committee.weight(authority);
1286            fp_ensure!(
1287                voting_rights > 0,
1288                IotaError::UnknownSigner {
1289                    signer: Some(authority.concise().to_string()),
1290                    index: Some(authority_index),
1291                    committee: Box::new(committee.clone()),
1292                }
1293            );
1294            weight += voting_rights;
1295
1296            selected_public_keys.push(committee.public_key(authority)?);
1297        }
1298
1299        fp_ensure!(
1300            weight >= Self::quorum_threshold(committee),
1301            IotaError::CertificateRequiresQuorum
1302        );
1303
1304        Ok(())
1305    }
1306}
1307
1308impl<const STRONG_THRESHOLD: bool> AuthorityQuorumSignInfo<STRONG_THRESHOLD> {
1309    pub fn new_from_auth_sign_infos(
1310        auth_sign_infos: Vec<AuthoritySignInfo>,
1311        committee: &Committee,
1312    ) -> IotaResult<Self> {
1313        fp_ensure!(
1314            auth_sign_infos.iter().all(|a| a.epoch == committee.epoch),
1315            IotaError::InvalidSignature {
1316                error: "All signatures must be from the same epoch as the committee".to_string()
1317            }
1318        );
1319        let total_stake: StakeUnit = auth_sign_infos
1320            .iter()
1321            .map(|a| committee.weight(&a.authority))
1322            .sum();
1323        fp_ensure!(
1324            total_stake >= Self::quorum_threshold(committee),
1325            IotaError::InvalidSignature {
1326                error: "Signatures don't have enough stake to form a quorum".to_string()
1327            }
1328        );
1329
1330        let signatures: BTreeMap<_, _> = auth_sign_infos
1331            .into_iter()
1332            .map(|a| (a.authority, a.signature))
1333            .collect();
1334        let mut map = RoaringBitmap::new();
1335        for pk in signatures.keys() {
1336            map.insert(
1337                committee
1338                    .authority_index(pk)
1339                    .ok_or_else(|| IotaError::UnknownSigner {
1340                        signer: Some(pk.concise().to_string()),
1341                        index: None,
1342                        committee: Box::new(committee.clone()),
1343                    })?,
1344            );
1345        }
1346        let sigs: Vec<AuthoritySignature> = signatures.into_values().collect();
1347
1348        Ok(AuthorityQuorumSignInfo {
1349            epoch: committee.epoch,
1350            signature: AggregateAuthoritySignature::aggregate(&sigs).map_err(|e| {
1351                IotaError::InvalidSignature {
1352                    error: e.to_string(),
1353                }
1354            })?,
1355            signers_map: map,
1356        })
1357    }
1358
1359    pub fn authorities<'a>(
1360        &'a self,
1361        committee: &'a Committee,
1362    ) -> impl Iterator<Item = IotaResult<&'a AuthorityName>> {
1363        self.signers_map.iter().map(|i| {
1364            committee
1365                .authority_by_index(i)
1366                .ok_or(IotaError::InvalidAuthenticator)
1367        })
1368    }
1369
1370    pub fn quorum_threshold(committee: &Committee) -> StakeUnit {
1371        committee.threshold::<STRONG_THRESHOLD>()
1372    }
1373
1374    pub fn len(&self) -> u64 {
1375        self.signers_map.len()
1376    }
1377
1378    pub fn is_empty(&self) -> bool {
1379        self.signers_map.is_empty()
1380    }
1381}
1382
1383impl<const S: bool> Display for AuthorityQuorumSignInfo<S> {
1384    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1385        writeln!(
1386            f,
1387            "{} {{ epoch: {:?}, signers_map: {:?} }}",
1388            if S {
1389                "AuthorityStrongQuorumSignInfo"
1390            } else {
1391                "AuthorityWeakQuorumSignInfo"
1392            },
1393            self.epoch,
1394            self.signers_map,
1395        )?;
1396        Ok(())
1397    }
1398}
1399
1400mod private {
1401    pub trait SealedAuthoritySignInfoTrait {}
1402    impl SealedAuthoritySignInfoTrait for super::EmptySignInfo {}
1403    impl SealedAuthoritySignInfoTrait for super::AuthoritySignInfo {}
1404    impl<const S: bool> SealedAuthoritySignInfoTrait for super::AuthorityQuorumSignInfo<S> {}
1405}
1406
1407/// Something that we know how to hash and sign.
1408pub trait Signable<W> {
1409    fn write(&self, writer: &mut W);
1410}
1411
1412pub trait SignableBytes
1413where
1414    Self: Sized,
1415{
1416    fn from_signable_bytes(bytes: &[u8]) -> Result<Self, Error>;
1417}
1418
1419/// Activate the blanket implementation of `Signable` based on serde and BCS.
1420/// * We use `serde_name` to extract a seed from the name of structs and enums.
1421/// * We use `BCS` to generate canonical bytes suitable for hashing and signing.
1422///
1423/// # Safety
1424/// We protect the access to this marker trait through a "sealed trait" pattern:
1425/// impls must be add added here (nowehre else) which lets us note those impls
1426/// MUST be on types that comply with the `serde_name` machinery
1427/// for the below implementations not to panic. One way to check they work is to
1428/// write a unit test for serialization to / deserialization from signable
1429/// bytes.
1430mod bcs_signable {
1431
1432    pub trait BcsSignable: serde::Serialize + serde::de::DeserializeOwned {}
1433    impl BcsSignable for crate::committee::Committee {}
1434    impl BcsSignable for crate::messages_checkpoint::CheckpointSummary {}
1435    impl BcsSignable for crate::messages_checkpoint::CheckpointContents {}
1436    impl BcsSignable for crate::messages_consensus::VersionedMisbehaviorReport {}
1437
1438    impl BcsSignable for crate::effects::TransactionEffects {}
1439    impl BcsSignable for crate::effects::TransactionEvents {}
1440    impl BcsSignable for crate::transaction::TransactionData {}
1441    impl BcsSignable for crate::transaction::SenderSignedData {}
1442    impl BcsSignable for crate::object::ObjectInner {}
1443
1444    impl BcsSignable for crate::global_state_hash::GlobalStateHash {}
1445
1446    impl BcsSignable for super::bcs_signable_test::Foo {}
1447    #[cfg(test)]
1448    impl BcsSignable for super::bcs_signable_test::Bar {}
1449}
1450
1451impl<T, W> Signable<W> for T
1452where
1453    T: bcs_signable::BcsSignable,
1454    W: std::io::Write,
1455{
1456    fn write(&self, writer: &mut W) {
1457        let name = serde_name::trace_name::<Self>().expect("Self must be a struct or an enum");
1458        // Note: This assumes that names never contain the separator `::`.
1459        write!(writer, "{name}::").expect("Hasher should not fail");
1460        bcs::serialize_into(writer, &self).expect("Message serialization should not fail");
1461    }
1462}
1463
1464/// Manual [`Signable`] impl for MoveAuthenticator.
1465///
1466/// `serde_name::trace_name` returns `None` for types that carry
1467/// `#[serde(flatten)]`, so the blanket impl via `BcsSignable` panics.
1468/// We hardcode the tag and serialise via `self.inner` — the same
1469/// representation that `AsRef<[u8]>` already uses.
1470impl<W> Signable<W> for crate::move_authenticator::MoveAuthenticator
1471where
1472    W: std::io::Write,
1473{
1474    fn write(&self, writer: &mut W) {
1475        let name = "MoveAuthenticator";
1476        write!(writer, "{name}::").expect("Hasher should not fail");
1477        bcs::serialize_into(writer, &self.inner).expect("Message serialization should not fail");
1478    }
1479}
1480
1481impl SignableBytes for crate::move_authenticator::MoveAuthenticator {
1482    fn from_signable_bytes(bytes: &[u8]) -> Result<Self, Error> {
1483        let name = "MoveAuthenticator";
1484        let name_byte_len = format!("{name}::").bytes().len();
1485        let inner = bcs::from_bytes(
1486            bytes
1487                .get(name_byte_len..)
1488                .ok_or_else(|| anyhow!("Failed to deserialize to {name}."))?,
1489        )?;
1490        Ok(Self::from_inner(inner))
1491    }
1492}
1493
1494impl<W> Signable<W> for EpochId
1495where
1496    W: std::io::Write,
1497{
1498    fn write(&self, writer: &mut W) {
1499        bcs::serialize_into(writer, &self).expect("Message serialization should not fail");
1500    }
1501}
1502
1503impl<T> SignableBytes for T
1504where
1505    T: bcs_signable::BcsSignable,
1506{
1507    fn from_signable_bytes(bytes: &[u8]) -> Result<Self, Error> {
1508        // Remove name tag before deserialization using BCS
1509        let name = serde_name::trace_name::<Self>().expect("Self should be a struct or an enum");
1510        let name_byte_len = format!("{name}::").bytes().len();
1511        Ok(bcs::from_bytes(bytes.get(name_byte_len..).ok_or_else(
1512            || anyhow!("Failed to deserialize to {name}."),
1513        )?)?)
1514    }
1515}
1516
1517fn hash<S: Signable<H>, H: HashFunction<DIGEST_SIZE>, const DIGEST_SIZE: usize>(
1518    signable: &S,
1519) -> [u8; DIGEST_SIZE] {
1520    let mut digest = H::default();
1521    signable.write(&mut digest);
1522    let hash = digest.finalize();
1523    hash.into()
1524}
1525
1526pub fn default_hash<S: Signable<DefaultHash>>(signable: &S) -> [u8; 32] {
1527    hash::<S, DefaultHash, 32>(signable)
1528}
1529
1530#[derive(Default)]
1531pub struct VerificationObligation<'a> {
1532    pub messages: Vec<Vec<u8>>,
1533    pub signatures: Vec<AggregateAuthoritySignature>,
1534    pub public_keys: Vec<Vec<&'a AuthorityPublicKey>>,
1535}
1536
1537impl<'a> VerificationObligation<'a> {
1538    pub fn new() -> VerificationObligation<'a> {
1539        VerificationObligation::default()
1540    }
1541
1542    /// Add a new message to the list of messages to be verified.
1543    /// Returns the index of the message.
1544    pub fn add_message<T>(&mut self, message_value: &T, epoch: EpochId, intent: Intent) -> usize
1545    where
1546        T: Serialize,
1547    {
1548        let intent_msg = IntentMessage::new(intent, message_value);
1549        let mut intent_msg_bytes =
1550            bcs::to_bytes(&intent_msg).expect("Message serialization should not fail");
1551        epoch.write(&mut intent_msg_bytes);
1552        self.signatures.push(AggregateAuthoritySignature::default());
1553        self.public_keys.push(Vec::new());
1554        self.messages.push(intent_msg_bytes);
1555        self.messages.len() - 1
1556    }
1557
1558    // Attempts to add signature and public key to the obligation. If this fails,
1559    // ensure to call `verify` manually.
1560    pub fn add_signature_and_public_key(
1561        &mut self,
1562        signature: &AuthoritySignature,
1563        public_key: &'a AuthorityPublicKey,
1564        idx: usize,
1565    ) -> IotaResult<()> {
1566        self.public_keys
1567            .get_mut(idx)
1568            .ok_or(IotaError::InvalidAuthenticator)?
1569            .push(public_key);
1570        self.signatures
1571            .get_mut(idx)
1572            .ok_or(IotaError::InvalidAuthenticator)?
1573            .add_signature(signature.clone())
1574            .map_err(|_| IotaError::InvalidSignature {
1575                error: "Failed to add signature to obligation".to_string(),
1576            })?;
1577        Ok(())
1578    }
1579
1580    #[instrument(level = "trace", skip_all)]
1581    pub fn verify_all(self) -> IotaResult<()> {
1582        let mut pks = Vec::with_capacity(self.public_keys.len());
1583        for pk in self.public_keys.clone() {
1584            pks.push(pk.into_iter());
1585        }
1586        AggregateAuthoritySignature::batch_verify(
1587            &self.signatures.iter().collect::<Vec<_>>()[..],
1588            pks,
1589            &self.messages.iter().map(|x| &x[..]).collect::<Vec<_>>()[..],
1590        )
1591        .map_err(|e| {
1592            let message = format!(
1593                "pks: {:?}, messages: {:?}, sigs: {:?}",
1594                &self.public_keys,
1595                self.messages
1596                    .iter()
1597                    .map(Base64::encode)
1598                    .collect::<Vec<String>>(),
1599                &self
1600                    .signatures
1601                    .iter()
1602                    .map(|s| Base64::encode(s.as_ref()))
1603                    .collect::<Vec<String>>()
1604            );
1605
1606            let chunk_size = 2048;
1607
1608            // This error message may be very long, so we print out the error in chunks of
1609            // to avoid hitting a max log line length on the system.
1610            for (i, chunk) in message
1611                .as_bytes()
1612                .chunks(chunk_size)
1613                .map(std::str::from_utf8)
1614                .enumerate()
1615            {
1616                warn!(
1617                    "Failed to batch verify aggregated auth sig: {} (chunk {}): {}",
1618                    e,
1619                    i,
1620                    chunk.unwrap()
1621                );
1622            }
1623
1624            IotaError::InvalidSignature {
1625                error: format!("Failed to batch verify aggregated auth sig: {e}"),
1626            }
1627        })?;
1628        Ok(())
1629    }
1630}
1631
1632pub mod bcs_signable_test {
1633    use serde::{Deserialize, Serialize};
1634
1635    #[derive(Clone, Serialize, Deserialize)]
1636    pub struct Foo(pub String);
1637
1638    #[cfg(test)]
1639    #[derive(Serialize, Deserialize)]
1640    pub struct Bar(pub String);
1641
1642    #[cfg(test)]
1643    use super::VerificationObligation;
1644
1645    #[cfg(test)]
1646    pub fn get_obligation_input<T>(value: &T) -> (VerificationObligation<'_>, usize)
1647    where
1648        T: super::bcs_signable::BcsSignable,
1649    {
1650        use iota_sdk_types::crypto::{Intent, IntentScope};
1651
1652        let mut obligation = VerificationObligation::default();
1653        // Add the obligation of the authority signature verifications.
1654        let idx = obligation.add_message(
1655            value,
1656            0,
1657            Intent::iota_app(IntentScope::SenderSignedTransaction),
1658        );
1659        (obligation, idx)
1660    }
1661}
1662
1663#[iota_proc_macros::allow_deprecated_for_derives]
1664#[derive(
1665    Clone, Copy, Deserialize, Serialize, Debug, EnumString, strum_macros::Display, PartialEq, Eq,
1666)]
1667#[strum(serialize_all = "lowercase")]
1668pub enum SignatureScheme {
1669    ED25519,
1670    Secp256k1,
1671    Secp256r1,
1672    BLS12381, // This is currently not supported for user Iota Address.
1673    MultiSig,
1674    #[deprecated(note = "zkLogin is deprecated and was never enabled on IOTA")]
1675    ZkLoginAuthenticatorDeprecated,
1676    PasskeyAuthenticator,
1677    MoveAuthenticator,
1678}
1679
1680impl SignatureScheme {
1681    pub fn flag(&self) -> u8 {
1682        match self {
1683            SignatureScheme::ED25519 => 0x00,
1684            SignatureScheme::Secp256k1 => 0x01,
1685            SignatureScheme::Secp256r1 => 0x02,
1686            SignatureScheme::MultiSig => 0x03,
1687            SignatureScheme::BLS12381 => 0x04, // This is currently not supported for user Iota
1688            // Address.
1689            #[allow(deprecated)]
1690            SignatureScheme::ZkLoginAuthenticatorDeprecated => 0x05,
1691            SignatureScheme::PasskeyAuthenticator => 0x06,
1692            SignatureScheme::MoveAuthenticator => 0x07,
1693        }
1694    }
1695
1696    /// Takes as input an hasher and updates it with a flag byte if the input
1697    /// scheme is not ED25519; it does nothing otherwise.
1698    pub fn update_hasher_with_flag(&self, hasher: &mut DefaultHash) {
1699        match self {
1700            SignatureScheme::ED25519 => (),
1701            _ => hasher.update([self.flag()]),
1702        };
1703    }
1704
1705    pub fn from_flag(flag: &str) -> Result<SignatureScheme, IotaError> {
1706        let byte_int = flag
1707            .parse::<u8>()
1708            .map_err(|_| IotaError::KeyConversion("Invalid key scheme".to_string()))?;
1709        Self::from_flag_byte(&byte_int)
1710    }
1711
1712    pub fn from_flag_byte(byte_int: &u8) -> Result<SignatureScheme, IotaError> {
1713        match byte_int {
1714            0x00 => Ok(SignatureScheme::ED25519),
1715            0x01 => Ok(SignatureScheme::Secp256k1),
1716            0x02 => Ok(SignatureScheme::Secp256r1),
1717            0x03 => Ok(SignatureScheme::MultiSig),
1718            0x04 => Ok(SignatureScheme::BLS12381),
1719            #[allow(deprecated)]
1720            0x05 => Ok(SignatureScheme::ZkLoginAuthenticatorDeprecated),
1721            0x06 => Ok(SignatureScheme::PasskeyAuthenticator),
1722            0x07 => Ok(SignatureScheme::MoveAuthenticator),
1723            _ => Err(IotaError::KeyConversion("Invalid key scheme".to_string())),
1724        }
1725    }
1726}
1727/// Unlike [enum Signature], [enum CompressedSignature] does not contain public
1728/// key.
1729#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1730pub enum CompressedSignature {
1731    Ed25519(Ed25519SignatureAsBytes),
1732    Secp256k1(Secp256k1SignatureAsBytes),
1733    Secp256r1(Secp256r1SignatureAsBytes),
1734    #[deprecated(note = "zkLogin is deprecated and was never enabled on IOTA")]
1735    ZkLoginDeprecated,
1736    Passkey(PasskeyAuthenticatorAsBytes),
1737    Move(MoveAuthenticatorAsBytes),
1738}
1739
1740#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1741pub struct PasskeyAuthenticatorAsBytes(pub Vec<u8>);
1742
1743#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1744pub struct MoveAuthenticatorAsBytes(pub Vec<u8>);
1745
1746impl AsRef<[u8]> for CompressedSignature {
1747    fn as_ref(&self) -> &[u8] {
1748        match self {
1749            CompressedSignature::Ed25519(sig) => &sig.0,
1750            CompressedSignature::Secp256k1(sig) => &sig.0,
1751            CompressedSignature::Secp256r1(sig) => &sig.0,
1752            #[allow(deprecated)]
1753            CompressedSignature::ZkLoginDeprecated => &[],
1754            CompressedSignature::Passkey(sig) => &sig.0,
1755            CompressedSignature::Move(sig) => &sig.0,
1756        }
1757    }
1758}
1759
1760impl FromStr for Signature {
1761    type Err = eyre::Report;
1762    fn from_str(s: &str) -> Result<Self, Self::Err> {
1763        Self::decode_base64(s).map_err(|e| eyre!("Fail to decode base64 {}", e.to_string()))
1764    }
1765}
1766
1767impl FromStr for PublicKey {
1768    type Err = eyre::Report;
1769    fn from_str(s: &str) -> Result<Self, Self::Err> {
1770        Self::decode_base64(s).map_err(|e| eyre!("Fail to decode base64 {}", e.to_string()))
1771    }
1772}
1773
1774impl FromStr for GenericSignature {
1775    type Err = eyre::Report;
1776    fn from_str(s: &str) -> Result<Self, Self::Err> {
1777        Self::decode_base64(s).map_err(|e| eyre!("Fail to decode base64 {}", e.to_string()))
1778    }
1779}
1780
1781// Types for randomness generation
1782//
1783pub type RandomnessSignature = fastcrypto_tbls::types::Signature;
1784pub type RandomnessPartialSignature = fastcrypto_tbls::tbls::PartialSignature<RandomnessSignature>;
1785pub type RandomnessPrivateKey =
1786    fastcrypto_tbls::ecies_v1::PrivateKey<fastcrypto::groups::bls12381::G2Element>;