How to verify SECP256K1 signed message in smart contract?
Asked Answered
R

1

6

I have signed the message, using ed25519

const msg = Buffer.from("hi");
const signerKeyPair = await keyStore.getKey(config.networkId, signerAccount);
const { signature } = signerKeyPair.sign(msg); 

How to verify the signature in the smart contract if I have a signature and signer PublicKey?

I've found that near-core uses a near-crypto crate to do it, but I'm not sure that I can use it for the smart contracts.

an example using near-core

use near_crypto::{PublicKey, Signature, KeyType};
...
   pub fn verify(&self, data: &[u8], public_key: String) -> bool {
        let public_key = PublicKey::from_str(&public_key).unwrap();
        let signature = Signature::empty(KeyType::SECP256K1);
        signature.verify(data, &public_key)
    }
...
Roemer answered 19/11, 2021 at 21:32 Comment(0)
R
4

Here is a solution

using ed25519-dalek = "1.0.1" crate

pub fn gimme_my_present(&mut self, signature: Vec<u8>) -> Promise {
    let signature = ed25519_dalek::Signature::try_from(signature.as_ref())
        .expect("Signature should be a valid array of 64 bytes [13, 254, 123, ...]");

    let account_id = near_sdk::env::signer_account_id();

    // Someone will give you the corresponding private key...
    let public_key = ed25519_dalek::PublicKey::from_bytes(
        &bs58::decode(
            "H5ANpdUoXVwhYBgAgEi1ieMQZKJbwxjPJtHX4vkVcSnF",
        )
        .into_vec()
        .unwrap(),
    )
    .unwrap();

    near_sdk::env::log(
        format!(
            "Verifiying validity of signature ('{:?}') for string '{}'...",
            signature, account_id
        )
        .as_bytes(),
    );

    if let Ok(_) = public_key.verify(account_id.as_bytes(), &signature) {
        return Promise::new(account_id).transfer(16 * 16 * ONE_NEAR);
    }

    panic!("Ima no gonna give-ya the present without a signature! :-P");
}

source

Roemer answered 20/11, 2021 at 7:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.