Skip to content

Commit

Permalink
add sign and verify challenge to wasm lib
Browse files Browse the repository at this point in the history
  • Loading branch information
OBorce committed Aug 28, 2024
1 parent d498c0f commit a9661e2
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 a9661e2

Please sign in to comment.