Skip to content

Commit a2c25f2

Browse files
authored
Merge pull request #259 from p2pderivatives/implement-low-r-signing
Implement low r signing
2 parents 67c9be3 + 1d166d0 commit a2c25f2

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed

src/lib.rs

+124
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,34 @@ impl<C: Context> Secp256k1<C> {
661661

662662
}
663663

664+
fn der_length_check(sig: &ffi::Signature, max_len: usize) -> bool {
665+
let mut ser_ret = [0; 72];
666+
let mut len: usize = ser_ret.len();
667+
unsafe {
668+
let err = ffi::secp256k1_ecdsa_signature_serialize_der(
669+
ffi::secp256k1_context_no_precomp,
670+
ser_ret.as_mut_c_ptr(),
671+
&mut len,
672+
sig,
673+
);
674+
debug_assert!(err == 1);
675+
}
676+
len <= max_len
677+
}
678+
679+
fn compact_sig_has_zero_first_bit(sig: &ffi::Signature) -> bool {
680+
let mut compact = [0; 64];
681+
unsafe {
682+
let err = ffi::secp256k1_ecdsa_signature_serialize_compact(
683+
ffi::secp256k1_context_no_precomp,
684+
compact.as_mut_c_ptr(),
685+
sig,
686+
);
687+
debug_assert!(err == 1);
688+
}
689+
compact[0] < 0x80
690+
}
691+
664692
impl<C: Signing> Secp256k1<C> {
665693

666694
/// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce
@@ -679,6 +707,59 @@ impl<C: Signing> Secp256k1<C> {
679707
}
680708
}
681709

710+
fn sign_grind_with_check(
711+
&self, msg: &Message,
712+
sk: &key::SecretKey,
713+
check: impl Fn(&ffi::Signature) -> bool) -> Signature {
714+
let mut entropy_p : *const ffi::types::c_void = ptr::null();
715+
let mut counter : u32 = 0;
716+
let mut extra_entropy = [0u8; 32];
717+
loop {
718+
unsafe {
719+
let mut ret = ffi::Signature::new();
720+
// We can assume the return value because it's not possible to construct
721+
// an invalid signature from a valid `Message` and `SecretKey`
722+
assert_eq!(ffi::secp256k1_ecdsa_sign(self.ctx, &mut ret, msg.as_c_ptr(),
723+
sk.as_c_ptr(), ffi::secp256k1_nonce_function_rfc6979,
724+
entropy_p), 1);
725+
if check(&ret) {
726+
return Signature::from(ret);
727+
}
728+
729+
counter += 1;
730+
// From 1.32 can use `to_le_bytes` instead
731+
let le_counter = counter.to_le();
732+
let le_counter_bytes : [u8; 4] = mem::transmute(le_counter);
733+
for (i, b) in le_counter_bytes.iter().enumerate() {
734+
extra_entropy[i] = *b;
735+
}
736+
737+
entropy_p = extra_entropy.as_ptr() as *const ffi::types::c_void;
738+
}
739+
}
740+
}
741+
742+
/// Constructs a signature for `msg` using the secret key `sk`, RFC6979 nonce
743+
/// and "grinds" the nonce by passing extra entropy if necessary to produce
744+
/// a signature that is less than 71 - bytes_to_grund bytes. The number
745+
/// of signing operation performed by this function is exponential in the
746+
/// number of bytes grinded.
747+
/// Requires a signing capable context.
748+
pub fn sign_grind_r(&self, msg: &Message, sk: &key::SecretKey, bytes_to_grind: usize) -> Signature {
749+
let len_check = |s : &ffi::Signature| der_length_check(s, 71 - bytes_to_grind);
750+
return self.sign_grind_with_check(msg, sk, len_check);
751+
}
752+
753+
/// Constructs a signature for `msg` using the secret key `sk`, RFC6979 nonce
754+
/// and "grinds" the nonce by passing extra entropy if necessary to produce
755+
/// a signature that is less than 71 bytes and compatible with the low r
756+
/// signature implementation of bitcoin core. In average, this function
757+
/// will perform two signing operations.
758+
/// Requires a signing capable context.
759+
pub fn sign_low_r(&self, msg: &Message, sk: &key::SecretKey) -> Signature {
760+
return self.sign_grind_with_check(msg, sk, compact_sig_has_zero_first_bit)
761+
}
762+
682763
/// Generates a random keypair. Convenience function for `key::SecretKey::new`
683764
/// and `key::PublicKey::from_secret_key`; call those functions directly for
684765
/// batch key generation. Requires a signing-capable context. Requires compilation
@@ -1008,6 +1089,18 @@ mod tests {
10081089
let (sk, pk) = s.generate_keypair(&mut thread_rng());
10091090
let sig = s.sign(&msg, &sk);
10101091
assert_eq!(s.verify(&msg, &sig, &pk), Ok(()));
1092+
let low_r_sig = s.sign_low_r(&msg, &sk);
1093+
assert_eq!(s.verify(&msg, &low_r_sig, &pk), Ok(()));
1094+
let grind_r_sig = s.sign_grind_r(&msg, &sk, 1);
1095+
assert_eq!(s.verify(&msg, &grind_r_sig, &pk), Ok(()));
1096+
let compact = sig.serialize_compact();
1097+
if compact[0] < 0x80 {
1098+
assert_eq!(sig, low_r_sig);
1099+
} else {
1100+
assert_ne!(sig, low_r_sig);
1101+
}
1102+
assert!(super::compact_sig_has_zero_first_bit(&low_r_sig.0));
1103+
assert!(super::der_length_check(&grind_r_sig.0, 70));
10111104
}
10121105
}
10131106

