Skip to content

Commit cff0732

Browse files
committed
enhance: sign message api
1 parent 291f8f6 commit cff0732

File tree

3 files changed

+42
-42
lines changed

3 files changed

+42
-42
lines changed

cli/src/modules/message.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1+
use crate::imports::*;
12
use kaspa_addresses::Version;
23
use kaspa_bip32::secp256k1::XOnlyPublicKey;
4+
use kaspa_wallet_core::message::SignMessageOptions;
35
use kaspa_wallet_core::{
46
account::{BIP32_ACCOUNT_KIND, KEYPAIR_ACCOUNT_KIND},
57
message::{sign_message, verify_message, PersonalMessage},
68
};
79

8-
use crate::imports::*;
9-
1010
#[derive(Default)]
1111
pub struct Message;
1212

@@ -87,8 +87,9 @@ impl Message {
8787

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

91-
let sig_result = sign_message(&pm, &privkey);
92+
let sig_result = sign_message(&pm, &privkey, &sign_options);
9293

9394
match sig_result {
9495
Ok(signature) => {

wallet/core/src/message.rs

+34-20
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,28 @@ impl AsRef<[u8]> for PersonalMessage<'_> {
1515
}
1616
}
1717

18-
/// Sign a message with the given private key
19-
pub fn sign_message(msg: &PersonalMessage, privkey: &[u8; 32]) -> Result<Vec<u8>, Error> {
20-
let hash = calc_personal_message_hash(msg);
21-
22-
let msg = secp256k1::Message::from_digest_slice(hash.as_bytes().as_slice())?;
23-
let schnorr_key = secp256k1::Keypair::from_seckey_slice(secp256k1::SECP256K1, privkey)?;
24-
let sig: [u8; 64] = *schnorr_key.sign_schnorr(msg).as_ref();
25-
26-
Ok(sig.to_vec())
18+
#[derive(Clone)]
19+
pub struct SignMessageOptions {
20+
/// The auxiliary randomness exists only to mitigate specific kinds of power analysis
21+
/// side-channel attacks. Providing it definitely improves security, but omitting it
22+
/// should not be considered dangerous, as most legacy signature schemes don't provide
23+
/// mitigations against such attacks. To read more about the relevant discussions that
24+
/// arose in adding this randomness please see: https://github.com/sipa/bips/issues/195
25+
pub no_aux_rand: bool,
2726
}
2827

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

3332
let msg = secp256k1::Message::from_digest_slice(hash.as_bytes().as_slice())?;
3433
let schnorr_key = secp256k1::Keypair::from_seckey_slice(secp256k1::SECP256K1, privkey)?;
35-
let sig: [u8; 64] = *secp256k1::SECP256K1.sign_schnorr_no_aux_rand(&msg, &schnorr_key).as_ref();
34+
35+
let sig: [u8; 64] = if options.no_aux_rand {
36+
*schnorr_key.sign_schnorr(msg).as_ref()
37+
} else {
38+
*secp256k1::Secp256k1::new().sign_schnorr_no_aux_rand(&msg, &schnorr_key).as_ref()
39+
};
3640

3741
Ok(sig.to_vec())
3842
}
@@ -85,8 +89,11 @@ mod tests {
8589
])
8690
.unwrap();
8791

88-
verify_message(&pm, &sign_message(&pm, &privkey).expect("sign_message failed"), &pubkey).expect("verify_message failed");
89-
verify_message(&pm, &sign_message_without_rand(&pm, &privkey).expect("sign_message failed"), &pubkey)
92+
let sign_with_aux_rand = SignMessageOptions { no_aux_rand: false };
93+
let sign_with_no_aux_rand = SignMessageOptions { no_aux_rand: true };
94+
verify_message(&pm, &sign_message(&pm, &privkey, &sign_with_aux_rand).expect("sign_message failed"), &pubkey)
95+
.expect("verify_message failed");
96+
verify_message(&pm, &sign_message(&pm, &privkey, &sign_with_no_aux_rand).expect("sign_message failed"), &pubkey)
9097
.expect("verify_message failed");
9198
}
9299

@@ -98,8 +105,9 @@ mod tests {
98105
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
99106
];
100107

