Skip to main content

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