starcoinorg / starcoin-java

Apache License 2.0
5 stars 10 forks source link

实现 SignedMessage 的校验 #31

Closed jolestar closed 2 years ago

jolestar commented 2 years ago
/// SigningMessage is a message to be signed and encapsulates the salt
#[derive(Clone, Debug, Hash, Eq, PartialEq, CryptoHasher, CryptoHash, JsonSchema)]
pub struct SigningMessage(pub Vec<u8>);

SigningMessage 封装的是原始的签名消息 bytes,不过它的 hash 通过 CryptoHash 加了 salt。

#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize, CryptoHasher, CryptoHash)]
pub struct SignedMessage {
    /// The account to sign the message.
    pub account: AccountAddress,
    pub message: SigningMessage,
    pub authenticator: TransactionAuthenticator,
    pub chain_id: ChainId,
}

SignedMessage 封装了校验签名所需的一些参数,并且提供两个方法,check_signaturecheck_account

check_signature: 保证 authenticator(pubkey&signature) 和 message 匹配 check_account: 保证 account 和 pubkey 匹配。需要从链上获取 AccountResource, 然后通过 AccountResource 中的 authentication_key 来校验 pubkey。考虑到 account 有可能在链上不存在,以及用户第一次创建后,authentication_key 为空,默认会使用 address 来作为 authentication_key 校验 account。


/// Checks that the signature of given message. Returns `Ok()` if the signature is valid.
    /// Note: this method do not check the relation of account and public key.
    pub fn check_signature(&self) -> Result<()> {
        self.authenticator.verify(&self.message)
    }

    /// Checks the account by on chain account resource, please ensure the AccountResource's address == message.account
    /// `chain_id` is the chain of the account resource on.
    /// if the `account_resource` is None, it means that the account is not create on chain
    pub fn check_account(
        &self,
        chain_id: ChainId,
        account_resource: Option<&AccountResource>,
    ) -> Result<()> {
        let authkey_in_message = self.authenticator.authentication_key();
        let authkey_on_chain = account_resource
            .map(|account| account.authentication_key())
            .unwrap_or_else(|| AuthenticationKey::DUMMY_KEY.as_ref());
        // if the account not exist on chain or the authentication_key on chain is dummy key, just check the derived_address.
        if authkey_on_chain == AuthenticationKey::DUMMY_KEY.as_ref() {
            ensure!(
                authkey_in_message.derived_address() == self.account,
                "authenticator's address do not match the signed message account"
            )
        } else {
            ensure!(
                self.chain_id == chain_id,
                "The chain id in message and on chain account miss match."
            );
            ensure!(
                authkey_in_message.as_ref() == authkey_on_chain,
                "authenticator's public key do not match the account resource on chain"
            );
        }
        Ok(())
    }

实现后需要和

  1. starcoin account sign-message|verify-sign-message
  2. https://starmask-test-dapp.starcoin.org/ 中的 personal sign

互相校验

ssyuan commented 2 years ago

https://github.com/starcoinorg/starcoin-java/pull/32 java版本已经实现