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