101-
let signature = sign_message_without_rand(&pm, &privkey).expect("sign_message failed");
102-
let signature_twice = sign_message_without_rand(&pm, &privkey).expect("sign_message failed");
108+
let sign_with_no_aux_rand = SignMessageOptions { no_aux_rand: true };
109+
let signature = sign_message(&pm, &privkey, &sign_with_no_aux_rand).expect("sign_message failed");
110+
let signature_twice = sign_message(&pm, &privkey, &sign_with_no_aux_rand).expect("sign_message failed");
103111
assert_eq!(signature, signature_twice);
104112
}
105113

@@ -116,8 +124,11 @@ mod tests {
116124
])
117125
.unwrap();
118126

119-
verify_message(&pm, &sign_message(&pm, &privkey).expect("sign_message failed"), &pubkey).expect("verify_message failed");
120-
verify_message(&pm, &sign_message_without_rand(&pm, &privkey).expect("sign_message failed"), &pubkey)
127+
let sign_with_aux_rand = SignMessageOptions { no_aux_rand: false };
128+
let sign_with_no_aux_rand = SignMessageOptions { no_aux_rand: true };
129+
verify_message(&pm, &sign_message(&pm, &privkey, &sign_with_aux_rand).expect("sign_message failed"), &pubkey)
130+
.expect("verify_message failed");
131+
verify_message(&pm, &sign_message(&pm, &privkey, &sign_with_no_aux_rand).expect("sign_message failed"), &pubkey)
121132
.expect("verify_message failed");
122133
}
123134

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

141-
verify_message(&pm, &sign_message(&pm, &privkey).expect("sign_message failed"), &pubkey).expect("verify_message failed");
142-
verify_message(&pm, &sign_message_without_rand(&pm, &privkey).expect("sign_message failed"), &pubkey)
152+
let sign_with_aux_rand = SignMessageOptions { no_aux_rand: false };
153+
let sign_with_no_aux_rand = SignMessageOptions { no_aux_rand: true };
154+
verify_message(&pm, &sign_message(&pm, &privkey, &sign_with_aux_rand).expect("sign_message failed"), &pubkey)
155+
.expect("verify_message failed");
156+
verify_message(&pm, &sign_message(&pm, &privkey, &sign_with_no_aux_rand).expect("sign_message failed"), &pubkey)
143157
.expect("verify_message failed");
144158
}
145159

wallet/core/src/wasm/message.rs

+4-19
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const TS_MESSAGE_TYPES: &'static str = r#"
1414
export interface ISignMessage {
1515
message: string;
1616
privateKey: PrivateKey | string;
17+
noAuxRand: boolean;
1718
}
1819
"#;
1920

@@ -30,28 +31,12 @@ pub fn js_sign_message(value: ISignMessage) -> Result<HexString, Error> {
3031
if let Some(object) = Object::try_from(&value) {
3132
let private_key = object.cast_into::<PrivateKey>("privateKey")?;
3233
let raw_msg = object.get_string("message")?;
34+
let no_aux_rand = object.get_bool("noAuxRand")?;
3335
let mut privkey_bytes = [0u8; 32];
3436
privkey_bytes.copy_from_slice(&private_key.secret_bytes());
3537
let pm = PersonalMessage(&raw_msg);
36-
let sig_vec = sign_message(&pm, &privkey_bytes)?;
37-
privkey_bytes.zeroize();
38-
Ok(faster_hex::hex_string(sig_vec.as_slice()).into())
39-
} else {
40-
Err(Error::custom("Failed to parse input"))
41-
}
42-
}
43-
44-
/// Signs a message with the given private key without rand
45-
/// @category Message Signing
46-
#[wasm_bindgen(js_name = signMessageWithoutRand)]
47-
pub fn js_sign_message_without_rand(value: ISignMessage) -> Result<HexString, Error> {
48-
if let Some(object) = Object::try_from(&value) {
49-
let private_key = object.cast_into::<PrivateKey>("privateKey")?;
50-
let raw_msg = object.get_string("message")?;
51-
let mut privkey_bytes = [0u8; 32];
52-
privkey_bytes.copy_from_slice(&private_key.secret_bytes());
53-
let pm = PersonalMessage(&raw_msg);
54-
let sig_vec = sign_message_without_rand(&pm, &privkey_bytes)?;
38+
let sign_options = SignMessageOptions { no_aux_rand };
39+
let sig_vec = sign_message(&pm, &privkey_bytes, &sign_options)?;
5540
privkey_bytes.zeroize();
5641
Ok(faster_hex::hex_string(sig_vec.as_slice()).into())
5742
} else {

0 commit comments

Comments
 (0)