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_sdk_crypto::{Verifier, simple::SimpleVerifier};
6use iota_sdk_types::{
7    Address, UserSignature,
8    crypto::{IntentMessage, SimpleSignature},
9};
10use serde::Serialize;
11
12use crate::error::{IotaError, IotaResult};
13
14#[derive(Default, Debug, Clone)]
15pub struct VerifyParams {
16    pub accept_passkey_in_multisig: bool,
17    pub additional_multisig_checks: bool,
18}
19
20impl VerifyParams {
21    pub fn new(accept_passkey_in_multisig: bool, additional_multisig_checks: bool) -> Self {
22        Self {
23            accept_passkey_in_multisig,
24            additional_multisig_checks,
25        }
26    }
27}
28
29/// A lightweight trait that all members of [`UserSignature`] implement.
30pub trait AuthenticatorTrait {
31    fn verify_claims<T>(
32        &self,
33        value: &IntentMessage<T>,
34        author: Address,
35        aux_verify_data: &VerifyParams,
36    ) -> IotaResult
37    where
38        T: Serialize;
39}
40
41impl AuthenticatorTrait for UserSignature {
42    fn verify_claims<T>(
43        &self,
44        value: &IntentMessage<T>,
45        author: Address,
46        aux_verify_data: &VerifyParams,
47    ) -> IotaResult
48    where
49        T: Serialize,
50    {
51        match self {
52            UserSignature::Simple(s) => s.verify_claims(value, author, aux_verify_data),
53            UserSignature::Multisig(s) => s.verify_claims(value, author, aux_verify_data),
54            UserSignature::PasskeyAuthenticator(s) => {
55                s.verify_claims(value, author, aux_verify_data)
56            }
57            UserSignature::MoveAuthenticator(s) => s.verify_claims(value, author, aux_verify_data),
58            _ => unimplemented!("a new UserSignature variant was added and needs to be handled"),
59        }
60    }
61}
62
63impl AuthenticatorTrait for SimpleSignature {
64    #[tracing::instrument(level = "trace", skip_all)]
65    fn verify_claims<T>(
66        &self,
67        value: &IntentMessage<T>,
68        author: Address,
69        _aux_verify_data: &VerifyParams,
70    ) -> IotaResult
71    where
72        T: Serialize,
73    {
74        // `SimpleVerifier` only checks the signature against its embedded public
75        // key, so the signer/author binding is enforced here.
76        let address: Address = self.to_public_key().into();
77        if author != address {
78            return Err(IotaError::IncorrectSigner {
79                error: format!("Incorrect signer, expected {author}, got {address}"),
80            });
81        }
82
83        SimpleVerifier
84            .verify(value.signing_digest().inner(), self)
85            .map_err(|e| IotaError::InvalidSignature {
86                error: format!("Fail to verify user sig {e}"),
87            })
88    }
89}