Skip to main content

iota_types/
signature.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use iota_protocol_config::ProtocolConfig;
6use iota_sdk_crypto::{Verifier, simple::SimpleVerifier};
7use iota_sdk_types::{
8    Address, UserSignature,
9    crypto::{IntentMessage, SimpleSignature},
10};
11use serde::Serialize;
12
13use crate::error::{IotaError, IotaResult};
14
15#[derive(Default, Debug, Clone)]
16pub struct VerifyParams {
17    pub accept_passkey_in_multisig: bool,
18    pub additional_multisig_checks: bool,
19    pub reject_partially_signed_mixed_ed25519_multisig: bool,
20}
21
22impl VerifyParams {
23    pub fn new(
24        accept_passkey_in_multisig: bool,
25        additional_multisig_checks: bool,
26        reject_partially_signed_mixed_ed25519_multisig: bool,
27    ) -> Self {
28        Self {
29            accept_passkey_in_multisig,
30            additional_multisig_checks,
31            reject_partially_signed_mixed_ed25519_multisig,
32        }
33    }
34
35    /// The parameters the network applies at `config`'s protocol version.
36    pub fn from_protocol_config(config: &ProtocolConfig) -> Self {
37        Self::new(
38            config.accept_passkey_in_multisig(),
39            config.additional_multisig_checks(),
40            config.reject_partially_signed_mixed_ed25519_multisig(),
41        )
42    }
43}
44
45/// A lightweight trait that all members of [`UserSignature`] implement.
46pub trait AuthenticatorTrait {
47    fn verify_claims<T>(
48        &self,
49        value: &IntentMessage<T>,
50        author: Address,
51        aux_verify_data: &VerifyParams,
52    ) -> IotaResult
53    where
54        T: Serialize;
55}
56
57impl AuthenticatorTrait for UserSignature {
58    fn verify_claims<T>(
59        &self,
60        value: &IntentMessage<T>,
61        author: Address,
62        aux_verify_data: &VerifyParams,
63    ) -> IotaResult
64    where
65        T: Serialize,
66    {
67        match self {
68            UserSignature::Simple(s) => s.verify_claims(value, author, aux_verify_data),
69            UserSignature::Multisig(s) => s.verify_claims(value, author, aux_verify_data),
70            UserSignature::PasskeyAuthenticator(s) => {
71                s.verify_claims(value, author, aux_verify_data)
72            }
73            UserSignature::MoveAuthenticator(s) => s.verify_claims(value, author, aux_verify_data),
74            _ => unimplemented!("a new UserSignature variant was added and needs to be handled"),
75        }
76    }
77}
78
79impl AuthenticatorTrait for SimpleSignature {
80    #[tracing::instrument(level = "trace", skip_all)]
81    fn verify_claims<T>(
82        &self,
83        value: &IntentMessage<T>,
84        author: Address,
85        _aux_verify_data: &VerifyParams,
86    ) -> IotaResult
87    where
88        T: Serialize,
89    {
90        // `SimpleVerifier` only checks the signature against its embedded public
91        // key, so the signer/author binding is enforced here.
92        let address: Address = self.to_public_key().into();
93        if author != address {
94            return Err(IotaError::IncorrectSigner {
95                error: format!("Incorrect signer, expected {author}, got {address}"),
96            });
97        }
98
99        SimpleVerifier
100            .verify(&value.signing_digest(), self)
101            .map_err(|e| IotaError::InvalidSignature {
102                error: format!("Fail to verify user sig {e}"),
103            })
104    }
105}