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