1use std::{
8 collections::BTreeMap,
9 fmt::{Debug, Display, Formatter},
10 hash::{Hash, Hasher},
11 str::FromStr,
12};
13
14use anyhow::{Error, anyhow};
15use derive_more::{AsRef, From};
16pub use enum_dispatch::enum_dispatch;
17use eyre::eyre;
18pub use fastcrypto::traits::{
19 AggregateAuthenticator, Authenticator, EncodeDecodeBase64, KeyPair as KeypairTraits, Signer,
20 SigningKey, ToFromBytes, VerifyingKey,
21};
22use fastcrypto::{
23 bls12381::min_sig::{
24 BLS12381AggregateSignature, BLS12381AggregateSignatureAsBytes, BLS12381KeyPair,
25 BLS12381PrivateKey, BLS12381PublicKey, BLS12381Signature,
26 },
27 ed25519::{
28 Ed25519KeyPair, Ed25519PrivateKey, Ed25519PublicKey, Ed25519PublicKeyAsBytes,
29 Ed25519Signature,
30 },
31 encoding::{Base64, Bech32, Encoding, Hex},
32 error::{FastCryptoError, FastCryptoResult},
33 hash::{Blake2b256, HashFunction},
34 secp256k1::{
35 Secp256k1KeyPair, Secp256k1PublicKey, Secp256k1PublicKeyAsBytes, Secp256k1Signature,
36 },
37 secp256r1::{
38 Secp256r1KeyPair, Secp256r1PublicKey, Secp256r1PublicKeyAsBytes, Secp256r1Signature,
39 },
40};
41use iota_sdk_crypto::{Verifier, simple::SimpleVerifier};
42use iota_sdk_types::{
43 Address, SignatureScheme,
44 crypto::{Intent, IntentMessage, IntentScope},
45};
46use rand::{
47 SeedableRng,
48 rngs::{OsRng, StdRng},
49};
50use roaring::RoaringBitmap;
51use serde::{Deserialize, Deserializer, Serialize, ser::Serializer};
52use serde_with::{Bytes, serde_as};
53use tracing::{instrument, warn};
54
55use crate::{
56 base_types::{AuthorityName, ConciseableName, address_from_iota_pub_key},
57 committee::{Committee, CommitteeTrait, EpochId, StakeUnit},
58 error::{IotaError, IotaResult},
59 iota_serde::{IotaBitmap, Readable},
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: Address,
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: Address,
133) -> Result<(), IotaError> {
134 authority_pubkey
135 .validate()
136 .map_err(|_| IotaError::InvalidSignature {
137 error: "Fail to validate pubkey".to_string(),
138 })?;
139 let mut msg = authority_pubkey.as_bytes().to_vec();
140 msg.extend_from_slice(iota_address.as_ref());
141 pop.verify_secure(
142 &IntentMessage::new(Intent::iota_app(IntentScope::ProofOfPossession), msg),
143 DEFAULT_EPOCH_ID,
144 authority_pubkey.into(),
145 )
146}
147
148#[expect(clippy::large_enum_variant)]
155#[derive(Debug, From, PartialEq, Eq)]
156pub enum IotaKeyPair {
157 Ed25519(Ed25519KeyPair),
158 Secp256k1(Secp256k1KeyPair),
159 Secp256r1(Secp256r1KeyPair),
160}
161
162impl IotaKeyPair {
163 pub fn public(&self) -> PublicKey {
164 match self {
165 IotaKeyPair::Ed25519(kp) => PublicKey::Ed25519(kp.public().into()),
166 IotaKeyPair::Secp256k1(kp) => PublicKey::Secp256k1(kp.public().into()),
167 IotaKeyPair::Secp256r1(kp) => PublicKey::Secp256r1(kp.public().into()),
168 }
169 }
170}
171
172impl Clone for IotaKeyPair {
173 fn clone(&self) -> Self {
174 match self {
175 IotaKeyPair::Ed25519(kp) => kp.copy().into(),
176 IotaKeyPair::Secp256k1(kp) => kp.copy().into(),
177 IotaKeyPair::Secp256r1(kp) => kp.copy().into(),
178 }
179 }
180}
181
182impl Signer<Signature> for IotaKeyPair {
183 fn sign(&self, msg: &[u8]) -> Signature {
184 let mut bytes = vec![self.public().flag()];
187 match self {
188 IotaKeyPair::Ed25519(kp) => {
189 let sig: Ed25519Signature = kp.sign(msg);
190 bytes.extend_from_slice(sig.as_ref());
191 }
192 IotaKeyPair::Secp256k1(kp) => {
193 let sig: Secp256k1Signature = kp.sign(msg);
194 bytes.extend_from_slice(sig.as_ref());
195 }
196 IotaKeyPair::Secp256r1(kp) => {
197 let sig: Secp256r1Signature = kp.sign(msg);
198 bytes.extend_from_slice(sig.as_ref());
199 }
200 }
201 bytes.extend_from_slice(self.public().as_ref());
202 Signature::from_bytes(&bytes).expect("Serialized signature did not have expected size")
203 }
204}
205
206impl From<&Ed25519KeyPair> for IotaKeyPair {
210 fn from(kp: &Ed25519KeyPair) -> Self {
211 IotaKeyPair::Ed25519(kp.copy())
212 }
213}
214
215impl From<&Secp256k1KeyPair> for IotaKeyPair {
216 fn from(kp: &Secp256k1KeyPair) -> Self {
217 IotaKeyPair::Secp256k1(kp.copy())
218 }
219}
220
221impl From<&Secp256r1KeyPair> for IotaKeyPair {
222 fn from(kp: &Secp256r1KeyPair) -> Self {
223 IotaKeyPair::Secp256r1(kp.copy())
224 }
225}
226
227impl From<&IotaKeyPair> for IotaKeyPair {
228 fn from(kp: &IotaKeyPair) -> Self {
229 kp.clone()
230 }
231}
232
233impl EncodeDecodeBase64 for IotaKeyPair {
234 fn encode_base64(&self) -> String {
235 Base64::encode(self.to_bytes())
236 }
237
238 fn decode_base64(value: &str) -> FastCryptoResult<Self> {
239 let bytes = Base64::decode(value)?;
240 Self::from_bytes(&bytes).map_err(|_| FastCryptoError::InvalidInput)
241 }
242}
243
244impl IotaKeyPair {
245 pub fn to_bytes(&self) -> Vec<u8> {
246 let mut bytes: Vec<u8> = Vec::new();
247 bytes.push(self.public().flag());
248
249 match self {
250 IotaKeyPair::Ed25519(kp) => {
251 bytes.extend_from_slice(kp.as_bytes());
252 }
253 IotaKeyPair::Secp256k1(kp) => {
254 bytes.extend_from_slice(kp.as_bytes());
255 }
256 IotaKeyPair::Secp256r1(kp) => {
257 bytes.extend_from_slice(kp.as_bytes());
258 }
259 }
260 bytes
261 }
262
263 pub fn from_bytes(bytes: &[u8]) -> Result<Self, eyre::Report> {
264 let (flag, key_bytes) = bytes.split_first().ok_or_else(|| eyre!("Invalid length"))?;
265 match SignatureScheme::from_byte(*flag) {
266 Ok(SignatureScheme::Ed25519) => {
267 Ok(IotaKeyPair::Ed25519(Ed25519KeyPair::from_bytes(key_bytes)?))
268 }
269 Ok(SignatureScheme::Secp256k1) => Ok(IotaKeyPair::Secp256k1(
270 Secp256k1KeyPair::from_bytes(key_bytes)?,
271 )),
272 Ok(SignatureScheme::Secp256r1) => Ok(IotaKeyPair::Secp256r1(
273 Secp256r1KeyPair::from_bytes(key_bytes)?,
274 )),
275 Ok(_) => Err(eyre!("Invalid flag byte")),
276 Err(_) => Err(eyre!("Invalid bytes")),
277 }
278 }
279
280 pub fn to_bytes_no_flag(&self) -> Vec<u8> {
281 match self {
282 IotaKeyPair::Ed25519(kp) => kp.as_bytes().to_vec(),
283 IotaKeyPair::Secp256k1(kp) => kp.as_bytes().to_vec(),
284 IotaKeyPair::Secp256r1(kp) => kp.as_bytes().to_vec(),
285 }
286 }
287
288 pub fn encode(&self) -> Result<String, eyre::Report> {
291 Bech32::encode(self.to_bytes(), IOTA_PRIV_KEY_PREFIX).map_err(|e| eyre!(e))
292 }
293
294 pub fn decode(value: &str) -> Result<Self, eyre::Report> {
298 let bytes = Bech32::decode(value, IOTA_PRIV_KEY_PREFIX)?;
299 Self::from_bytes(&bytes)
300 }
301}
302
303impl Serialize for IotaKeyPair {
304 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
305 where
306 S: Serializer,
307 {
308 let s = self.encode_base64();
309 serializer.serialize_str(&s)
310 }
311}
312
313impl<'de> Deserialize<'de> for IotaKeyPair {
314 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
315 where
316 D: Deserializer<'de>,
317 {
318 use serde::de::Error;
319 let s = String::deserialize(deserializer)?;
320 IotaKeyPair::decode_base64(&s).map_err(|e| Error::custom(e.to_string()))
321 }
322}
323
324#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
325pub enum PublicKey {
326 Ed25519(Ed25519PublicKeyAsBytes),
327 Secp256k1(Secp256k1PublicKeyAsBytes),
328 Secp256r1(Secp256r1PublicKeyAsBytes),
329 Passkey(Secp256r1PublicKeyAsBytes),
330}
331
332impl AsRef<[u8]> for PublicKey {
333 fn as_ref(&self) -> &[u8] {
334 match self {
335 PublicKey::Ed25519(pk) => &pk.0,
336 PublicKey::Secp256k1(pk) => &pk.0,
337 PublicKey::Secp256r1(pk) => &pk.0,
338 PublicKey::Passkey(pk) => &pk.0,
339 }
340 }
341}
342
343impl EncodeDecodeBase64 for PublicKey {
344 fn encode_base64(&self) -> String {
345 let mut bytes: Vec<u8> = Vec::new();
346 bytes.extend_from_slice(&[self.flag()]);
347 bytes.extend_from_slice(self.as_ref());
348 Base64::encode(&bytes[..])
349 }
350
351 fn decode_base64(value: &str) -> FastCryptoResult<Self> {
352 let bytes = Base64::decode(value)?;
353 match bytes.first() {
354 Some(x) => {
355 if x == &SignatureScheme::Ed25519.to_u8() {
356 let pk: Ed25519PublicKey =
357 Ed25519PublicKey::from_bytes(bytes.get(1..).ok_or(
358 FastCryptoError::InputLengthWrong(Ed25519PublicKey::LENGTH + 1),
359 )?)?;
360 Ok(PublicKey::Ed25519((&pk).into()))
361 } else if x == &SignatureScheme::Secp256k1.to_u8() {
362 let pk = Secp256k1PublicKey::from_bytes(bytes.get(1..).ok_or(
363 FastCryptoError::InputLengthWrong(Secp256k1PublicKey::LENGTH + 1),
364 )?)?;
365 Ok(PublicKey::Secp256k1((&pk).into()))
366 } else if x == &SignatureScheme::Secp256r1.to_u8() {
367 let pk = Secp256r1PublicKey::from_bytes(bytes.get(1..).ok_or(
368 FastCryptoError::InputLengthWrong(Secp256r1PublicKey::LENGTH + 1),
369 )?)?;
370 Ok(PublicKey::Secp256r1((&pk).into()))
371 } else if x == &SignatureScheme::PasskeyAuthenticator.to_u8() {
372 let pk = Secp256r1PublicKey::from_bytes(bytes.get(1..).ok_or(
373 FastCryptoError::InputLengthWrong(Secp256r1PublicKey::LENGTH + 1),
374 )?)?;
375 Ok(PublicKey::Passkey((&pk).into()))
376 } else {
377 Err(FastCryptoError::InvalidInput)
378 }
379 }
380 _ => Err(FastCryptoError::InvalidInput),
381 }
382 }
383}
384
385impl PublicKey {
386 pub fn flag(&self) -> u8 {
387 self.scheme().to_u8()
388 }
389
390 pub fn try_from_bytes(
391 curve: SignatureScheme,
392 key_bytes: &[u8],
393 ) -> Result<PublicKey, eyre::Report> {
394 match curve {
395 SignatureScheme::Ed25519 => Ok(PublicKey::Ed25519(
396 (&Ed25519PublicKey::from_bytes(key_bytes)?).into(),
397 )),
398 SignatureScheme::Secp256k1 => Ok(PublicKey::Secp256k1(
399 (&Secp256k1PublicKey::from_bytes(key_bytes)?).into(),
400 )),
401 SignatureScheme::Secp256r1 => Ok(PublicKey::Secp256r1(
402 (&Secp256r1PublicKey::from_bytes(key_bytes)?).into(),
403 )),
404 SignatureScheme::PasskeyAuthenticator => Ok(PublicKey::Passkey(
405 (&Secp256r1PublicKey::from_bytes(key_bytes)?).into(),
406 )),
407 _ => Err(eyre!("Unsupported curve")),
408 }
409 }
410
411 pub fn scheme(&self) -> SignatureScheme {
412 match self {
413 PublicKey::Ed25519(_) => SignatureScheme::Ed25519,
414 PublicKey::Secp256k1(_) => SignatureScheme::Secp256k1,
415 PublicKey::Secp256r1(_) => SignatureScheme::Secp256r1,
416 PublicKey::Passkey(_) => SignatureScheme::PasskeyAuthenticator,
417 }
418 }
419}
420
421#[serde_as]
424#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, AsRef)]
425#[as_ref(forward)]
426pub struct AuthorityPublicKeyBytes(
427 #[serde_as(as = "Readable<Base64, Bytes>")] pub [u8; AuthorityPublicKey::LENGTH],
428);
429
430impl AuthorityPublicKeyBytes {
431 fn fmt_impl(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
432 let s = Hex::encode(self.0);
433 write!(f, "k#{s}")?;
434 Ok(())
435 }
436}
437
438impl<'a> ConciseableName<'a> for AuthorityPublicKeyBytes {
439 type ConciseTypeRef = ConciseAuthorityPublicKeyBytesRef<'a>;
440 type ConciseType = ConciseAuthorityPublicKeyBytes;
441
442 fn concise(&'a self) -> ConciseAuthorityPublicKeyBytesRef<'a> {
447 ConciseAuthorityPublicKeyBytesRef(self)
448 }
449
450 fn concise_owned(&self) -> ConciseAuthorityPublicKeyBytes {
451 ConciseAuthorityPublicKeyBytes(*self)
452 }
453}
454
455pub struct ConciseAuthorityPublicKeyBytesRef<'a>(&'a AuthorityPublicKeyBytes);
457
458impl Debug for ConciseAuthorityPublicKeyBytesRef<'_> {
459 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
460 let s = Hex::encode(self.0.0.get(0..4).ok_or(std::fmt::Error)?);
461 write!(f, "k#{s}..")
462 }
463}
464
465impl Display for ConciseAuthorityPublicKeyBytesRef<'_> {
466 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
467 Debug::fmt(self, f)
468 }
469}
470
471#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
473pub struct ConciseAuthorityPublicKeyBytes(AuthorityPublicKeyBytes);
474
475impl Debug for ConciseAuthorityPublicKeyBytes {
476 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
477 let s = Hex::encode(self.0.0.get(0..4).ok_or(std::fmt::Error)?);
478 write!(f, "k#{s}..")
479 }
480}
481
482impl Display for ConciseAuthorityPublicKeyBytes {
483 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
484 Debug::fmt(self, f)
485 }
486}
487
488impl TryFrom<AuthorityPublicKeyBytes> for AuthorityPublicKey {
489 type Error = FastCryptoError;
490
491 fn try_from(bytes: AuthorityPublicKeyBytes) -> Result<AuthorityPublicKey, Self::Error> {
492 AuthorityPublicKey::from_bytes(bytes.as_ref())
493 }
494}
495
496impl From<&AuthorityPublicKey> for AuthorityPublicKeyBytes {
497 fn from(pk: &AuthorityPublicKey) -> AuthorityPublicKeyBytes {
498 AuthorityPublicKeyBytes::from_bytes(pk.as_ref()).unwrap()
499 }
500}
501
502impl Debug for AuthorityPublicKeyBytes {
503 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
504 self.fmt_impl(f)
505 }
506}
507
508impl Display for AuthorityPublicKeyBytes {
509 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
510 self.fmt_impl(f)
511 }
512}
513
514impl ToFromBytes for AuthorityPublicKeyBytes {
515 fn from_bytes(bytes: &[u8]) -> Result<Self, fastcrypto::error::FastCryptoError> {
516 let bytes: [u8; AuthorityPublicKey::LENGTH] = bytes
517 .try_into()
518 .map_err(|_| fastcrypto::error::FastCryptoError::InvalidInput)?;
519 Ok(AuthorityPublicKeyBytes(bytes))
520 }
521}
522
523impl AuthorityPublicKeyBytes {
524 pub const ZERO: Self = Self::new([0u8; AuthorityPublicKey::LENGTH]);
525
526 pub const fn new(bytes: [u8; AuthorityPublicKey::LENGTH]) -> AuthorityPublicKeyBytes
529where {
530 AuthorityPublicKeyBytes(bytes)
531 }
532}
533
534impl FromStr for AuthorityPublicKeyBytes {
535 type Err = Error;
536
537 fn from_str(s: &str) -> Result<Self, Self::Err> {
538 let value = Hex::decode(s).map_err(|e| anyhow!(e))?;
539 Self::from_bytes(&value[..]).map_err(|e| anyhow!(e))
540 }
541}
542
543impl Default for AuthorityPublicKeyBytes {
544 fn default() -> Self {
545 Self::ZERO
546 }
547}
548
549pub trait IotaAuthoritySignature {
553 fn verify_secure<T>(
554 &self,
555 value: &IntentMessage<T>,
556 epoch_id: EpochId,
557 author: AuthorityPublicKeyBytes,
558 ) -> Result<(), IotaError>
559 where
560 T: Serialize;
561
562 fn new_secure<T>(
563 value: &IntentMessage<T>,
564 epoch_id: &EpochId,
565 secret: &dyn Signer<Self>,
566 ) -> Self
567 where
568 T: Serialize;
569}
570
571impl IotaAuthoritySignature for AuthoritySignature {
572 #[instrument(level = "trace", skip_all)]
573 fn new_secure<T>(value: &IntentMessage<T>, epoch: &EpochId, secret: &dyn Signer<Self>) -> Self
574 where
575 T: Serialize,
576 {
577 let mut intent_msg_bytes =
578 bcs::to_bytes(&value).expect("Message serialization should not fail");
579 epoch.write(&mut intent_msg_bytes);
580 secret.sign(&intent_msg_bytes)
581 }
582
583 #[instrument(level = "trace", skip_all)]
584 fn verify_secure<T>(
585 &self,
586 value: &IntentMessage<T>,
587 epoch: EpochId,
588 author: AuthorityPublicKeyBytes,
589 ) -> Result<(), IotaError>
590 where
591 T: Serialize,
592 {
593 let mut message = bcs::to_bytes(&value).expect("Message serialization should not fail");
594 epoch.write(&mut message);
595
596 let public_key = AuthorityPublicKey::try_from(author).map_err(|_| {
597 IotaError::KeyConversion(
598 "Failed to serialize public key bytes to valid public key".to_string(),
599 )
600 })?;
601 public_key
602 .verify(&message[..], self)
603 .map_err(|e| IotaError::InvalidSignature {
604 error: format!(
605 "Fail to verify auth sig {} epoch: {} author: {}",
606 e,
607 epoch,
608 author.concise()
609 ),
610 })
611 }
612}
613
614pub fn get_key_pair<KP: KeypairTraits>() -> (Address, KP)
617where
618 <KP as KeypairTraits>::PubKey: IotaPublicKey,
619{
620 get_key_pair_from_rng(&mut OsRng)
621}
622
623pub fn random_committee_key_pairs_of_size(size: usize) -> Vec<AuthorityKeyPair> {
625 let mut rng = StdRng::from_seed([0; 32]);
626 (0..size)
627 .map(|_| {
628 let key_pair = get_key_pair_from_rng::<AuthorityKeyPair, _>(&mut rng);
634 get_key_pair_from_rng::<AuthorityKeyPair, _>(&mut rng);
635 get_key_pair_from_rng::<AccountKeyPair, _>(&mut rng);
636 get_key_pair_from_rng::<AccountKeyPair, _>(&mut rng);
637 key_pair.1
638 })
639 .collect()
640}
641
642pub fn deterministic_random_account_key() -> (Address, AccountKeyPair) {
643 let mut rng = StdRng::from_seed([0; 32]);
644 get_key_pair_from_rng(&mut rng)
645}
646
647pub fn get_account_key_pair() -> (Address, AccountKeyPair) {
648 get_key_pair()
649}
650
651pub fn get_authority_key_pair() -> (Address, AuthorityKeyPair) {
652 get_key_pair()
653}
654
655pub fn get_key_pair_from_rng<KP: KeypairTraits, R>(csprng: &mut R) -> (Address, KP)
658where
659 R: rand::CryptoRng + rand::RngCore,
660 <KP as KeypairTraits>::PubKey: IotaPublicKey,
661{
662 let kp = KP::generate(&mut StdRng::from_rng(csprng).unwrap());
663 (address_from_iota_pub_key(kp.public()), kp)
664}
665
666pub fn get_key_pair_from_bytes<KP: KeypairTraits>(bytes: &[u8]) -> IotaResult<(Address, KP)>
668where
669 <KP as KeypairTraits>::PubKey: IotaPublicKey,
670{
671 let priv_length = <KP as KeypairTraits>::PrivKey::LENGTH;
672 let pub_key_length = <KP as KeypairTraits>::PubKey::LENGTH;
673 if bytes.len() != priv_length + pub_key_length {
674 return Err(IotaError::KeyConversion(format!(
675 "Invalid input byte length, expected {}: {}",
676 priv_length + pub_key_length,
677 bytes.len()
678 )));
679 }
680 let sk = <KP as KeypairTraits>::PrivKey::from_bytes(
681 bytes
682 .get(..priv_length)
683 .ok_or(IotaError::InvalidPrivateKey)?,
684 )
685 .map_err(|_| IotaError::InvalidPrivateKey)?;
686 let kp: KP = sk.into();
687 Ok((address_from_iota_pub_key(kp.public()), kp))
688}
689
690pub use iota_sdk_types::SimpleSignature as Signature;
698
699pub fn zero_ed25519_signature() -> Signature {
703 Signature::from_bytes([0u8; 1 + Ed25519Signature::LENGTH + Ed25519PublicKey::LENGTH])
706 .expect("zero-filled ed25519 signature has the expected length")
707}
708
709impl IotaPublicKey for BLS12381PublicKey {
713 const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::Bls12381;
714}
715
716impl IotaPublicKey for Ed25519PublicKey {
717 const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::Ed25519;
718}
719
720impl IotaPublicKey for Secp256k1PublicKey {
721 const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::Secp256k1;
722}
723
724impl IotaPublicKey for Secp256r1PublicKey {
725 const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::Secp256r1;
726}
727
728pub trait IotaPublicKey: VerifyingKey {
729 const SIGNATURE_SCHEME: SignatureScheme;
730}
731
732pub trait IotaSignature: Sized {
736 fn new_hashed(hashed_msg: &[u8], secret: impl Into<IotaKeyPair>) -> Signature {
738 Signer::sign(&secret.into(), hashed_msg)
739 }
740
741 #[instrument(level = "trace", skip_all)]
743 fn new_secure<T>(value: &IntentMessage<T>, secret: impl Into<IotaKeyPair>) -> Signature
744 where
745 T: Serialize,
746 {
747 let mut hasher = DefaultHash::default();
753 hasher.update(bcs::to_bytes(&value).expect("Message serialization should not fail"));
754
755 Signer::sign(&secret.into(), &hasher.finalize().digest)
756 }
757
758 fn verify_secure<T>(&self, value: &IntentMessage<T>, author: Address) -> IotaResult<()>
759 where
760 T: Serialize;
761}
762
763impl IotaSignature for Signature {
764 #[instrument(level = "trace", skip_all)]
765 fn verify_secure<T>(&self, value: &IntentMessage<T>, author: Address) -> Result<(), IotaError>
766 where
767 T: Serialize,
768 {
769 let mut hasher = DefaultHash::default();
770 hasher.update(bcs::to_bytes(&value).expect("Message serialization should not fail"));
771 let digest = hasher.finalize().digest;
772
773 let address: Address = self.to_public_key().into();
776 if author != address {
777 return Err(IotaError::IncorrectSigner {
778 error: format!("Incorrect signer, expected {author}, got {address}"),
779 });
780 }
781
782 SimpleVerifier
783 .verify(&digest, self)
784 .map_err(|e| IotaError::InvalidSignature {
785 error: format!("Fail to verify user sig {e}"),
786 })
787 }
788}
789
790pub trait AuthoritySignInfoTrait: private::SealedAuthoritySignInfoTrait {
797 fn verify_secure<T: Serialize>(
798 &self,
799 data: &T,
800 intent: Intent,
801 committee: &Committee,
802 ) -> IotaResult;
803
804 fn add_to_verification_obligation<'a>(
805 &self,
806 committee: &'a Committee,
807 obligation: &mut VerificationObligation<'a>,
808 message_index: usize,
809 ) -> IotaResult<()>;
810}
811
812#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
813pub struct EmptySignInfo {}
814impl AuthoritySignInfoTrait for EmptySignInfo {
815 fn verify_secure<T: Serialize>(
816 &self,
817 _data: &T,
818 _intent: Intent,
819 _committee: &Committee,
820 ) -> IotaResult {
821 Ok(())
822 }
823
824 fn add_to_verification_obligation<'a>(
825 &self,
826 _committee: &'a Committee,
827 _obligation: &mut VerificationObligation<'a>,
828 _message_index: usize,
829 ) -> IotaResult<()> {
830 Ok(())
831 }
832}
833
834#[derive(Clone, Debug, Eq, Serialize, Deserialize)]
835pub struct AuthoritySignInfo {
836 pub epoch: EpochId,
837 pub authority: AuthorityName,
838 pub signature: AuthoritySignature,
839}
840
841impl AuthoritySignInfoTrait for AuthoritySignInfo {
842 #[instrument(level = "trace", skip_all)]
843 fn verify_secure<T: Serialize>(
844 &self,
845 data: &T,
846 intent: Intent,
847 committee: &Committee,
848 ) -> IotaResult<()> {
849 let mut obligation = VerificationObligation::default();
850 let idx = obligation.add_message(data, self.epoch, intent);
851 self.add_to_verification_obligation(committee, &mut obligation, idx)?;
852 obligation.verify_all()?;
853 Ok(())
854 }
855
856 fn add_to_verification_obligation<'a>(
857 &self,
858 committee: &'a Committee,
859 obligation: &mut VerificationObligation<'a>,
860 message_index: usize,
861 ) -> IotaResult<()> {
862 fp_ensure!(
863 self.epoch == committee.epoch(),
864 IotaError::WrongEpoch {
865 expected_epoch: committee.epoch(),
866 actual_epoch: self.epoch,
867 }
868 );
869 let weight = committee.weight(&self.authority);
870 fp_ensure!(
871 weight > 0,
872 IotaError::UnknownSigner {
873 signer: Some(self.authority.concise().to_string()),
874 index: None,
875 committee: Box::new(committee.clone())
876 }
877 );
878
879 obligation
880 .public_keys
881 .get_mut(message_index)
882 .ok_or(IotaError::InvalidAddress)?
883 .push(committee.public_key(&self.authority)?);
884 obligation
885 .signatures
886 .get_mut(message_index)
887 .ok_or(IotaError::InvalidAddress)?
888 .add_signature(self.signature.clone())
889 .map_err(|_| IotaError::InvalidSignature {
890 error: "Fail to aggregator auth sig".to_string(),
891 })?;
892 Ok(())
893 }
894}
895
896impl AuthoritySignInfo {
897 pub fn new<T>(
898 epoch: EpochId,
899 value: &T,
900 intent: Intent,
901 name: AuthorityName,
902 secret: &dyn Signer<AuthoritySignature>,
903 ) -> Self
904 where
905 T: Serialize,
906 {
907 Self {
908 epoch,
909 authority: name,
910 signature: AuthoritySignature::new_secure(
911 &IntentMessage::new(intent, value),
912 &epoch,
913 secret,
914 ),
915 }
916 }
917}
918
919impl Hash for AuthoritySignInfo {
920 fn hash<H: Hasher>(&self, state: &mut H) {
921 self.epoch.hash(state);
922 self.authority.hash(state);
923 }
924}
925
926impl Display for AuthoritySignInfo {
927 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
928 write!(
929 f,
930 "AuthoritySignInfo {{ epoch: {:?}, authority: {} }}",
931 self.epoch, self.authority,
932 )
933 }
934}
935
936impl PartialEq for AuthoritySignInfo {
937 fn eq(&self, other: &Self) -> bool {
938 self.epoch == other.epoch && self.authority == other.authority
941 }
942}
943
944#[serde_as]
951#[derive(Clone, Debug, Serialize, Deserialize)]
952pub struct AuthorityQuorumSignInfo<const STRONG_THRESHOLD: bool> {
953 pub epoch: EpochId,
954 pub signature: AggregateAuthoritySignature,
955 #[serde_as(as = "IotaBitmap")]
956 pub signers_map: RoaringBitmap,
957}
958
959pub type AuthorityStrongQuorumSignInfo = AuthorityQuorumSignInfo<true>;
960
961#[serde_as]
964#[derive(Clone, Debug, Serialize, Deserialize)]
965pub struct IotaAuthorityStrongQuorumSignInfo {
966 pub epoch: EpochId,
967 pub signature: AggregateAuthoritySignatureAsBytes,
968 #[serde_as(as = "IotaBitmap")]
969 pub signers_map: RoaringBitmap,
970}
971
972impl From<&AuthorityStrongQuorumSignInfo> for IotaAuthorityStrongQuorumSignInfo {
973 fn from(info: &AuthorityStrongQuorumSignInfo) -> Self {
974 Self {
975 epoch: info.epoch,
976 signature: (&info.signature).into(),
977 signers_map: info.signers_map.clone(),
978 }
979 }
980}
981
982impl TryFrom<&IotaAuthorityStrongQuorumSignInfo> for AuthorityStrongQuorumSignInfo {
983 type Error = FastCryptoError;
984
985 fn try_from(info: &IotaAuthorityStrongQuorumSignInfo) -> Result<Self, Self::Error> {
986 Ok(Self {
987 epoch: info.epoch,
988 signature: (&info.signature).try_into()?,
989 signers_map: info.signers_map.clone(),
990 })
991 }
992}
993
994static_assertions::assert_not_impl_any!(AuthorityStrongQuorumSignInfo: Hash, Eq, PartialEq);
1009
1010impl<const STRONG_THRESHOLD: bool> AuthoritySignInfoTrait
1011 for AuthorityQuorumSignInfo<STRONG_THRESHOLD>
1012{
1013 #[instrument(level = "trace", skip_all)]
1014 fn verify_secure<T: Serialize>(
1015 &self,
1016 data: &T,
1017 intent: Intent,
1018 committee: &Committee,
1019 ) -> IotaResult {
1020 let mut obligation = VerificationObligation::default();
1021 let idx = obligation.add_message(data, self.epoch, intent);
1022 self.add_to_verification_obligation(committee, &mut obligation, idx)?;
1023 obligation.verify_all()?;
1024 Ok(())
1025 }
1026
1027 fn add_to_verification_obligation<'a>(
1028 &self,
1029 committee: &'a Committee,
1030 obligation: &mut VerificationObligation<'a>,
1031 message_index: usize,
1032 ) -> IotaResult<()> {
1033 fp_ensure!(
1035 self.epoch == committee.epoch(),
1036 IotaError::WrongEpoch {
1037 expected_epoch: committee.epoch(),
1038 actual_epoch: self.epoch,
1039 }
1040 );
1041
1042 let mut weight = 0;
1043
1044 obligation
1046 .signatures
1047 .get_mut(message_index)
1048 .ok_or(IotaError::InvalidAuthenticator)?
1049 .add_aggregate(self.signature.clone())
1050 .map_err(|_| IotaError::InvalidSignature {
1051 error: "Signature Aggregation failed".to_string(),
1052 })?;
1053
1054 let selected_public_keys = obligation
1055 .public_keys
1056 .get_mut(message_index)
1057 .ok_or(IotaError::InvalidAuthenticator)?;
1058
1059 for authority_index in self.signers_map.iter() {
1060 let authority = committee
1061 .authority_by_index(authority_index)
1062 .ok_or_else(|| IotaError::UnknownSigner {
1063 signer: None,
1064 index: Some(authority_index),
1065 committee: Box::new(committee.clone()),
1066 })?;
1067 let voting_rights = committee.weight(authority);
1068 fp_ensure!(
1069 voting_rights > 0,
1070 IotaError::UnknownSigner {
1071 signer: Some(authority.concise().to_string()),
1072 index: Some(authority_index),
1073 committee: Box::new(committee.clone()),
1074 }
1075 );
1076 weight += voting_rights;
1077
1078 selected_public_keys.push(committee.public_key(authority)?);
1079 }
1080
1081 fp_ensure!(
1082 weight >= Self::quorum_threshold(committee),
1083 IotaError::CertificateRequiresQuorum
1084 );
1085
1086 Ok(())
1087 }
1088}
1089
1090impl<const STRONG_THRESHOLD: bool> AuthorityQuorumSignInfo<STRONG_THRESHOLD> {
1091 pub fn new_from_auth_sign_infos(
1092 auth_sign_infos: Vec<AuthoritySignInfo>,
1093 committee: &Committee,
1094 ) -> IotaResult<Self> {
1095 fp_ensure!(
1096 auth_sign_infos.iter().all(|a| a.epoch == committee.epoch),
1097 IotaError::InvalidSignature {
1098 error: "All signatures must be from the same epoch as the committee".to_string()
1099 }
1100 );
1101 let total_stake: StakeUnit = auth_sign_infos
1102 .iter()
1103 .map(|a| committee.weight(&a.authority))
1104 .sum();
1105 fp_ensure!(
1106 total_stake >= Self::quorum_threshold(committee),
1107 IotaError::InvalidSignature {
1108 error: "Signatures don't have enough stake to form a quorum".to_string()
1109 }
1110 );
1111
1112 let signatures: BTreeMap<_, _> = auth_sign_infos
1113 .into_iter()
1114 .map(|a| (a.authority, a.signature))
1115 .collect();
1116 let mut map = RoaringBitmap::new();
1117 for pk in signatures.keys() {
1118 map.insert(
1119 committee
1120 .authority_index(pk)
1121 .ok_or_else(|| IotaError::UnknownSigner {
1122 signer: Some(pk.concise().to_string()),
1123 index: None,
1124 committee: Box::new(committee.clone()),
1125 })?,
1126 );
1127 }
1128 let sigs: Vec<AuthoritySignature> = signatures.into_values().collect();
1129
1130 Ok(AuthorityQuorumSignInfo {
1131 epoch: committee.epoch,
1132 signature: AggregateAuthoritySignature::aggregate(&sigs).map_err(|e| {
1133 IotaError::InvalidSignature {
1134 error: e.to_string(),
1135 }
1136 })?,
1137 signers_map: map,
1138 })
1139 }
1140
1141 pub fn authorities<'a>(
1142 &'a self,
1143 committee: &'a Committee,
1144 ) -> impl Iterator<Item = IotaResult<&'a AuthorityName>> {
1145 self.signers_map.iter().map(|i| {
1146 committee
1147 .authority_by_index(i)
1148 .ok_or(IotaError::InvalidAuthenticator)
1149 })
1150 }
1151
1152 pub fn quorum_threshold(committee: &Committee) -> StakeUnit {
1153 committee.threshold::<STRONG_THRESHOLD>()
1154 }
1155
1156 pub fn len(&self) -> u64 {
1157 self.signers_map.len()
1158 }
1159
1160 pub fn is_empty(&self) -> bool {
1161 self.signers_map.is_empty()
1162 }
1163}
1164
1165impl<const S: bool> Display for AuthorityQuorumSignInfo<S> {
1166 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1167 writeln!(
1168 f,
1169 "{} {{ epoch: {:?}, signers_map: {:?} }}",
1170 if S {
1171 "AuthorityStrongQuorumSignInfo"
1172 } else {
1173 "AuthorityWeakQuorumSignInfo"
1174 },
1175 self.epoch,
1176 self.signers_map,
1177 )?;
1178 Ok(())
1179 }
1180}
1181
1182mod private {
1183 pub trait SealedAuthoritySignInfoTrait {}
1184 impl SealedAuthoritySignInfoTrait for super::EmptySignInfo {}
1185 impl SealedAuthoritySignInfoTrait for super::AuthoritySignInfo {}
1186 impl<const S: bool> SealedAuthoritySignInfoTrait for super::AuthorityQuorumSignInfo<S> {}
1187}
1188
1189pub trait Signable<W> {
1191 fn write(&self, writer: &mut W);
1192}
1193
1194mod bcs_signable {
1206
1207 pub trait BcsSignable: serde::Serialize + serde::de::DeserializeOwned {}
1208 impl BcsSignable for crate::committee::Committee {}
1209 impl BcsSignable for iota_sdk_types::checkpoint::CheckpointSummary {}
1210 impl BcsSignable for iota_sdk_types::checkpoint::CheckpointContents {}
1211 #[cfg(not(target_arch = "wasm32"))]
1212 impl BcsSignable for crate::messages_consensus::VersionedMisbehaviorReport {}
1213
1214 impl BcsSignable for crate::effects::TransactionEffects {}
1215 impl BcsSignable for crate::effects::TransactionEvents {}
1216 impl BcsSignable for crate::transaction::TransactionData {}
1217 impl BcsSignable for crate::transaction::SenderSignedData {}
1218 impl BcsSignable for crate::object::ObjectInner {}
1219
1220 impl BcsSignable for crate::global_state_hash::GlobalStateHash {}
1221
1222 impl BcsSignable for super::bcs_signable_test::Foo {}
1223 #[cfg(test)]
1224 impl BcsSignable for super::bcs_signable_test::Bar {}
1225}
1226
1227impl<T, W> Signable<W> for T
1228where
1229 T: bcs_signable::BcsSignable,
1230 W: std::io::Write,
1231{
1232 fn write(&self, writer: &mut W) {
1233 let name = serde_name::trace_name::<Self>().expect("Self must be a struct or an enum");
1234 write!(writer, "{name}::").expect("Hasher should not fail");
1236 bcs::serialize_into(writer, &self).expect("Message serialization should not fail");
1237 }
1238}
1239
1240impl<W> Signable<W> for EpochId
1241where
1242 W: std::io::Write,
1243{
1244 fn write(&self, writer: &mut W) {
1245 bcs::serialize_into(writer, &self).expect("Message serialization should not fail");
1246 }
1247}
1248
1249fn hash<S: Signable<H>, H: HashFunction<DIGEST_SIZE>, const DIGEST_SIZE: usize>(
1250 signable: &S,
1251) -> [u8; DIGEST_SIZE] {
1252 let mut digest = H::default();
1253 signable.write(&mut digest);
1254 let hash = digest.finalize();
1255 hash.into()
1256}
1257
1258pub fn default_hash<S: Signable<DefaultHash>>(signable: &S) -> [u8; 32] {
1259 hash::<S, DefaultHash, 32>(signable)
1260}
1261
1262#[derive(Default)]
1263pub struct VerificationObligation<'a> {
1264 pub messages: Vec<Vec<u8>>,
1265 pub signatures: Vec<AggregateAuthoritySignature>,
1266 pub public_keys: Vec<Vec<&'a AuthorityPublicKey>>,
1267}
1268
1269impl<'a> VerificationObligation<'a> {
1270 pub fn new() -> VerificationObligation<'a> {
1271 VerificationObligation::default()
1272 }
1273
1274 pub fn add_message<T>(&mut self, message_value: &T, epoch: EpochId, intent: Intent) -> usize
1277 where
1278 T: Serialize,
1279 {
1280 let intent_msg = IntentMessage::new(intent, message_value);
1281 let mut intent_msg_bytes =
1282 bcs::to_bytes(&intent_msg).expect("Message serialization should not fail");
1283 epoch.write(&mut intent_msg_bytes);
1284 self.signatures.push(AggregateAuthoritySignature::default());
1285 self.public_keys.push(Vec::new());
1286 self.messages.push(intent_msg_bytes);
1287 self.messages.len() - 1
1288 }
1289
1290 pub fn add_signature_and_public_key(
1293 &mut self,
1294 signature: &AuthoritySignature,
1295 public_key: &'a AuthorityPublicKey,
1296 idx: usize,
1297 ) -> IotaResult<()> {
1298 self.public_keys
1299 .get_mut(idx)
1300 .ok_or(IotaError::InvalidAuthenticator)?
1301 .push(public_key);
1302 self.signatures
1303 .get_mut(idx)
1304 .ok_or(IotaError::InvalidAuthenticator)?
1305 .add_signature(signature.clone())
1306 .map_err(|_| IotaError::InvalidSignature {
1307 error: "Failed to add signature to obligation".to_string(),
1308 })?;
1309 Ok(())
1310 }
1311
1312 #[instrument(level = "trace", skip_all)]
1313 pub fn verify_all(self) -> IotaResult<()> {
1314 let mut pks = Vec::with_capacity(self.public_keys.len());
1315 for pk in self.public_keys.clone() {
1316 pks.push(pk.into_iter());
1317 }
1318 AggregateAuthoritySignature::batch_verify(
1319 &self.signatures.iter().collect::<Vec<_>>()[..],
1320 pks,
1321 &self.messages.iter().map(|x| &x[..]).collect::<Vec<_>>()[..],
1322 )
1323 .map_err(|e| {
1324 let message = format!(
1325 "pks: {:?}, messages: {:?}, sigs: {:?}",
1326 self.public_keys,
1327 self.messages
1328 .iter()
1329 .map(Base64::encode)
1330 .collect::<Vec<String>>(),
1331 self.signatures
1332 .iter()
1333 .map(|s| Base64::encode(s.as_ref()))
1334 .collect::<Vec<String>>()
1335 );
1336
1337 let chunk_size = 2048;
1338
1339 for (i, chunk) in message
1342 .as_bytes()
1343 .chunks(chunk_size)
1344 .map(std::str::from_utf8)
1345 .enumerate()
1346 {
1347 warn!(
1348 "Failed to batch verify aggregated auth sig: {} (chunk {}): {}",
1349 e,
1350 i,
1351 chunk.unwrap()
1352 );
1353 }
1354
1355 IotaError::InvalidSignature {
1356 error: format!("Failed to batch verify aggregated auth sig: {e}"),
1357 }
1358 })?;
1359 Ok(())
1360 }
1361}
1362
1363pub mod bcs_signable_test {
1364 use serde::{Deserialize, Serialize};
1365
1366 #[derive(Clone, Serialize, Deserialize)]
1367 pub struct Foo(pub String);
1368
1369 #[cfg(test)]
1370 #[derive(Serialize, Deserialize)]
1371 pub struct Bar(pub String);
1372
1373 #[cfg(test)]
1374 use super::VerificationObligation;
1375
1376 #[cfg(test)]
1377 pub fn get_obligation_input<T>(value: &T) -> (VerificationObligation<'_>, usize)
1378 where
1379 T: super::bcs_signable::BcsSignable,
1380 {
1381 use iota_sdk_types::crypto::{Intent, IntentScope};
1382
1383 let mut obligation = VerificationObligation::default();
1384 let idx = obligation.add_message(
1386 value,
1387 0,
1388 Intent::iota_app(IntentScope::SenderSignedTransaction),
1389 );
1390 (obligation, idx)
1391 }
1392}
1393
1394impl FromStr for PublicKey {
1395 type Err = eyre::Report;
1396 fn from_str(s: &str) -> Result<Self, Self::Err> {
1397 Self::decode_base64(s).map_err(|e| eyre!("Fail to decode base64 {}", e.to_string()))
1398 }
1399}
1400
1401#[cfg(not(target_arch = "wasm32"))]
1404pub type RandomnessSignature = fastcrypto_tbls::types::Signature;
1405#[cfg(not(target_arch = "wasm32"))]
1406pub type RandomnessPartialSignature = fastcrypto_tbls::tbls::PartialSignature<RandomnessSignature>;
1407#[cfg(not(target_arch = "wasm32"))]
1408pub type RandomnessPrivateKey =
1409 fastcrypto_tbls::ecies_v1::PrivateKey<fastcrypto::groups::bls12381::G2Element>;