Skip to content

Commit 2115cba

Browse files
committed
Merge #13666: Always create signatures with Low R values
e306be7 Use 72 byte dummy signatures when watching only inputs may be used (Andrew Chow) 48b1473 Use 71 byte signature for DUMMY_SIGNATURE_CREATOR (Andrew Chow) 18dfea0 Always create 70 byte signatures with low R values (Andrew Chow) Pull request description: When creating signatures for transactions, always make one which has a 32 byte or smaller R and 32 byte or smaller S value. This results in signatures that are always less than 71 bytes (32 byte R + 32 byte S + 6 bytes DER + 1 byte sighash) with low R values. In most cases, the signature will be 71 bytes. Because R is not mutable in the same way that S is, a low R value can only be found by trying different nonces. RFC 6979 for deterministic nonce generation has the option to specify additional entropy, so we simply use that and add a uin32_t counter which we increment in order to try different nonces. Nonces are sill deterministically generated as the nonce used will the be the first one where the counter results in a nonce that results in a low R value. Because different nonces need to be tried, time to produce a signature does increase. On average, it takes twice as long to make a signature as two signatures need to be created, on average, to find one with a low R. Having a fixed size signature makes size calculations easier and also saves half a byte of transaction size, on average. DUMMY_SIGNATURE_CREATOR has been modified to produce 71 byte dummy signatures instead of 72 byte signatures. Tree-SHA512: 3cd791505126ce92da7c631856a97ba0b59e87d9c132feff6e0eef1dc47768e81fbb38bfbe970371bedf9714b7f61a13a5fe9f30f962c81734092a4d19a4ef33
2 parents 13d51a2 + e306be7 commit 2115cba

File tree

12 files changed

+118
-62
lines changed

12 files changed

+118
-62
lines changed

src/bench/verify_script.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ static void VerifyScriptBench(benchmark::State& state)
7676
CMutableTransaction txSpend = BuildSpendingTransaction(scriptSig, txCredit);
7777
CScriptWitness& witness = txSpend.vin[0].scriptWitness;
7878
witness.stack.emplace_back();
79-
key.Sign(SignatureHash(witScriptPubkey, txSpend, 0, SIGHASH_ALL, txCredit.vout[0].nValue, SigVersion::WITNESS_V0), witness.stack.back(), 0);
79+
key.Sign(SignatureHash(witScriptPubkey, txSpend, 0, SIGHASH_ALL, txCredit.vout[0].nValue, SigVersion::WITNESS_V0), witness.stack.back());
8080
witness.stack.back().push_back(static_cast<unsigned char>(SIGHASH_ALL));
8181
witness.stack.push_back(ToByteVector(pubkey));
8282

src/key.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,15 +189,35 @@ CPubKey CKey::GetPubKey() const {
189189
return result;
190190
}
191191

