aboutsummaryrefslogtreecommitdiff
path: root/test/functional/test_framework
diff options
context:
space:
mode:
authorPieter Wuille <pieter@wuille.net>2021-10-27 15:46:03 -0400
committerPieter Wuille <pieter@wuille.net>2021-11-12 12:04:20 -0500
commitca83ffc2ea5fe08f16fff7df71c040d067f2afb0 (patch)
tree803e6de3f7b48b54e4e608482f7124d49a7e79fa /test/functional/test_framework
parentc98c53f20cadeda53f6a9323f72363593d174f68 (diff)
downloadbitcoin-ca83ffc2ea5fe08f16fff7df71c040d067f2afb0.tar.xz
tests: add deterministic signing mode to ECDSA
This does the following: * Adds a rfc6979 argument to test_framework/key.py's sign_ecdsa to select (deterministic) RFC6979-based nonce generation. * Add a flag in feature_taproot.py's framework called "deterministic". * Make the Schnorr signing in feature_taproot.py randomized by default, reverting to the old deterministic (aux_rnd=0x0000...00) behavior if the deterministic context flag is set. * Make the ECDSA signing in feature_taproot.py use RFC6979-based nonces when the deterministic context flag is set (keeping the old randomized behavior otherwise).
Diffstat (limited to 'test/functional/test_framework')
-rw-r--r--test/functional/test_framework/key.py20
1 files changed, 17 insertions, 3 deletions
diff --git a/test/functional/test_framework/key.py b/test/functional/test_framework/key.py
index 26526e35fa..e5dea66963 100644
--- a/test/functional/test_framework/key.py
+++ b/test/functional/test_framework/key.py
@@ -8,6 +8,7 @@ keys, and is trivially vulnerable to side channel attacks. Do not use for
anything but tests."""
import csv
import hashlib
+import hmac
import os
import random
import unittest
@@ -326,6 +327,16 @@ def generate_privkey():
"""Generate a valid random 32-byte private key."""
return random.randrange(1, SECP256K1_ORDER).to_bytes(32, 'big')
+def rfc6979_nonce(key):
+ """Compute signing nonce using RFC6979."""
+ v = bytes([1] * 32)
+ k = bytes([0] * 32)
+ k = hmac.new(k, v + b"\x00" + key, 'sha256').digest()
+ v = hmac.new(k, v, 'sha256').digest()
+ k = hmac.new(k, v + b"\x01" + key, 'sha256').digest()
+ v = hmac.new(k, v, 'sha256').digest()
+ return hmac.new(k, v, 'sha256').digest()
+
class ECKey():
"""A secp256k1 private key"""
@@ -368,15 +379,18 @@ class ECKey():
ret.compressed = self.compressed
return ret
- def sign_ecdsa(self, msg, low_s=True):
+ def sign_ecdsa(self, msg, low_s=True, rfc6979=False):
"""Construct a DER-encoded ECDSA signature with this key.
See https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm for the
ECDSA signer algorithm."""
assert(self.valid)
z = int.from_bytes(msg, 'big')
- # Note: no RFC6979, but a simple random nonce (some tests rely on distinct transactions for the same operation)
- k = random.randrange(1, SECP256K1_ORDER)
+ # Note: no RFC6979 by default, but a simple random nonce (some tests rely on distinct transactions for the same operation)
+ if rfc6979:
+ k = int.from_bytes(rfc6979_nonce(self.secret.to_bytes(32, 'big') + msg), 'big')
+ else:
+ k = random.randrange(1, SECP256K1_ORDER)
R = SECP256K1.affine(SECP256K1.mul([(SECP256K1_G, k)]))
r = R[0] % SECP256K1_ORDER
s = (modinv(k, SECP256K1_ORDER) * (z + self.secret * r)) % SECP256K1_ORDER