Skip to content

Commit

Permalink
enhance: sign message api
Browse files Browse the repository at this point in the history
  • Loading branch information
witter-deland committed Nov 13, 2024
1 parent 291f8f6 commit cff0732
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 42 deletions.
7 changes: 4 additions & 3 deletions cli/src/modules/message.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use crate::imports::*;
use kaspa_addresses::Version;
use kaspa_bip32::secp256k1::XOnlyPublicKey;
use kaspa_wallet_core::message::SignMessageOptions;
use kaspa_wallet_core::{
account::{BIP32_ACCOUNT_KIND, KEYPAIR_ACCOUNT_KIND},
message::{sign_message, verify_message, PersonalMessage},
};

use crate::imports::*;

#[derive(Default)]
pub struct Message;

Expand Down Expand Up @@ -87,8 +87,9 @@ impl Message {

let pm = PersonalMessage(message);
let privkey = self.get_address_private_key(&ctx, kaspa_address).await?;
let sign_options = SignMessageOptions { no_aux_rand: false };

let sig_result = sign_message(&pm, &privkey);
let sig_result = sign_message(&pm, &privkey, &sign_options);

match sig_result {
Ok(signature) => {
Expand Down
54 changes: 34 additions & 20 deletions wallet/core/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,28 @@ impl AsRef<[u8]> for PersonalMessage<'_> {
}
}

/// Sign a message with the given private key
pub fn sign_message(msg: &PersonalMessage, privkey: &[u8; 32]) -> Result<Vec<u8>, Error> {
let hash = calc_personal_message_hash(msg);

let msg = secp256k1::Message::from_digest_slice(hash.as_bytes().as_slice())?;
let schnorr_key = secp256k1::Keypair::from_seckey_slice(secp256k1::SECP256K1, privkey)?;
let sig: [u8; 64] = *schnorr_key.sign_schnorr(msg).as_ref();

Ok(sig.to_vec())
#[derive(Clone)]
pub struct SignMessageOptions {
/// The auxiliary randomness exists only to mitigate specific kinds of power analysis
/// side-channel attacks. Providing it definitely improves security, but omitting it
/// should not be considered dangerous, as most legacy signature schemes don't provide
/// mitigations against such attacks. To read more about the relevant discussions that
/// arose in adding this randomness please see: https://github.com/sipa/bips/issues/195
pub no_aux_rand: bool,
}

/// Sign a message with the given private key without random
pub fn sign_message_without_rand(msg: &PersonalMessage, privkey: &[u8; 32]) -> Result<Vec<u8>, Error> {
/// Sign a message with the given private key
pub fn sign_message(msg: &PersonalMessage, privkey: &[u8; 32], options: &SignMessageOptions) -> Result<Vec<u8>, Error> {
let hash = calc_personal_message_hash(msg);

let msg = secp256k1::Message::from_digest_slice(hash.as_bytes().as_slice())?;
let schnorr_key = secp256k1::Keypair::from_seckey_slice(secp256k1::SECP256K1, privkey)?;
let sig: [u8; 64] = *secp256k1::SECP256K1.sign_schnorr_no_aux_rand(&msg, &schnorr_key).as_ref();

let sig: [u8; 64] = if options.no_aux_rand {
*schnorr_key.sign_schnorr(msg).as_ref()
} else {
*secp256k1::Secp256k1::new().sign_schnorr_no_aux_rand(&msg, &schnorr_key).as_ref()
};

Ok(sig.to_vec())
}
Expand Down Expand Up @@ -85,8 +89,11 @@ mod tests {
])
.unwrap();

verify_message(&pm, &sign_message(&pm, &privkey).expect("sign_message failed"), &pubkey).expect("verify_message failed");
verify_message(&pm, &sign_message_without_rand(&pm, &privkey).expect("sign_message failed"), &pubkey)
let sign_with_aux_rand = SignMessageOptions { no_aux_rand: false };
let sign_with_no_aux_rand = SignMessageOptions { no_aux_rand: true };
verify_message(&pm, &sign_message(&pm, &privkey, &sign_with_aux_rand).expect("sign_message failed"), &pubkey)
.expect("verify_message failed");
verify_message(&pm, &sign_message(&pm, &privkey, &sign_with_no_aux_rand).expect("sign_message failed"), &pubkey)
.expect("verify_message failed");
}

Expand All @@ -98,8 +105,9 @@ mod tests {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
];

let signature = sign_message_without_rand(&pm, &privkey).expect("sign_message failed");
let signature_twice = sign_message_without_rand(&pm, &privkey).expect("sign_message failed");
let sign_with_no_aux_rand = SignMessageOptions { no_aux_rand: true };
let signature = sign_message(&pm, &privkey, &sign_with_no_aux_rand).expect("sign_message failed");
let signature_twice = sign_message(&pm, &privkey, &sign_with_no_aux_rand).expect("sign_message failed");
assert_eq!(signature, signature_twice);
}