192-
bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, uint32_t test_case) const {
192+
// Check that the sig has a low R value and will be less than 71 bytes
193+
bool SigHasLowR(const secp256k1_ecdsa_signature* sig)
194+
{
195+
unsigned char compact_sig[64];
196+
secp256k1_ecdsa_signature_serialize_compact(secp256k1_context_sign, compact_sig, sig);
197+
198+
// In DER serialization, all values are interpreted as big-endian, signed integers. The highest bit in the integer indicates
199+
// its signed-ness; 0 is positive, 1 is negative. When the value is interpreted as a negative integer, it must be converted
200+
// to a positive value by prepending a 0x00 byte so that the highest bit is 0. We can avoid this prepending by ensuring that
201+
// our highest bit is always 0, and thus we must check that the first byte is less than 0x80.
202+
return compact_sig[0] < 0x80;
203+
}
204+
205+
bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, bool grind, uint32_t test_case) const {
193206
if (!fValid)
194207
return false;
195208
vchSig.resize(CPubKey::SIGNATURE_SIZE);
196209
size_t nSigLen = CPubKey::SIGNATURE_SIZE;
197210
unsigned char extra_entropy[32] = {0};
198211
WriteLE32(extra_entropy, test_case);
199212
secp256k1_ecdsa_signature sig;
200-
int ret = secp256k1_ecdsa_sign(secp256k1_context_sign, &sig, hash.begin(), begin(), secp256k1_nonce_function_rfc6979, test_case ? extra_entropy : nullptr);
213+
uint32_t counter = 0;
214+
int ret = secp256k1_ecdsa_sign(secp256k1_context_sign, &sig, hash.begin(), begin(), secp256k1_nonce_function_rfc6979, (!grind && test_case) ? extra_entropy : nullptr);
215+
216+
// Grind for low R
217+
while (ret && !SigHasLowR(&sig) && grind) {
218+
WriteLE32(extra_entropy, ++counter);
219+
ret = secp256k1_ecdsa_sign(secp256k1_context_sign, &sig, hash.begin(), begin(), secp256k1_nonce_function_rfc6979, extra_entropy);
220+
}
201221
assert(ret);
202222
secp256k1_ecdsa_signature_serialize_der(secp256k1_context_sign, vchSig.data(), &nSigLen, &sig);
203223
vchSig.resize(nSigLen);

src/key.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ class CKey
114114
* Create a DER-serialized signature.
115115
* The test_case parameter tweaks the deterministic nonce.
116116
*/
117-
bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig, uint32_t test_case = 0) const;
117+
bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig, bool grind = true, uint32_t test_case = 0) const;
118118

119119
/**
120120
* Create a compact signature (65 bytes), which allows reconstructing the used public key.

src/script/sign.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -417,22 +417,25 @@ class DummySignatureChecker final : public BaseSignatureChecker
417417
const DummySignatureChecker DUMMY_CHECKER;
418418

419419
class DummySignatureCreator final : public BaseSignatureCreator {
420+
private:
421+
char m_r_len = 32;
422+
char m_s_len = 32;
420423
public:
421-
DummySignatureCreator() {}
424+
DummySignatureCreator(char r_len, char s_len) : m_r_len(r_len), m_s_len(s_len) {}
422425
const BaseSignatureChecker& Checker() const override { return DUMMY_CHECKER; }
423426
bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override
424427
{
425428
// Create a dummy signature that is a valid DER-encoding
426-
vchSig.assign(72, '\000');
429+
vchSig.assign(m_r_len + m_s_len + 7, '\000');
427430
vchSig[0] = 0x30;
428-
vchSig[1] = 69;
431+
vchSig[1] = m_r_len + m_s_len + 4;
429432
vchSig[2] = 0x02;
430-
vchSig[3] = 33;
433+
vchSig[3] = m_r_len;
431434
vchSig[4] = 0x01;
432-
vchSig[4 + 33] = 0x02;
433-
vchSig[5 + 33] = 32;
434-
vchSig[6 + 33] = 0x01;
435-
vchSig[6 + 33 + 32] = SIGHASH_ALL;
435+
vchSig[4 + m_r_len] = 0x02;
436+
vchSig[5 + m_r_len] = m_s_len;
437+
vchSig[6 + m_r_len] = 0x01;
438+
vchSig[6 + m_r_len + m_s_len] = SIGHASH_ALL;
436439
return true;
437440
}
438441
};
@@ -450,7 +453,8 @@ bool LookupHelper(const M& map, const K& key, V& value)
450453

451454
}
452455

453-
const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR = DummySignatureCreator();
456+
const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR = DummySignatureCreator(32, 32);
457+
const BaseSignatureCreator& DUMMY_MAXIMUM_SIGNATURE_CREATOR = DummySignatureCreator(33, 32);
454458
const SigningProvider& DUMMY_SIGNING_PROVIDER = SigningProvider();
455459

456460
bool IsSolvable(const SigningProvider& provider, const CScript& script)

src/script/sign.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,10 @@ class MutableTransactionSignatureCreator : public BaseSignatureCreator {
8080
bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override;
8181
};
8282

83-
/** A signature creator that just produces 72-byte empty signatures. */
83+
/** A signature creator that just produces 71-byte empty signatures. */
8484
extern const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR;
85+
/** A signature creator that just produces 72-byte empty signatures. */
86+
extern const BaseSignatureCreator& DUMMY_MAXIMUM_SIGNATURE_CREATOR;
8587

