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