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