@@ -1034,8 +1127,12 @@ mod tests {
10341127
for key in wild_keys.iter().map(|k| SecretKey::from_slice(&k[..]).unwrap()) {
10351128
for msg in wild_msgs.iter().map(|m| Message::from_slice(&m[..]).unwrap()) {
10361129
let sig = s.sign(&msg, &key);
1130+
let low_r_sig = s.sign_low_r(&msg, &key);
1131+
let grind_r_sig = s.sign_grind_r(&msg, &key, 1);
10371132
let pk = PublicKey::from_secret_key(&s, &key);
10381133
assert_eq!(s.verify(&msg, &sig, &pk), Ok(()));
1134+
assert_eq!(s.verify(&msg, &low_r_sig, &pk), Ok(()));
1135+
assert_eq!(s.verify(&msg, &grind_r_sig, &pk), Ok(()));
10391136
}
10401137
}
10411138
}
@@ -1095,6 +1192,33 @@ mod tests {
10951192
assert_eq!(secp.verify(&msg, &sig, &pk), Ok(()));
10961193
}
10971194

1195+
#[test]
1196+
fn test_low_r() {
1197+
let secp = Secp256k1::new();
1198+
let msg = hex!("887d04bb1cf1b1554f1b268dfe62d13064ca67ae45348d50d1392ce2d13418ac");
1199+
let msg = Message::from_slice(&msg).unwrap();
1200+
let sk = SecretKey::from_str("57f0148f94d13095cfda539d0da0d1541304b678d8b36e243980aab4e1b7cead").unwrap();
1201+
let expected_sig = hex!("047dd4d049db02b430d24c41c7925b2725bcd5a85393513bdec04b4dc363632b1054d0180094122b380f4cfa391e6296244da773173e78fc745c1b9c79f7b713");
1202+
let expected_sig = Signature::from_compact(&expected_sig).unwrap();
1203+
1204+
let sig = secp.sign_low_r(&msg, &sk);
1205+
1206+
assert_eq!(expected_sig, sig);
1207+
}
1208+
1209+
#[test]
1210+
fn test_grind_r() {
1211+
let secp = Secp256k1::new();
1212+
let msg = hex!("ef2d5b9a7c61865a95941d0f04285420560df7e9d76890ac1b8867b12ce43167");
1213+
let msg = Message::from_slice(&msg).unwrap();
1214+
let sk = SecretKey::from_str("848355d75fe1c354cf05539bb29b2015f1863065bcb6766b44d399ab95c3fa0b").unwrap();
1215+
let expected_sig = Signature::from_str("304302202ffc447100d518c8ba643d11f3e6a83a8640488e7d2537b1954b942408be6ea3021f26e1248dd1e52160c3a38af9769d91a1a806cab5f9d508c103464d3c02d6e1").unwrap();
1216+
1217+
let sig = secp.sign_grind_r(&msg, &sk, 2);
1218+
1219+
assert_eq!(expected_sig, sig);
1220+
}
1221+
10981222
#[cfg(feature = "serde")]
10991223
#[test]
11001224
fn test_signature_serde() {

0 commit comments

Comments
 (0)