8688
typedef std::pair<CPubKey, std::vector<unsigned char>> SigPair;
8789

src/test/key_tests.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,40 @@ BOOST_AUTO_TEST_CASE(key_test1)
152152
BOOST_CHECK(detsigc == ParseHex("2052d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd561d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d"));
153153
}
154154

155+
BOOST_AUTO_TEST_CASE(key_signature_tests)
156+
{
157+
// When entropy is specified, we should see at least one high R signature within 20 signatures
158+
CKey key = DecodeSecret(strSecret1);
159+
std::string msg = "A message to be signed";
160+
uint256 msg_hash = Hash(msg.begin(), msg.end());
161+
std::vector<unsigned char> sig;
162+
bool found = false;
163+
164+
for (int i = 1; i <=20; ++i) {
165+
sig.clear();
166+
key.Sign(msg_hash, sig, false, i);
167+
found = sig[3] == 0x21 && sig[4] == 0x00;
168+
if (found) {
169+
break;
170+
}
171+
}
172+
BOOST_CHECK(found);
173+
174+
// When entropy is not specified, we should always see low R signatures that are less than 70 bytes in 256 tries
175+
// We should see at least one signature that is less than 70 bytes.
176+
found = true;
177+
bool found_small = false;
178+
for (int i = 0; i < 256; ++i) {
179+
sig.clear();
180+
std::string msg = "A message to be signed" + std::to_string(i);
181+
msg_hash = Hash(msg.begin(), msg.end());
182+
key.Sign(msg_hash, sig);
183+
found = sig[3] == 0x20;
184+
BOOST_CHECK(sig.size() <= 70);
185+
found_small |= sig.size() < 70;
186+
}
187+
BOOST_CHECK(found);
188+
BOOST_CHECK(found_small);
189+
}
190+
155191
BOOST_AUTO_TEST_SUITE_END()

src/test/script_tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ class TestBuilder
369369
std::vector<unsigned char> vchSig, r, s;
370370
uint32_t iter = 0;
371371
do {
372-
key.Sign(hash, vchSig, iter++);
372+
key.Sign(hash, vchSig, false, iter++);
373373
if ((lenS == 33) != (vchSig[5 + vchSig[3]] == 33)) {
374374
NegateSignatureS(vchSig);
375375
}

src/wallet/wallet.cpp

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1542,30 +1542,29 @@ int64_t CWalletTx::GetTxTime() const
15421542
return n ? n : nTimeReceived;
15431543
}
15441544

1545-
// Helper for producing a max-sized low-S signature (eg 72 bytes)
1546-
bool CWallet::DummySignInput(CTxIn &tx_in, const CTxOut &txout) const
1545+
// Helper for producing a max-sized low-S low-R signature (eg 71 bytes)
1546+
// or a max-sized low-S signature (e.g. 72 bytes) if use_max_sig is true
1547+
bool CWallet::DummySignInput(CTxIn &tx_in, const CTxOut &txout, bool use_max_sig) const
15471548
{
15481549
// Fill in dummy signatures for fee calculation.
15491550
const CScript& scriptPubKey = txout.scriptPubKey;
15501551
SignatureData sigdata;
15511552

1552-
if (!ProduceSignature(*this, DUMMY_SIGNATURE_CREATOR, scriptPubKey, sigdata))
1553-
{
1553+
if (!ProduceSignature(*this, use_max_sig ? DUMMY_MAXIMUM_SIGNATURE_CREATOR : DUMMY_SIGNATURE_CREATOR, scriptPubKey, sigdata)) {
15541554
return false;
1555-
} else {
1556-
UpdateInput(tx_in, sigdata);
15571555
}
1556+
UpdateInput(tx_in, sigdata);
15581557
return true;
15591558
}
15601559

1561-
// Helper for producing a bunch of max-sized low-S signatures (eg 72 bytes)
1562-
bool CWallet::DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut> &txouts) const
1560+
// Helper for producing a bunch of max-sized low-S low-R signatures (eg 71 bytes)
1561+
bool CWallet::DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut> &txouts, bool use_max_sig) const
15631562
{
15641563
// Fill in dummy signatures for fee calculation.
15651564
int nIn = 0;
15661565
for (const auto& txout : txouts)
15671566
{
1568-
if (!DummySignInput(txNew.vin[nIn], txout)) {
1567+
if (!DummySignInput(txNew.vin[nIn], txout, use_max_sig)) {
15691568
return false;
15701569
}
15711570

@@ -1574,7 +1573,7 @@ bool CWallet::DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut>
15741573
return true;
15751574
}
15761575

1577-
int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet)
1576+
int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, bool use_max_sig)
15781577
{
15791578
std::vector<CTxOut> txouts;
15801579
// Look up the inputs. We should have already checked that this transaction
@@ -1588,26 +1587,26 @@ int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wall
15881587
assert(input.prevout.n < mi->second.tx->vout.size());
15891588
txouts.emplace_back(mi->second.tx->vout[input.prevout.n]);
15901589
}
1591-
return CalculateMaximumSignedTxSize(tx, wallet, txouts);
1590+
return CalculateMaximumSignedTxSize(tx, wallet, txouts, use_max_sig);
15921591
}
15931592

15941593
// txouts needs to be in the order of tx.vin
1595-
int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts)
1594+
int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts, bool use_max_sig)
15961595
{
15971596
CMutableTransaction txNew(tx);
1598-
if (!wallet->DummySignTx(txNew, txouts)) {
1597+
if (!wallet->DummySignTx(txNew, txouts, use_max_sig)) {
15991598
// This should never happen, because IsAllFromMe(ISMINE_SPENDABLE)
16001599
// implies that we can sign for every input.
16011600
return -1;
16021601
}
16031602
return GetVirtualTransactionSize(txNew);
16041603
}
16051604

1606-
int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* wallet)
1605+
int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* wallet, bool use_max_sig)
16071606
{
16081607
CMutableTransaction txn;
16091608
txn.vin.push_back(CTxIn(COutPoint()));
1610-
if (!wallet->DummySignInput(txn.vin[0], txout)) {
1609+
if (!wallet->DummySignInput(txn.vin[0], txout, use_max_sig)) {
16111610
// This should never happen, because IsAllFromMe(ISMINE_SPENDABLE)
16121611
// implies that we can sign for every input.
16131612
return -1;
@@ -2334,7 +2333,7 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
23342333
bool solvable = IsSolvable(*this, pcoin->tx->vout[i].scriptPubKey);
23352334
bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable));
23362335

2337-
vCoins.push_back(COutput(pcoin, i, nDepth, spendable, solvable, safeTx));
2336+
vCoins.push_back(COutput(pcoin, i, nDepth, spendable, solvable, safeTx, (coinControl && coinControl->fAllowWatchOnly)));
23382337

23392338
// Checks the sum amount of all UTXO's.
23402339
if (nMinimumSumAmount != MAX_MONEY) {
@@ -2889,7 +2888,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
28892888
txNew.vin.push_back(CTxIn(coin.outpoint,CScript()));
28902889
}
28912890

2892-
nBytes = CalculateMaximumSignedTxSize(txNew, this);
2891+
nBytes = CalculateMaximumSignedTxSize(txNew, this, coin_control.fAllowWatchOnly);
28932892
if (nBytes < 0) {
28942893
strFailReason = _("Signing transaction failed");
28952894
return false;

src/wallet/wallet.h

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ class CMerkleTx
276276
};
277277

278278
//Get the marginal bytes of spending the specified output
279-
int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* pwallet);
279+
int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* pwallet, bool use_max_sig = false);
280280

