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
7use std::{
8    collections::BTreeMap,
9    fmt::{Debug, Display, Formatter},
10    hash::{Hash, Hasher},
11    str::FromStr,
12};
13
14use anyhow::{Error, anyhow};
15use derive_more::{AsRef, From};
16pub use enum_dispatch::enum_dispatch;
17use eyre::eyre;
18pub use fastcrypto::traits::{
19    AggregateAuthenticator, Authenticator, EncodeDecodeBase64, KeyPair as KeypairTraits, Signer,
20    SigningKey, ToFromBytes, VerifyingKey,
21};
22use fastcrypto::{
23    bls12381::min_sig::{
24        BLS12381AggregateSignature, BLS12381AggregateSignatureAsBytes, BLS12381KeyPair,
25        BLS12381PrivateKey, BLS12381PublicKey, BLS12381Signature,
26    },
27    ed25519::{Ed25519KeyPair, Ed25519PublicKey, Ed25519PublicKeyAsBytes, Ed25519Signature},
28    encoding::{Base64, Encoding, Hex},
29    error::{FastCryptoError, FastCryptoResult},
30    hash::{Blake2b256, HashFunction},
31    secp256k1::{Secp256k1PublicKey, Secp256k1PublicKeyAsBytes},
32    secp256r1::{Secp256r1PublicKey, Secp256r1PublicKeyAsBytes},
33    serde_helpers::BytesRepresentation,
34};
35use iota_sdk_crypto::{
36    ed25519::Ed25519PrivateKey, secp256k1::Secp256k1PrivateKey, secp256r1::Secp256r1PrivateKey,
37    simple::SimpleKeypair,
38};
39use iota_sdk_types::{
40    Address, SignatureScheme,
41    crypto::{Intent, IntentMessage, IntentScope, SimpleSignature},
42};
43use rand::{
44    SeedableRng,
45    rngs::{OsRng, StdRng},
46};
47use roaring::RoaringBitmap;
48use serde::{Deserialize, Serialize};
49use serde_with::{Bytes, serde_as};
50use tracing::{instrument, warn};
51
52use crate::{
53    base_types::{AuthorityName, ConciseableName},
54    committee::{Committee, CommitteeTrait, EpochId, StakeUnit},
55    error::{IotaError, IotaResult},
56    iota_serde::{IotaBitmap, Readable},
57};
58
59#[cfg(test)]
60#[path = "unit_tests/crypto_tests.rs"]
61mod crypto_tests;
62
63#[cfg(test)]
64#[path = "unit_tests/intent_tests.rs"]
65mod intent_tests;
66
67////////////////////////////////////////////////////////////////////////
68// Type aliases selecting the signature algorithm for the code base.
69////////////////////////////////////////////////////////////////////////
70// Here we select the types that are used by default in the code base.
71// The whole code base should only:
72// - refer to those aliases and not use the individual scheme implementations
73// - not use the schemes in a way that break genericity (e.g. using their Struct
74//   impl functions)
75// - swap one of those aliases to point to another type if necessary
76//
77// Beware: if you change those aliases to point to another scheme
78// implementation, you will have to change all related aliases to point to
79// concrete types that work with each other. Failure to do so will result in a
80// ton of compilation errors, and worse: it will not make sense!
81
82// Authority Objects
83pub type AuthorityKeyPair = BLS12381KeyPair;
84pub type AuthorityPublicKey = BLS12381PublicKey;
85pub type AuthorityPrivateKey = BLS12381PrivateKey;
86pub type AuthoritySignature = BLS12381Signature;
87pub type AggregateAuthoritySignature = BLS12381AggregateSignature;
88pub type AggregateAuthoritySignatureAsBytes = BLS12381AggregateSignatureAsBytes;
89
90pub type AccountKeyPair = Ed25519PrivateKey;
91
92pub type NetworkKeyPair = Ed25519KeyPair;
93pub type NetworkPublicKey = Ed25519PublicKey;
94pub type NetworkPrivateKey = Ed25519PrivateKey;
95
96pub type DefaultHash = Blake2b256;
97
98pub const DEFAULT_EPOCH_ID: EpochId = 0;
99pub const IOTA_PRIV_KEY_PREFIX: &str = "iotaprivkey";
100
101/// Creates a proof of that the authority account address is owned by the
102/// holder of authority key, and also ensures that the authority
103/// public key exists. A proof of possession is an authority
104/// signature committed over the intent message `intent || message || epoch`
105/// (See more at [struct IntentMessage] and [struct Intent]) where the message
106/// is constructed as `authority_pubkey_bytes || authority_account_address`.
107pub fn generate_proof_of_possession(
108    keypair: &AuthorityKeyPair,
109    address: Address,
110) -> AuthoritySignature {
111    let mut msg: Vec<u8> = Vec::new();
112    msg.extend_from_slice(keypair.public().as_bytes());
113    msg.extend_from_slice(address.as_ref());
114    AuthoritySignature::new_secure(
115        &IntentMessage::new(Intent::iota_app(IntentScope::ProofOfPossession), msg),
116        &DEFAULT_EPOCH_ID,
117        keypair,
118    )
119}
120
121/// Verify proof of possession against the expected intent message,
122/// consisting of the authority pubkey and the authority account address.
123pub fn verify_proof_of_possession(
124    pop: &AuthoritySignature,
125    authority_pubkey: &AuthorityPublicKey,
126    iota_address: Address,
127) -> Result<(), IotaError> {
128    authority_pubkey
129        .validate()
130        .map_err(|_| IotaError::InvalidSignature {
131            error: "Fail to validate pubkey".to_string(),
132        })?;
133    let mut msg = authority_pubkey.as_bytes().to_vec();
134    msg.extend_from_slice(iota_address.as_ref());
135    pop.verify_secure(
136        &IntentMessage::new(Intent::iota_app(IntentScope::ProofOfPossession), msg),
137        DEFAULT_EPOCH_ID,
138        authority_pubkey.into(),
139    )
140}
141
142/// The validator network stacks keep using the fastcrypto ed25519 keypair
143/// type; this conversion lets those keys be stored in configs as
144/// [`SimpleKeypair`].
145pub fn network_to_simple_keypair(kp: &NetworkKeyPair) -> SimpleKeypair {
146    use iota_sdk_crypto::ToFromBytes as _;
147
148    SimpleKeypair::from(
149        Ed25519PrivateKey::from_bytes(kp.as_bytes()).expect("valid ed25519 private key bytes"),
150    )
151}
152
153/// Convert a stored [`SimpleKeypair`] back into the fastcrypto ed25519 keypair
154/// consumed by the validator network stacks. Fails if the key is not ed25519.
155pub fn simple_to_network_keypair(kp: &SimpleKeypair) -> Result<NetworkKeyPair, Error> {
156    if kp.scheme() != SignatureScheme::Ed25519 {
157        return Err(anyhow!(
158            "invalid scheme for network keypair: {}",
159            kp.scheme()
160        ));
161    }
162    NetworkKeyPair::from_bytes(&kp.to_bytes()[1..]).map_err(|e| anyhow!(e))
163}
164
165impl From<&SimpleKeypair> for PublicKey {
166    fn from(kp: &SimpleKeypair) -> Self {
167        match kp.public_key() {
168            iota_sdk_types::PublicKey::Ed25519(pk) => {
169                PublicKey::Ed25519(BytesRepresentation(pk.into_inner()))
170            }
171            iota_sdk_types::PublicKey::Secp256k1(pk) => {
172                PublicKey::Secp256k1(BytesRepresentation(pk.into_inner()))
173            }
174            iota_sdk_types::PublicKey::Secp256r1(pk) => {
175                PublicKey::Secp256r1(BytesRepresentation(pk.into_inner()))
176            }
177            _ => unreachable!("SimpleKeypair keys use the three simple signature schemes"),
178        }
179    }
180}
181
182#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
183pub enum PublicKey {
184    Ed25519(Ed25519PublicKeyAsBytes),
185    Secp256k1(Secp256k1PublicKeyAsBytes),
186    Secp256r1(Secp256r1PublicKeyAsBytes),
187    Passkey(Secp256r1PublicKeyAsBytes),
188}
189
190impl AsRef<[u8]> for PublicKey {
191    fn as_ref(&self) -> &[u8] {
192        match self {
193            PublicKey::Ed25519(pk) => &pk.0,
194            PublicKey::Secp256k1(pk) => &pk.0,
195            PublicKey::Secp256r1(pk) => &pk.0,
196            PublicKey::Passkey(pk) => &pk.0,
197        }
198    }
199}
200
201impl EncodeDecodeBase64 for PublicKey {
202    fn encode_base64(&self) -> String {
203        let mut bytes: Vec<u8> = Vec::new();
204        bytes.extend_from_slice(&[self.flag()]);
205        bytes.extend_from_slice(self.as_ref());
206        Base64::encode(&bytes[..])
207    }
208
209    fn decode_base64(value: &str) -> FastCryptoResult<Self> {
210        let bytes = Base64::decode(value)?;
211        match bytes.first() {
212            Some(x) => {
213                if x == &SignatureScheme::Ed25519.to_u8() {
214                    let pk: Ed25519PublicKey =
215                        Ed25519PublicKey::from_bytes(bytes.get(1..).ok_or(
216                            FastCryptoError::InputLengthWrong(Ed25519PublicKey::LENGTH + 1),
217                        )?)?;
218                    Ok(PublicKey::Ed25519((&pk).into()))
219                } else if x == &SignatureScheme::Secp256k1.to_u8() {
220                    let pk = Secp256k1PublicKey::from_bytes(bytes.get(1..).ok_or(
221                        FastCryptoError::InputLengthWrong(Secp256k1PublicKey::LENGTH + 1),
222                    )?)?;
223                    Ok(PublicKey::Secp256k1((&pk).into()))
224                } else if x == &SignatureScheme::Secp256r1.to_u8() {
225                    let pk = Secp256r1PublicKey::from_bytes(bytes.get(1..).ok_or(
226                        FastCryptoError::InputLengthWrong(Secp256r1PublicKey::LENGTH + 1),
227                    )?)?;
228                    Ok(PublicKey::Secp256r1((&pk).into()))
229                } else if x == &SignatureScheme::PasskeyAuthenticator.to_u8() {
230                    let pk = Secp256r1PublicKey::from_bytes(bytes.get(1..).ok_or(
231                        FastCryptoError::InputLengthWrong(Secp256r1PublicKey::LENGTH + 1),
232                    )?)?;
233                    Ok(PublicKey::Passkey((&pk).into()))
234                } else {
235                    Err(FastCryptoError::InvalidInput)
236                }
237            }
238            _ => Err(FastCryptoError::InvalidInput),
239        }
240    }
241}
242
243impl PublicKey {
244    pub fn flag(&self) -> u8 {
245        self.scheme().to_u8()
246    }
247
248    pub fn try_from_bytes(
249        curve: SignatureScheme,
250        key_bytes: &[u8],
251    ) -> Result<PublicKey, eyre::Report> {
252        match curve {
253            SignatureScheme::Ed25519 => Ok(PublicKey::Ed25519(
254                (&Ed25519PublicKey::from_bytes(key_bytes)?).into(),
255            )),
256            SignatureScheme::Secp256k1 => Ok(PublicKey::Secp256k1(
257                (&Secp256k1PublicKey::from_bytes(key_bytes)?).into(),
258            )),
259            SignatureScheme::Secp256r1 => Ok(PublicKey::Secp256r1(
260                (&Secp256r1PublicKey::from_bytes(key_bytes)?).into(),
261            )),
262            SignatureScheme::PasskeyAuthenticator => Ok(PublicKey::Passkey(
263                (&Secp256r1PublicKey::from_bytes(key_bytes)?).into(),
264            )),
265            _ => Err(eyre!("Unsupported curve")),
266        }
267    }
268
269    pub fn scheme(&self) -> SignatureScheme {
270        match self {
271            PublicKey::Ed25519(_) => SignatureScheme::Ed25519,
272            PublicKey::Secp256k1(_) => SignatureScheme::Secp256k1,
273            PublicKey::Secp256r1(_) => SignatureScheme::Secp256r1,
274            PublicKey::Passkey(_) => SignatureScheme::PasskeyAuthenticator,
275        }
276    }
277}
278
279/// Defines the compressed version of the public key that we pass around
280/// in IOTA.
281#[serde_as]
282#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, AsRef)]
283#[as_ref(forward)]
284pub struct AuthorityPublicKeyBytes(
285    #[serde_as(as = "Readable<Base64, Bytes>")] pub [u8; AuthorityPublicKey::LENGTH],
286);
287
288impl AuthorityPublicKeyBytes {
289    fn fmt_impl(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
290        let s = Hex::encode(self.0);
291        write!(f, "k#{s}")?;
292        Ok(())
293    }
294}
295
296impl<'a> ConciseableName<'a> for AuthorityPublicKeyBytes {
297    type ConciseTypeRef = ConciseAuthorityPublicKeyBytesRef<'a>;
298    type ConciseType = ConciseAuthorityPublicKeyBytes;
299
300    /// Get a ConciseAuthorityPublicKeyBytesRef. Usage:
301    ///
302    ///   debug!(name = ?authority.concise());
303    ///   format!("{:?}", authority.concise());
304    fn concise(&'a self) -> ConciseAuthorityPublicKeyBytesRef<'a> {
305        ConciseAuthorityPublicKeyBytesRef(self)
306    }
307
308    fn concise_owned(&self) -> ConciseAuthorityPublicKeyBytes {
309        ConciseAuthorityPublicKeyBytes(*self)
310    }
311}
312
313/// A wrapper around AuthorityPublicKeyBytes that provides a concise Debug impl.
314pub struct ConciseAuthorityPublicKeyBytesRef<'a>(&'a AuthorityPublicKeyBytes);
315
316impl Debug for ConciseAuthorityPublicKeyBytesRef<'_> {
317    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
318        let s = Hex::encode(self.0.0.get(0..4).ok_or(std::fmt::Error)?);
319        write!(f, "k#{s}..")
320    }
321}
322
323impl Display for ConciseAuthorityPublicKeyBytesRef<'_> {
324    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
325        Debug::fmt(self, f)
326    }
327}
328
329/// A wrapper around AuthorityPublicKeyBytes but owns it.
330#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
331pub struct ConciseAuthorityPublicKeyBytes(AuthorityPublicKeyBytes);
332
333impl Debug for ConciseAuthorityPublicKeyBytes {
334    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
335        let s = Hex::encode(self.0.0.get(0..4).ok_or(std::fmt::Error)?);
336        write!(f, "k#{s}..")
337    }
338}
339
340impl Display for ConciseAuthorityPublicKeyBytes {
341    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
342        Debug::fmt(self, f)
343    }
344}
345
346impl TryFrom<AuthorityPublicKeyBytes> for AuthorityPublicKey {
347    type Error = FastCryptoError;
348
349    fn try_from(bytes: AuthorityPublicKeyBytes) -> Result<AuthorityPublicKey, Self::Error> {
350        AuthorityPublicKey::from_bytes(bytes.as_ref())
351    }
352}
353
354impl From<&AuthorityPublicKey> for AuthorityPublicKeyBytes {
355    fn from(pk: &AuthorityPublicKey) -> AuthorityPublicKeyBytes {
356        AuthorityPublicKeyBytes::from_bytes(pk.as_ref()).unwrap()
357    }
358}
359
360impl Debug for AuthorityPublicKeyBytes {
361    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
362        self.fmt_impl(f)
363    }
364}
365
366impl Display for AuthorityPublicKeyBytes {
367    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
368        self.fmt_impl(f)
369    }
370}
371
372impl ToFromBytes for AuthorityPublicKeyBytes {
373    fn from_bytes(bytes: &[u8]) -> Result<Self, fastcrypto::error::FastCryptoError> {
374        let bytes: [u8; AuthorityPublicKey::LENGTH] = bytes
375            .try_into()
376            .map_err(|_| fastcrypto::error::FastCryptoError::InvalidInput)?;
377        Ok(AuthorityPublicKeyBytes(bytes))
378    }
379}
380
381impl AuthorityPublicKeyBytes {
382    pub const ZERO: Self = Self::new([0u8; AuthorityPublicKey::LENGTH]);
383
384    /// This ensures it's impossible to construct an instance with other than
385    /// registered lengths
386    pub const fn new(bytes: [u8; AuthorityPublicKey::LENGTH]) -> AuthorityPublicKeyBytes
387where {
388        AuthorityPublicKeyBytes(bytes)
389    }
390}
391
392impl FromStr for AuthorityPublicKeyBytes {
393    type Err = Error;
394
395    fn from_str(s: &str) -> Result<Self, Self::Err> {
396        let value = Hex::decode(s).map_err(|e| anyhow!(e))?;
397        Self::from_bytes(&value[..]).map_err(|e| anyhow!(e))
398    }
399}
400
401impl Default for AuthorityPublicKeyBytes {
402    fn default() -> Self {
403        Self::ZERO
404    }
405}
406
407// Add helper calls for Authority Signature
408//
409
410pub trait IotaAuthoritySignature {
411    fn verify_secure<T>(
412        &self,
413        value: &IntentMessage<T>,
414        epoch_id: EpochId,
415        author: AuthorityPublicKeyBytes,
416    ) -> Result<(), IotaError>
417    where
418        T: Serialize;
419
420    fn new_secure<T>(
421        value: &IntentMessage<T>,
422        epoch_id: &EpochId,
423        secret: &dyn Signer<Self>,
424    ) -> Self
425    where
426        T: Serialize;
427}
428
429impl IotaAuthoritySignature for AuthoritySignature {
430    #[instrument(level = "trace", skip_all)]
431    fn new_secure<T>(value: &IntentMessage<T>, epoch: &EpochId, secret: &dyn Signer<Self>) -> Self
432    where
433        T: Serialize,
434    {
435        let mut intent_msg_bytes =
436            bcs::to_bytes(&value).expect("Message serialization should not fail");
437        epoch.write(&mut intent_msg_bytes);
438        secret.sign(&intent_msg_bytes)
439    }
440
441    #[instrument(level = "trace", skip_all)]
442    fn verify_secure<T>(
443        &self,
444        value: &IntentMessage<T>,
445        epoch: EpochId,
446        author: AuthorityPublicKeyBytes,
447    ) -> Result<(), IotaError>
448    where
449        T: Serialize,
450    {
451        let mut message = bcs::to_bytes(&value).expect("Message serialization should not fail");
452        epoch.write(&mut message);
453
454        let public_key = AuthorityPublicKey::try_from(author).map_err(|_| {
455            IotaError::KeyConversion(
456                "Failed to serialize public key bytes to valid public key".to_string(),
457            )
458        })?;
459        public_key
460            .verify(&message[..], self)
461            .map_err(|e| IotaError::InvalidSignature {
462                error: format!(
463                    "Fail to verify auth sig {} epoch: {} author: {}",
464                    e,
465                    epoch,
466                    author.concise()
467                ),
468            })
469    }
470}
471
472/// Random key-pair generation for the `get_key_pair` helpers, implemented for
473/// the fastcrypto authority/network keypairs and the SDK account keys.
474pub trait RandomKeyPair: Sized {
475    fn generate_with_address(rng: &mut StdRng) -> (Address, Self);
476}
477
478impl RandomKeyPair for BLS12381KeyPair {
479    fn generate_with_address(rng: &mut StdRng) -> (Address, Self) {
480        let kp = <BLS12381KeyPair as KeypairTraits>::generate(rng);
481        // Authority keys have no on-chain account; this address only labels
482        // key files and `keytool` output.
483        let mut hasher = DefaultHash::default();
484        hasher.update([SignatureScheme::Bls12381.to_u8()]);
485        hasher.update(kp.public().as_ref());
486        (Address::new(hasher.finalize().digest), kp)
487    }
488}
489
490impl RandomKeyPair for Ed25519KeyPair {
491    fn generate_with_address(rng: &mut StdRng) -> (Address, Self) {
492        let kp = <Ed25519KeyPair as KeypairTraits>::generate(rng);
493        let public = PublicKey::Ed25519(BytesRepresentation(
494            kp.public()
495                .as_ref()
496                .try_into()
497                .expect("ed25519 public keys are 32 bytes"),
498        ));
499        (Address::from(&public), kp)
500    }
501}
502
503macro_rules! random_key_pair_from_sdk {
504    ($private_key:ty, $variant:ident) => {
505        impl RandomKeyPair for $private_key {
506            fn generate_with_address(rng: &mut StdRng) -> (Address, Self) {
507                let kp = <$private_key>::random_with(rng);
508                let public = PublicKey::$variant(BytesRepresentation(kp.public_key().into_inner()));
509                (Address::from(&public), kp)
510            }
511        }
512    };
513}
514
515random_key_pair_from_sdk!(Ed25519PrivateKey, Ed25519);
516random_key_pair_from_sdk!(Secp256k1PrivateKey, Secp256k1);
517random_key_pair_from_sdk!(Secp256r1PrivateKey, Secp256r1);
518
519// TODO: get_key_pair() should return KeyPair only.
520// TODO: rename to random_key_pair
521pub fn get_key_pair<KP: RandomKeyPair>() -> (Address, KP) {
522    get_key_pair_from_rng(&mut OsRng)
523}
524
525/// Generate a random committee key pairs with a given committee size
526pub fn random_committee_key_pairs_of_size(size: usize) -> Vec<AuthorityKeyPair> {
527    let mut rng = StdRng::from_seed([0; 32]);
528    (0..size)
529        .map(|_| {
530            // TODO: We are generating the keys 4 times to match exactly as how we generate
531            // keys in ConfigBuilder::build (iota-config/src/network_config_builder). This
532            // is because we are using these key generation functions as
533            // fixtures and we call them independently in different paths and
534            // exact the results to be the same. We should eliminate them.
535            let key_pair = get_key_pair_from_rng::<AuthorityKeyPair, _>(&mut rng);
536            get_key_pair_from_rng::<AuthorityKeyPair, _>(&mut rng);
537            get_key_pair_from_rng::<AccountKeyPair, _>(&mut rng);
538            get_key_pair_from_rng::<AccountKeyPair, _>(&mut rng);
539            key_pair.1
540        })
541        .collect()
542}
543
544pub fn deterministic_random_account_key() -> (Address, AccountKeyPair) {
545    let mut rng = StdRng::from_seed([0; 32]);
546    get_key_pair_from_rng(&mut rng)
547}
548
549pub fn get_account_key_pair() -> (Address, AccountKeyPair) {
550    get_key_pair()
551}
552
553pub fn get_authority_key_pair() -> (Address, AuthorityKeyPair) {
554    get_key_pair()
555}
556
557/// Generate a keypair from the specified RNG (useful for testing with seedable
558/// rngs).
559pub fn get_key_pair_from_rng<KP: RandomKeyPair, R>(csprng: &mut R) -> (Address, KP)
560where
561    R: rand::CryptoRng + rand::RngCore,
562{
563    KP::generate_with_address(&mut StdRng::from_rng(csprng).unwrap())
564}
565
566// TODO: C-GETTER
567pub fn get_key_pair_from_bytes<KP: KeypairTraits>(bytes: &[u8]) -> IotaResult<KP> {
568    let priv_length = <KP as KeypairTraits>::PrivKey::LENGTH;
569    let pub_key_length = <KP as KeypairTraits>::PubKey::LENGTH;
570    if bytes.len() != priv_length + pub_key_length {
571        return Err(IotaError::KeyConversion(format!(
572            "Invalid input byte length, expected {}: {}",
573            priv_length + pub_key_length,
574            bytes.len()
575        )));
576    }
577    let sk = <KP as KeypairTraits>::PrivKey::from_bytes(
578        bytes
579            .get(..priv_length)
580            .ok_or(IotaError::InvalidPrivateKey)?,
581    )
582    .map_err(|_| IotaError::InvalidPrivateKey)?;
583    Ok(sk.into())
584}
585
586/// An all-zero ed25519 [`SimpleSignature`] placeholder, used for system
587/// transactions (which are not signed) and in tests where the signature
588/// content is irrelevant.
589pub fn zero_ed25519_signature() -> SimpleSignature {
590    // `flag || signature || public key`, all zero; the leading zero byte selects
591    // the ed25519 scheme.
592    SimpleSignature::from_bytes([0u8; 1 + Ed25519Signature::LENGTH + Ed25519PublicKey::LENGTH])
593        .expect("zero-filled ed25519 signature has the expected length")
594}
595
596// BLS Port
597//
598
599impl IotaPublicKey for BLS12381PublicKey {
600    const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::Bls12381;
601}
602
603impl IotaPublicKey for Ed25519PublicKey {
604    const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::Ed25519;
605}
606
607impl IotaPublicKey for Secp256k1PublicKey {
608    const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::Secp256k1;
609}
610
611impl IotaPublicKey for Secp256r1PublicKey {
612    const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::Secp256r1;
613}
614
615pub trait IotaPublicKey: VerifyingKey {
616    const SIGNATURE_SCHEME: SignatureScheme;
617}
618
619/// AuthoritySignInfoTrait is a trait used specifically for a few structs in
620/// messages.rs to template on whether the struct is signed by an authority. We
621/// want to limit how those structs can be instantiated on, hence the sealed
622/// trait. TODO: We could also add the aggregated signature as another impl of
623/// the trait.       This will make CertifiedTransaction also an instance of the
624/// same struct.
625pub trait AuthoritySignInfoTrait: private::SealedAuthoritySignInfoTrait {
626    fn verify_secure<T: Serialize>(
627        &self,
628        data: &T,
629        intent: Intent,
630        committee: &Committee,
631    ) -> IotaResult;
632
633    fn add_to_verification_obligation<'a>(
634        &self,
635        committee: &'a Committee,
636        obligation: &mut VerificationObligation<'a>,
637        message_index: usize,
638    ) -> IotaResult<()>;
639}
640
641#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
642pub struct EmptySignInfo {}
643impl AuthoritySignInfoTrait for EmptySignInfo {
644    fn verify_secure<T: Serialize>(
645        &self,
646        _data: &T,
647        _intent: Intent,
648        _committee: &Committee,
649    ) -> IotaResult {
650        Ok(())
651    }
652
653    fn add_to_verification_obligation<'a>(
654        &self,
655        _committee: &'a Committee,
656        _obligation: &mut VerificationObligation<'a>,
657        _message_index: usize,
658    ) -> IotaResult<()> {
659        Ok(())
660    }
661}
662
663#[derive(Clone, Debug, Eq, Serialize, Deserialize)]
664pub struct AuthoritySignInfo {
665    pub epoch: EpochId,
666    pub authority: AuthorityName,
667    pub signature: AuthoritySignature,
668}
669
670impl AuthoritySignInfoTrait for AuthoritySignInfo {
671    #[instrument(level = "trace", skip_all)]
672    fn verify_secure<T: Serialize>(
673        &self,
674        data: &T,
675        intent: Intent,
676        committee: &Committee,
677    ) -> IotaResult<()> {
678        let mut obligation = VerificationObligation::default();
679        let idx = obligation.add_message(data, self.epoch, intent);
680        self.add_to_verification_obligation(committee, &mut obligation, idx)?;
681        obligation.verify_all()?;
682        Ok(())
683    }
684
685    fn add_to_verification_obligation<'a>(
686        &self,
687        committee: &'a Committee,
688        obligation: &mut VerificationObligation<'a>,
689        message_index: usize,
690    ) -> IotaResult<()> {
691        fp_ensure!(
692            self.epoch == committee.epoch(),
693            IotaError::WrongEpoch {
694                expected_epoch: committee.epoch(),
695                actual_epoch: self.epoch,
696            }
697        );
698        let weight = committee.weight(&self.authority);
699        fp_ensure!(
700            weight > 0,
701            IotaError::UnknownSigner {
702                signer: Some(self.authority.concise().to_string()),
703                index: None,
704                committee: Box::new(committee.clone())
705            }
706        );
707
708        obligation
709            .public_keys
710            .get_mut(message_index)
711            .ok_or(IotaError::InvalidAddress)?
712            .push(committee.public_key(&self.authority)?);
713        obligation
714            .signatures
715            .get_mut(message_index)
716            .ok_or(IotaError::InvalidAddress)?
717            .add_signature(self.signature.clone())
718            .map_err(|_| IotaError::InvalidSignature {
719                error: "Fail to aggregator auth sig".to_string(),
720            })?;
721        Ok(())
722    }
723}
724
725impl AuthoritySignInfo {
726    pub fn new<T>(
727        epoch: EpochId,
728        value: &T,
729        intent: Intent,
730        name: AuthorityName,
731        secret: &dyn Signer<AuthoritySignature>,
732    ) -> Self
733    where
734        T: Serialize,
735    {
736        Self {
737            epoch,
738            authority: name,
739            signature: AuthoritySignature::new_secure(
740                &IntentMessage::new(intent, value),
741                &epoch,
742                secret,
743            ),
744        }
745    }
746}
747
748impl Hash for AuthoritySignInfo {
749    fn hash<H: Hasher>(&self, state: &mut H) {
750        self.epoch.hash(state);
751        self.authority.hash(state);
752    }
753}
754
755impl Display for AuthoritySignInfo {
756    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
757        write!(
758            f,
759            "AuthoritySignInfo {{ epoch: {:?}, authority: {} }}",
760            self.epoch, self.authority,
761        )
762    }
763}
764
765impl PartialEq for AuthoritySignInfo {
766    fn eq(&self, other: &Self) -> bool {
767        // We do not compare the signature, because there can be multiple
768        // valid signatures for the same epoch and authority.
769        self.epoch == other.epoch && self.authority == other.authority
770    }
771}
772
773/// Represents at least a quorum (could be more) of authority signatures.
774/// STRONG_THRESHOLD indicates whether to use the quorum threshold for quorum
775/// check. When STRONG_THRESHOLD is true, the quorum is valid when the total
776/// stake is at least the quorum threshold (2f+1) of the committee; when
777/// STRONG_THRESHOLD is false, the quorum is valid when the total stake is at
778/// least the validity threshold (f+1) of the committee.
779#[serde_as]
780#[derive(Clone, Debug, Serialize, Deserialize)]
781pub struct AuthorityQuorumSignInfo<const STRONG_THRESHOLD: bool> {
782    pub epoch: EpochId,
783    pub signature: AggregateAuthoritySignature,
784    #[serde_as(as = "IotaBitmap")]
785    pub signers_map: RoaringBitmap,
786}
787
788pub type AuthorityStrongQuorumSignInfo = AuthorityQuorumSignInfo<true>;
789
790// Variant of [AuthorityStrongQuorumSignInfo] but with a serialized signature,
791// to be used in external APIs.
792#[serde_as]
793#[derive(Clone, Debug, Serialize, Deserialize)]
794pub struct IotaAuthorityStrongQuorumSignInfo {
795    pub epoch: EpochId,
796    pub signature: AggregateAuthoritySignatureAsBytes,
797    #[serde_as(as = "IotaBitmap")]
798    pub signers_map: RoaringBitmap,
799}
800
801impl From<&AuthorityStrongQuorumSignInfo> for IotaAuthorityStrongQuorumSignInfo {
802    fn from(info: &AuthorityStrongQuorumSignInfo) -> Self {
803        Self {
804            epoch: info.epoch,
805            signature: (&info.signature).into(),
806            signers_map: info.signers_map.clone(),
807        }
808    }
809}
810
811impl TryFrom<&IotaAuthorityStrongQuorumSignInfo> for AuthorityStrongQuorumSignInfo {
812    type Error = FastCryptoError;
813
814    fn try_from(info: &IotaAuthorityStrongQuorumSignInfo) -> Result<Self, Self::Error> {
815        Ok(Self {
816            epoch: info.epoch,
817            signature: (&info.signature).try_into()?,
818            signers_map: info.signers_map.clone(),
819        })
820    }
821}
822
823// Note: if you meet an error due to this line it may be because you need an Eq
824// implementation for `CertifiedTransaction`, or one of the structs that include
825// it, i.e. `ConfirmationTransaction`, `TransactionInfoResponse` or
826// `ObjectInfoResponse`.
827//
828// Please note that any such implementation must be agnostic to the exact set of
829// signatures in the certificate, as clients are allowed to equivocate on the
830// exact nature of valid certificates they send to the system. This assertion is
831// a simple tool to make sure certificates are accounted for correctly - should
832// you remove it, you're on your own to maintain the invariant that valid
833// certificates with distinct signatures are equivalent, but yet-unchecked
834// certificates that differ on signers aren't.
835//
836// see also https://github.com/iotaledger/iota/issues/266
837static_assertions::assert_not_impl_any!(AuthorityStrongQuorumSignInfo: Hash, Eq, PartialEq);
838
839impl<const STRONG_THRESHOLD: bool> AuthoritySignInfoTrait
840    for AuthorityQuorumSignInfo<STRONG_THRESHOLD>
841{
842    #[instrument(level = "trace", skip_all)]
843    fn verify_secure<T: Serialize>(
844        &self,
845        data: &T,
846        intent: Intent,
847        committee: &Committee,
848    ) -> IotaResult {
849        let mut obligation = VerificationObligation::default();
850        let idx = obligation.add_message(data, self.epoch, intent);
851        self.add_to_verification_obligation(committee, &mut obligation, idx)?;
852        obligation.verify_all()?;
853        Ok(())
854    }
855
856    fn add_to_verification_obligation<'a>(
857        &self,
858        committee: &'a Committee,
859        obligation: &mut VerificationObligation<'a>,
860        message_index: usize,
861    ) -> IotaResult<()> {
862        // Check epoch
863        fp_ensure!(
864            self.epoch == committee.epoch(),
865            IotaError::WrongEpoch {
866                expected_epoch: committee.epoch(),
867                actual_epoch: self.epoch,
868            }
869        );
870
871        let mut weight = 0;
872
873        // Create obligations for the committee signatures
874        obligation
875            .signatures
876            .get_mut(message_index)
877            .ok_or(IotaError::InvalidAuthenticator)?
878            .add_aggregate(self.signature.clone())
879            .map_err(|_| IotaError::InvalidSignature {
880                error: "Signature Aggregation failed".to_string(),
881            })?;
882
883        let selected_public_keys = obligation
884            .public_keys
885            .get_mut(message_index)
886            .ok_or(IotaError::InvalidAuthenticator)?;
887
888        for authority_index in self.signers_map.iter() {
889            let authority = committee
890                .authority_by_index(authority_index)
891                .ok_or_else(|| IotaError::UnknownSigner {
892                    signer: None,
893                    index: Some(authority_index),
894                    committee: Box::new(committee.clone()),
895                })?;
896            let voting_rights = committee.weight(authority);
897            fp_ensure!(
898                voting_rights > 0,
899                IotaError::UnknownSigner {
900                    signer: Some(authority.concise().to_string()),
901                    index: Some(authority_index),
902                    committee: Box::new(committee.clone()),
903                }
904            );
905            weight += voting_rights;
906
907            selected_public_keys.push(committee.public_key(authority)?);
908        }
909
910        fp_ensure!(
911            weight >= Self::quorum_threshold(committee),
912            IotaError::CertificateRequiresQuorum
913        );
914
915        Ok(())
916    }
917}
918
919impl<const STRONG_THRESHOLD: bool> AuthorityQuorumSignInfo<STRONG_THRESHOLD> {
920    pub fn new_from_auth_sign_infos(
921        auth_sign_infos: Vec<AuthoritySignInfo>,
922        committee: &Committee,
923    ) -> IotaResult<Self> {
924        fp_ensure!(
925            auth_sign_infos.iter().all(|a| a.epoch == committee.epoch),
926            IotaError::InvalidSignature {
927                error: "All signatures must be from the same epoch as the committee".to_string()
928            }
929        );
930        let total_stake: StakeUnit = auth_sign_infos
931            .iter()
932            .map(|a| committee.weight(&a.authority))
933            .sum();
934        fp_ensure!(
935            total_stake >= Self::quorum_threshold(committee),
936            IotaError::InvalidSignature {
937                error: "Signatures don't have enough stake to form a quorum".to_string()
938            }
939        );
940
941        let signatures: BTreeMap<_, _> = auth_sign_infos
942            .into_iter()
943            .map(|a| (a.authority, a.signature))
944            .collect();
945        let mut map = RoaringBitmap::new();
946        for pk in signatures.keys() {
947            map.insert(
948                committee
949                    .authority_index(pk)
950                    .ok_or_else(|| IotaError::UnknownSigner {
951                        signer: Some(pk.concise().to_string()),
952                        index: None,
953                        committee: Box::new(committee.clone()),
954                    })?,
955            );
956        }
957        let sigs: Vec<AuthoritySignature> = signatures.into_values().collect();
958
959        Ok(AuthorityQuorumSignInfo {
960            epoch: committee.epoch,
961            signature: AggregateAuthoritySignature::aggregate(&sigs).map_err(|e| {
962                IotaError::InvalidSignature {
963                    error: e.to_string(),
964                }
965            })?,
966            signers_map: map,
967        })
968    }
969
970    pub fn authorities<'a>(
971        &'a self,
972        committee: &'a Committee,
973    ) -> impl Iterator<Item = IotaResult<&'a AuthorityName>> {
974        self.signers_map.iter().map(|i| {
975            committee
976                .authority_by_index(i)
977                .ok_or(IotaError::InvalidAuthenticator)
978        })
979    }
980
981    pub fn quorum_threshold(committee: &Committee) -> StakeUnit {
982        committee.threshold::<STRONG_THRESHOLD>()
983    }
984
985    pub fn len(&self) -> u64 {
986        self.signers_map.len()
987    }
988
989    pub fn is_empty(&self) -> bool {
990        self.signers_map.is_empty()
991    }
992}
993
994impl<const S: bool> Display for AuthorityQuorumSignInfo<S> {
995    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
996        writeln!(
997            f,
998            "{} {{ epoch: {:?}, signers_map: {:?} }}",
999            if S {
1000                "AuthorityStrongQuorumSignInfo"
1001            } else {
1002                "AuthorityWeakQuorumSignInfo"
1003            },
1004            self.epoch,
1005            self.signers_map,
1006        )?;
1007        Ok(())
1008    }
1009}
1010
1011mod private {
1012    pub trait SealedAuthoritySignInfoTrait {}
1013    impl SealedAuthoritySignInfoTrait for super::EmptySignInfo {}
1014    impl SealedAuthoritySignInfoTrait for super::AuthoritySignInfo {}
1015    impl<const S: bool> SealedAuthoritySignInfoTrait for super::AuthorityQuorumSignInfo<S> {}
1016}
1017
1018/// Something that we know how to hash and sign.
1019pub trait Signable<W> {
1020    fn write(&self, writer: &mut W);
1021}
1022
1023/// Activate the blanket implementation of `Signable` based on serde and BCS.
1024/// * We use `serde_name` to extract a seed from the name of structs and enums.
1025/// * We use `BCS` to generate canonical bytes suitable for hashing and signing.
1026///
1027/// # Safety
1028/// We protect the access to this marker trait through a "sealed trait" pattern:
1029/// impls must be add added here (nowehre else) which lets us note those impls
1030/// MUST be on types that comply with the `serde_name` machinery
1031/// for the below implementations not to panic. One way to check they work is to
1032/// write a unit test for serialization to / deserialization from signable
1033/// bytes.
1034mod bcs_signable {
1035
1036    pub trait BcsSignable: serde::Serialize + serde::de::DeserializeOwned {}
1037    impl BcsSignable for crate::committee::Committee {}
1038    impl BcsSignable for iota_sdk_types::checkpoint::CheckpointSummary {}
1039    impl BcsSignable for iota_sdk_types::checkpoint::CheckpointContents {}
1040    #[cfg(not(target_arch = "wasm32"))]
1041    impl BcsSignable for crate::messages_consensus::VersionedMisbehaviorReport {}
1042
1043    impl BcsSignable for iota_sdk_types::TransactionEffects {}
1044    impl BcsSignable for iota_sdk_types::TransactionEvents {}
1045    impl BcsSignable for iota_sdk_types::Transaction {}
1046    impl BcsSignable for iota_sdk_types::SenderSignedTransaction {}
1047    impl BcsSignable for crate::object::ObjectInner {}
1048
1049    impl BcsSignable for crate::global_state_hash::GlobalStateHash {}
1050
1051    impl BcsSignable for super::bcs_signable_test::Foo {}
1052    #[cfg(test)]
1053    impl BcsSignable for super::bcs_signable_test::Bar {}
1054}
1055
1056impl<T, W> Signable<W> for T
1057where
1058    T: bcs_signable::BcsSignable,
1059    W: std::io::Write,
1060{
1061    fn write(&self, writer: &mut W) {
1062        let name = serde_name::trace_name::<Self>().expect("Self must be a struct or an enum");
1063        // Note: This assumes that names never contain the separator `::`.
1064        write!(writer, "{name}::").expect("Hasher should not fail");
1065        bcs::serialize_into(writer, &self).expect("Message serialization should not fail");
1066    }
1067}
1068
1069impl<W> Signable<W> for EpochId
1070where
1071    W: std::io::Write,
1072{
1073    fn write(&self, writer: &mut W) {
1074        bcs::serialize_into(writer, &self).expect("Message serialization should not fail");
1075    }
1076}
1077
1078fn hash<S: Signable<H>, H: HashFunction<DIGEST_SIZE>, const DIGEST_SIZE: usize>(
1079    signable: &S,
1080) -> [u8; DIGEST_SIZE] {
1081    let mut digest = H::default();
1082    signable.write(&mut digest);
1083    let hash = digest.finalize();
1084    hash.into()
1085}
1086
1087pub fn default_hash<S: Signable<DefaultHash>>(signable: &S) -> [u8; 32] {
1088    hash::<S, DefaultHash, 32>(signable)
1089}
1090
1091#[derive(Default)]
1092pub struct VerificationObligation<'a> {
1093    pub messages: Vec<Vec<u8>>,
1094    pub signatures: Vec<AggregateAuthoritySignature>,
1095    pub public_keys: Vec<Vec<&'a AuthorityPublicKey>>,
1096}
1097
1098impl<'a> VerificationObligation<'a> {
1099    pub fn new() -> VerificationObligation<'a> {
1100        VerificationObligation::default()
1101    }
1102
1103    /// Add a new message to the list of messages to be verified.
1104    /// Returns the index of the message.
1105    pub fn add_message<T>(&mut self, message_value: &T, epoch: EpochId, intent: Intent) -> usize
1106    where
1107        T: Serialize,
1108    {
1109        let intent_msg = IntentMessage::new(intent, message_value);
1110        let mut intent_msg_bytes =
1111            bcs::to_bytes(&intent_msg).expect("Message serialization should not fail");
1112        epoch.write(&mut intent_msg_bytes);
1113        self.signatures.push(AggregateAuthoritySignature::default());
1114        self.public_keys.push(Vec::new());
1115        self.messages.push(intent_msg_bytes);
1116        self.messages.len() - 1
1117    }
1118
1119    // Attempts to add signature and public key to the obligation. If this fails,
1120    // ensure to call `verify` manually.
1121    pub fn add_signature_and_public_key(
1122        &mut self,
1123        signature: &AuthoritySignature,
1124        public_key: &'a AuthorityPublicKey,
1125        idx: usize,
1126    ) -> IotaResult<()> {
1127        self.public_keys
1128            .get_mut(idx)
1129            .ok_or(IotaError::InvalidAuthenticator)?
1130            .push(public_key);
1131        self.signatures
1132            .get_mut(idx)
1133            .ok_or(IotaError::InvalidAuthenticator)?
1134            .add_signature(signature.clone())
1135            .map_err(|_| IotaError::InvalidSignature {
1136                error: "Failed to add signature to obligation".to_string(),
1137            })?;
1138        Ok(())
1139    }
1140
1141    #[instrument(level = "trace", skip_all)]
1142    pub fn verify_all(self) -> IotaResult<()> {
1143        let mut pks = Vec::with_capacity(self.public_keys.len());
1144        for pk in self.public_keys.clone() {
1145            pks.push(pk.into_iter());
1146        }
1147        AggregateAuthoritySignature::batch_verify(
1148            &self.signatures.iter().collect::<Vec<_>>()[..],
1149            pks,
1150            &self.messages.iter().map(|x| &x[..]).collect::<Vec<_>>()[..],
1151        )
1152        .map_err(|e| {
1153            let message = format!(
1154                "pks: {:?}, messages: {:?}, sigs: {:?}",
1155                self.public_keys,
1156                self.messages
1157                    .iter()
1158                    .map(Base64::encode)
1159                    .collect::<Vec<String>>(),
1160                self.signatures
1161                    .iter()
1162                    .map(|s| Base64::encode(s.as_ref()))
1163                    .collect::<Vec<String>>()
1164            );
1165
1166            let chunk_size = 2048;
1167
1168            // This error message may be very long, so we print out the error in chunks of
1169            // to avoid hitting a max log line length on the system.
1170            for (i, chunk) in message
1171                .as_bytes()
1172                .chunks(chunk_size)
1173                .map(std::str::from_utf8)
1174                .enumerate()
1175            {
1176                warn!(
1177                    "Failed to batch verify aggregated auth sig: {} (chunk {}): {}",
1178                    e,
1179                    i,
1180                    chunk.unwrap()
1181                );
1182            }
1183
1184            IotaError::InvalidSignature {
1185                error: format!("Failed to batch verify aggregated auth sig: {e}"),
1186            }
1187        })?;
1188        Ok(())
1189    }
1190}
1191
1192pub mod bcs_signable_test {
1193    use serde::{Deserialize, Serialize};
1194
1195    #[derive(Clone, Serialize, Deserialize)]
1196    pub struct Foo(pub String);
1197
1198    #[cfg(test)]
1199    #[derive(Serialize, Deserialize)]
1200    pub struct Bar(pub String);
1201
1202    #[cfg(test)]
1203    use super::VerificationObligation;
1204
1205    #[cfg(test)]
1206    pub fn get_obligation_input<T>(value: &T) -> (VerificationObligation<'_>, usize)
1207    where
1208        T: super::bcs_signable::BcsSignable,
1209    {
1210        use iota_sdk_types::crypto::{Intent, IntentScope};
1211
1212        let mut obligation = VerificationObligation::default();
1213        // Add the obligation of the authority signature verifications.
1214        let idx = obligation.add_message(
1215            value,
1216            0,
1217            Intent::iota_app(IntentScope::SenderSignedTransaction),
1218        );
1219        (obligation, idx)
1220    }
1221}
1222
1223impl FromStr for PublicKey {
1224    type Err = eyre::Report;
1225    fn from_str(s: &str) -> Result<Self, Self::Err> {
1226        Self::decode_base64(s).map_err(|e| eyre!("Fail to decode base64 {}", e.to_string()))
1227    }
1228}
1229
1230// Types for randomness generation
1231//
1232#[cfg(not(target_arch = "wasm32"))]
1233pub type RandomnessSignature = fastcrypto_tbls::types::Signature;
1234#[cfg(not(target_arch = "wasm32"))]
1235pub type RandomnessPartialSignature = fastcrypto_tbls::tbls::PartialSignature<RandomnessSignature>;
1236#[cfg(not(target_arch = "wasm32"))]
1237pub type RandomnessPrivateKey =
1238    fastcrypto_tbls::ecies_v1::PrivateKey<fastcrypto::groups::bls12381::G2Element>;