test: refactor: negate signature-s using libsecp256k1

Co-authored-by: laanwj <126646+laanwj@users.noreply.github.com>
This commit is contained in:
Sebastian Falbesoner
2025-05-07 12:21:18 +02:00
parent 59d3e4ed34
commit 1ee698fde2

View File

@@ -30,6 +30,7 @@
#include <boost/test/unit_test.hpp>
#include <secp256k1.h>
#include <univalue.h>
// Uncomment if you want to output updated JSON tests.
@@ -144,25 +145,17 @@ void static NegateSignatureS(std::vector<unsigned char>& vchSig) {
r = std::vector<unsigned char>(vchSig.begin() + 4, vchSig.begin() + 4 + vchSig[3]);
s = std::vector<unsigned char>(vchSig.begin() + 6 + vchSig[3], vchSig.begin() + 6 + vchSig[3] + vchSig[5 + vchSig[3]]);
// Really ugly to implement mod-n negation here, but it would be feature creep to expose such functionality from libsecp256k1.
static const unsigned char order[33] = {
0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41
};
while (s.size() < 33) {
s.insert(s.begin(), 0x00);
}
int carry = 0;
for (int p = 32; p >= 1; p--) {
int n = (int)order[p] - s[p] - carry;
s[p] = (n + 256) & 0xFF;
carry = (n < 0);
}
assert(carry == 0);
if (s.size() > 1 && s[0] == 0 && s[1] < 0x80) {
assert(s[0] == 0);
// Perform mod-n negation of s by (ab)using libsecp256k1
// (note that this function is meant to be used for negating secret keys,
// but it works for any non-zero scalar modulo the group order, i.e. also for s)
int ret = secp256k1_ec_seckey_negate(secp256k1_context_static, s.data() + 1);
assert(ret);
if (s[1] < 0x80) {
s.erase(s.begin());
}