-
Notifications
You must be signed in to change notification settings - Fork 43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Wrong local sig is generated, when the first byte of a hash input is 0. #35
Comments
Hi @rantan ! #[test]
fn test_byte_vec(){
let message: Vec<u8> = vec![0, 1];
let big_int0 = BigInt::from((message[0] as i32));
let big_int1 = BigInt::from((message[1] as i32));
let result = HSha256::create_hash(&[&big_int0,&big_int1]).to_hex();
let mut hasher = Sha256::new();
hasher.input(&message);
let result2 = hex::encode(hasher.result());
assert_eq!(result,result2); This issue is more relevant to Here is the relevant tests that compare this hash to known test vectors: If you feel that some usage of this hash function is not covered by the tests (probably the one above): I encourage you to open an issue for it in the |
Thank you for your response. How about this part. https://github.com/KZen-networks/multi-party-schnorr/blob/master/src/protocols/thresholdsig/bitcoin_schnorr.rs#L188 When creating localsig, it converts message bytes array to BigInt. According above way you showed, I think it should convert each byte to a BigInt value. |
This is a solid question. As you can see from the report, this is the convention we use in all our libraries. However we do intend on changing it at some point, just didn't find the right excuse. How critical it is for the operation of your code? |
Thank you for the information. I read it and I could understand probably ;) However, I think this issue and the It is the problem that the input data passed into the hash function is going to be changed through converting to BigInt in This is an example to show that the message hash is going to be changed if the first byte is 0. The assertion is failure. #[test]
fn test() {
let message: Vec<u8> = hex::decode("00908debc0c1426a7fa1b830348974f7be2b3978698e2259f4ac75a8adce707f").unwrap();
let bi = BigInt::from(&message[..]);
assert_eq!(BigInt::to_vec(&bi), message);
} It means that a message what |
I think you are right. We will fix it. |
Thank you! I think there are 2 way to fix.
Which do you prefer or others? |
YES, go ahead. |
…yte. The sha256 hash function which is used in schnorr signature generation receives inputs as BigInt value. But the BigInt value eliminate head bytes if it is zero. So that, the output of hash function was wrong. This commit changes the message into BigInt array for each byte of the message. fix ZenGo-X#35
Hey @rantan |
Hi. #[cfg(test)]
mod tests {
use curv::{GE, FE, BigInt};
use curv::elliptic::curves::traits::{ECPoint, ECScalar};
use curv::elliptic::curves::secp256_k1::Secp256k1Scalar;
use protocols::thresholdsig::bitcoin_schnorr::{LocalSig, SharedKeys};
use sha2::Digest;
#[test]
fn test_compute_localsig() {
let g: GE = ECPoint::generator();
let local_ephemeral_key = {
let prev = Secp256k1Scalar::new_random();
SharedKeys {
y: g * prev,
x_i: prev
}
};
let local_private_key = {
let prev = Secp256k1Scalar::new_random();
SharedKeys {
y: g * prev,
x_i: prev
}
};
let message =
hex::decode("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")
.unwrap();
let sig = LocalSig::compute(&message[..], &local_ephemeral_key, &local_private_key);
let expected: LocalSig = {
let beta_i = local_ephemeral_key.x_i.clone();
let alpha_i = local_private_key.x_i.clone();
let mut hasher = sha2::Sha256::new();
hasher.input(&local_ephemeral_key.y.get_element().serialize()[..]);
hasher.input(&local_private_key.y.get_element().serialize()[..]);
hasher.input(&message[..]);
let bn = BigInt::from(&hasher.result()[..]);
let e: FE = ECScalar::from(&bn);
let gamma_i = beta_i + e.clone() * alpha_i;
LocalSig { gamma_i, e }
};
assert_eq!(expected.gamma_i, sig.gamma_i);
assert_eq!(expected.e, sig.e);
}
} According to this test, the LocalSig is correct for my issue. Thanks! |
great, feel free to create a PR with the same concept and apply it to other places in the code that you think might be exposed to the same issue |
…yte. The sha256 hash function which is used in schnorr signature generation receives inputs as BigInt value. But the BigInt value eliminate head bytes if it is zero. So that, the output of hash function was wrong. This commit changes the message into BigInt array for each byte of the message. fix ZenGo-X#35
…yte. The sha256 hash function which is used in schnorr signature generation receives inputs as BigInt value. But the BigInt value eliminate head bytes if it is zero. So that, the output of hash function was wrong. This commit changes the message into BigInt array for each byte of the message. fix ZenGo-X#35
Current LocalSig generation code in
src/protocols/thresholdsig/bitcoin_schnorr.rs
uses a hash function which get input values as BigInt. However, if the first bytes of input is 0, the BigInt omit the 0. So the final hash value is going to be wrong.I tried to create signature with this crate and i got some wrong signatures. It couldn't be verified on other schnorr signature verification code like this.
This is a simple test case for the hash function. The assertion is failure.
I think that the signature compute code should use other hash function implementation or fix it.
The text was updated successfully, but these errors were encountered: