Skip to content

Commit 1d166d0

Browse files
committed
Implement low r signing
1 parent 2917de5 commit 1d166d0

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
@@ -660,6 +660,34 @@ impl<C: Context> Secp256k1<C> {
660660

661661
}
662662

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

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

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

@@ -1029,8 +1122,12 @@ mod tests {
10291122
for key in wild_keys.iter().map(|k| SecretKey::from_slice(&k[..]).unwrap()) {
10301123
for msg in wild_msgs.iter().map(|m| Message::from_slice(&m[..]).unwrap()) {
10311124
let sig = s.sign(&msg, &key);
1125+
let low_r_sig = s.sign_low_r(&msg, &key);
1126+
let grind_r_sig = s.sign_grind_r(&msg, &key, 1);
10321127
let pk = PublicKey::from_secret_key(&s, &key);
10331128
assert_eq!(s.verify(&msg, &sig, &pk), Ok(()));
1129+
assert_eq!(s.verify(&msg, &low_r_sig, &pk), Ok(()));
1130+
assert_eq!(s.verify(&msg, &grind_r_sig, &pk), Ok(()));
10341131
}
10351132
}
10361133
}
@@ -1090,6 +1187,33 @@ mod tests {
10901187
assert_eq!(secp.verify(&msg, &sig, &pk), Ok(()));
10911188
}
10921189

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

0 commit comments

Comments
 (0)