281281
/**
282282
* A transaction with a bunch of additional info that only the owner cares about.
@@ -461,9 +461,9 @@ class CWalletTx : public CMerkleTx
461461
CAmount GetChange() const;
462462

463463
// Get the marginal bytes if spending the specified output from this transaction
464-
int GetSpendSize(unsigned int out) const
464+
int GetSpendSize(unsigned int out, bool use_max_sig = false) const
465465
{
466-
return CalculateMaximumSignedInputSize(tx->vout[out], pwallet);
466+
return CalculateMaximumSignedInputSize(tx->vout[out], pwallet, use_max_sig);
467467
}
468468

469469
void GetAmounts(std::list<COutputEntry>& listReceived,
@@ -507,20 +507,23 @@ class COutput
507507
/** Whether we know how to spend this output, ignoring the lack of keys */
508508
bool fSolvable;
509509

510+
/** Whether to use the maximum sized, 72 byte signature when calculating the size of the input spend. This should only be set when watch-only outputs are allowed */
511+
bool use_max_sig;
512+
510513
/**
511514
* Whether this output is considered safe to spend. Unconfirmed transactions
512515
* from outside keys and unconfirmed replacement transactions are considered
513516
* unsafe and will not be used to fund new spending transactions.
514517
*/
515518
bool fSafe;
516519

517-
COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn, bool fSolvableIn, bool fSafeIn)
520+
COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn, bool fSolvableIn, bool fSafeIn, bool use_max_sig_in = false)
518521
{
519-
tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn; fSolvable = fSolvableIn; fSafe = fSafeIn; nInputBytes = -1;
522+
tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn; fSolvable = fSolvableIn; fSafe = fSafeIn; nInputBytes = -1; use_max_sig = use_max_sig_in;
520523
// If known and signable by the given wallet, compute nInputBytes
521524
// Failure will keep this value -1
522525
if (fSpendable && tx) {
523-
nInputBytes = tx->GetSpendSize(i);
526+
nInputBytes = tx->GetSpendSize(i, use_max_sig);
524527
}
525528
}
526529

@@ -976,14 +979,14 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
976979
void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& entries);
977980
bool AddAccountingEntry(const CAccountingEntry&);
978981
bool AddAccountingEntry(const CAccountingEntry&, WalletBatch *batch);
979-
bool DummySignTx(CMutableTransaction &txNew, const std::set<CTxOut> &txouts) const
982+
bool DummySignTx(CMutableTransaction &txNew, const std::set<CTxOut> &txouts, bool use_max_sig = false) const
980983
{
981984
std::vector<CTxOut> v_txouts(txouts.size());
982985
std::copy(txouts.begin(), txouts.end(), v_txouts.begin());
983-
return DummySignTx(txNew, v_txouts);
986+
return DummySignTx(txNew, v_txouts, use_max_sig);
984987
}
985-
bool DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut> &txouts) const;
986-
bool DummySignInput(CTxIn &tx_in, const CTxOut &txout) const;
988+
bool DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut> &txouts, bool use_max_sig = false) const;
989+
bool DummySignInput(CTxIn &tx_in, const CTxOut &txout, bool use_max_sig = false) const;
987990

988991
CFeeRate m_pay_tx_fee{DEFAULT_PAY_TX_FEE};
989992
unsigned int m_confirm_target{DEFAULT_TX_CONFIRM_TARGET};
@@ -1308,9 +1311,9 @@ class WalletRescanReserver
13081311
};
13091312

13101313
// Calculate the size of the transaction assuming all signatures are max size
1311-
// Use DummySignatureCreator, which inserts 72 byte signatures everywhere.
1314+
// Use DummySignatureCreator, which inserts 71 byte signatures everywhere.
13121315
// NOTE: this requires that all inputs must be in mapWallet (eg the tx should
13131316
// be IsAllFromMe).
1314-
int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet);
1315-
int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts);
1317+
int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, bool use_max_sig = false);
1318+
int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts, bool use_max_sig = false);
13161319
#endif // BITCOIN_WALLET_WALLET_H

0 commit comments

Comments
 (0)