Expand All @@ -116,8 +124,11 @@ mod tests {
])
.unwrap();

verify_message(&pm, &sign_message(&pm, &privkey).expect("sign_message failed"), &pubkey).expect("verify_message failed");
verify_message(&pm, &sign_message_without_rand(&pm, &privkey).expect("sign_message failed"), &pubkey)
let sign_with_aux_rand = SignMessageOptions { no_aux_rand: false };
let sign_with_no_aux_rand = SignMessageOptions { no_aux_rand: true };
verify_message(&pm, &sign_message(&pm, &privkey, &sign_with_aux_rand).expect("sign_message failed"), &pubkey)
.expect("verify_message failed");
verify_message(&pm, &sign_message(&pm, &privkey, &sign_with_no_aux_rand).expect("sign_message failed"), &pubkey)
.expect("verify_message failed");
}

Expand All @@ -138,8 +149,11 @@ Ut omnis magnam et accusamus earum rem impedit provident eum commodi repellat qu
])
.unwrap();

verify_message(&pm, &sign_message(&pm, &privkey).expect("sign_message failed"), &pubkey).expect("verify_message failed");
verify_message(&pm, &sign_message_without_rand(&pm, &privkey).expect("sign_message failed"), &pubkey)
let sign_with_aux_rand = SignMessageOptions { no_aux_rand: false };
let sign_with_no_aux_rand = SignMessageOptions { no_aux_rand: true };
verify_message(&pm, &sign_message(&pm, &privkey, &sign_with_aux_rand).expect("sign_message failed"), &pubkey)
.expect("verify_message failed");
verify_message(&pm, &sign_message(&pm, &privkey, &sign_with_no_aux_rand).expect("sign_message failed"), &pubkey)
.expect("verify_message failed");
}

Expand Down
23 changes: 4 additions & 19 deletions wallet/core/src/wasm/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const TS_MESSAGE_TYPES: &'static str = r#"
export interface ISignMessage {
message: string;
privateKey: PrivateKey | string;
noAuxRand: boolean;
}
"#;

Expand All @@ -30,28 +31,12 @@ pub fn js_sign_message(value: ISignMessage) -> Result<HexString, Error> {
if let Some(object) = Object::try_from(&value) {
let private_key = object.cast_into::<PrivateKey>("privateKey")?;
let raw_msg = object.get_string("message")?;
let no_aux_rand = object.get_bool("noAuxRand")?;
let mut privkey_bytes = [0u8; 32];
privkey_bytes.copy_from_slice(&private_key.secret_bytes());
let pm = PersonalMessage(&raw_msg);
let sig_vec = sign_message(&pm, &privkey_bytes)?;
privkey_bytes.zeroize();
Ok(faster_hex::hex_string(sig_vec.as_slice()).into())
} else {
Err(Error::custom("Failed to parse input"))
}
}

/// Signs a message with the given private key without rand
/// @category Message Signing
#[wasm_bindgen(js_name = signMessageWithoutRand)]
pub fn js_sign_message_without_rand(value: ISignMessage) -> Result<HexString, Error> {
if let Some(object) = Object::try_from(&value) {
let private_key = object.cast_into::<PrivateKey>("privateKey")?;
let raw_msg = object.get_string("message")?;
let mut privkey_bytes = [0u8; 32];
privkey_bytes.copy_from_slice(&private_key.secret_bytes());
let pm = PersonalMessage(&raw_msg);
let sig_vec = sign_message_without_rand(&pm, &privkey_bytes)?;
let sign_options = SignMessageOptions { no_aux_rand };
let sig_vec = sign_message(&pm, &privkey_bytes, &sign_options)?;
privkey_bytes.zeroize();
Ok(faster_hex::hex_string(sig_vec.as_slice()).into())
} else {
Expand Down

0 comments on commit cff0732

Please sign in to comment.