Skip to content

Commit

Permalink
Merge pull request #1804 from mintlayer/feature/wasm-sign-verify-chal…
Browse files Browse the repository at this point in the history
…lenge

add sign and verify challenge to wasm lib
  • Loading branch information
OBorce committed Sep 2, 2024
2 parents 4aebefb + a9661e2 commit 1e150d7
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 0 deletions.
12 changes: 12 additions & 0 deletions wasm-wrappers/WASM-API.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ that derived the given public key.
Note that this function is used for verifying messages related to spending,
such as transaction input witness.

### Function: `sign_challenge`

Given a message and a private key, create and sign a challenge with the given private key
This kind of signature is to be used when signing challenges.

### Function: `verify_challenge`

Given a signed challenge, an address and a message. Verify that
the signature is produced by signing the message with the private key
that derived the given public key.
Note that this function is used for verifying messages related challenges.

### Function: `encode_output_transfer`

Given a destination address, an amount and a network type (mainnet, testnet, etc), this function
Expand Down
23 changes: 23 additions & 0 deletions wasm-wrappers/js-bindings/wasm_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ import {
effective_pool_balance,
Amount,
encode_output_issue_nft,
sign_challenge,
verify_challenge,
} from "../pkg/wasm_wrappers.js";

function assert_eq_arrays(arr1, arr2) {
Expand Down Expand Up @@ -103,6 +105,27 @@ export async function run_test() {
console.log("Tested invalid menemonic successfully");
}

{
let challenge = sign_challenge(priv_key, message);
let address = pubkey_to_pubkeyhash_address(pub_key, Network.Testnet);
let result = verify_challenge(address, Network.Testnet, challenge, message);
if (!result) {
throw new Error("Invalid sing and verify challenge");
}

const different_priv_key = make_private_key();
const different_pub_key = public_key_from_private_key(different_priv_key);
let different_address = pubkey_to_pubkeyhash_address(different_pub_key, Network.Testnet);
try {
verify_challenge(different_address, Network.Testnet, challenge, message);
} catch (e) {
if (!e.includes("Public key to address mismatch")) {
throw e;
}
console.log("Tested verify with different address successfully");
}
}

try {
make_receiving_address(bad_priv_key, 0);
throw new Error("Invalid private key worked somehow!");
Expand Down
36 changes: 36 additions & 0 deletions wasm-wrappers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ use common::{
output_value::OutputValue::{self, Coin, TokenV1},
signature::{
inputsig::{
arbitrary_message::{produce_message_challenge, ArbitraryMessageSignature},
authorize_hashed_timelock_contract_spend::AuthorizedHashedTimelockContractSpend,
authorize_pubkeyhash_spend::AuthorizedPublicKeyHashSpend,
classical_multisig::authorize_classical_multisig::{
sign_classical_multisig_spending, AuthorizedClassicalMultisigSpend,
},
Expand Down Expand Up @@ -340,6 +342,40 @@ pub fn verify_signature_for_spending(
Ok(verifcation_result)
}

/// Given a message and a private key, create and sign a challenge with the given private key
/// This kind of signature is to be used when signing challenges.
#[wasm_bindgen]
pub fn sign_challenge(private_key: &[u8], message: &[u8]) -> Result<Vec<u8>, Error> {
let private_key = PrivateKey::decode_all(&mut &private_key[..])
.map_err(|_| Error::InvalidPrivateKeyEncoding)?;

let challenge = produce_message_challenge(message);
let public_key = PublicKey::from_private_key(&private_key);

let signature = private_key.sign_message(&challenge.encode(), randomness::make_true_rng())?;
let signature = AuthorizedPublicKeyHashSpend::new(public_key, signature);
Ok(signature.encode())
}

/// Given a signed challenge, an address and a message. Verify that
/// the signature is produced by signing the message with the private key
/// that derived the given public key.
/// Note that this function is used for verifying messages related challenges.
#[wasm_bindgen]
pub fn verify_challenge(
address: &str,
network: Network,
signed_challenge: &[u8],
message: &[u8],
) -> Result<bool, Error> {
let chain_config = Builder::new(network.into()).build();
let destination = parse_addressable::<Destination>(&chain_config, address)?;
let message_challenge = produce_message_challenge(message);
let sig = ArbitraryMessageSignature::from_data(signed_challenge.to_vec());
sig.verify_signature(&chain_config, &destination, &message_challenge)?;
Ok(true)
}

fn parse_addressable<T: Addressable>(
chain_config: &ChainConfig,
address: &str,
Expand Down

0 comments on commit 1e150d7

Please sign in to comment.