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