Browse Source

Make empty byte arrays pass CheckSignatureEncoding()

Makes it possible to compactly provide a delibrately invalid signature
for use with CHECK(MULTI)SIG. For instance with BIP19 if m != n invalid
signatures need to be provided in the scriptSig; prior to this change
those invalid signatures would need to be large DER-encoded signatures.

Note that we may want to further expand on this change in the future by
saying that only OP_0 is a "valid" invalid signature; BIP19 even with
this change is inherently malleable as the invalid signatures can be any
validly encoded DER signature.
0.13
Peter Todd 10 years ago
parent
commit
2fa9a8ec86
No known key found for this signature in database
GPG Key ID: 2481403DA5F091FB
  1. 5
      src/script/interpreter.cpp
  2. 2
      src/test/data/script_invalid.json
  3. 5
      src/test/data/script_valid.json
  4. 4
      src/test/multisig_tests.cpp

5
src/script/interpreter.cpp

@ -189,6 +189,11 @@ bool static IsDefinedHashtypeSignature(const valtype &vchSig) {
} }
bool static CheckSignatureEncoding(const valtype &vchSig, unsigned int flags, ScriptError* serror) { bool static CheckSignatureEncoding(const valtype &vchSig, unsigned int flags, ScriptError* serror) {
// Empty signature. Not strictly DER encoded, but allowed to provide a
// compact way to provide an invalid signature for use with CHECK(MULTI)SIG
if (vchSig.size() == 0) {
return true;
}
if ((flags & (SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC)) != 0 && !IsDERSignature(vchSig)) { if ((flags & (SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC)) != 0 && !IsDERSignature(vchSig)) {
return set_error(serror, SCRIPT_ERR_SIG_DER); return set_error(serror, SCRIPT_ERR_SIG_DER);
} else if ((flags & SCRIPT_VERIFY_LOW_S) != 0 && !IsLowDERSignature(vchSig, serror)) { } else if ((flags & SCRIPT_VERIFY_LOW_S) != 0 && !IsLowDERSignature(vchSig, serror)) {

2
src/test/data/script_invalid.json

@ -504,7 +504,7 @@
"2-of-2 CHECKMULTISIG NOT with the first pubkey invalid, and both signatures validly encoded." "2-of-2 CHECKMULTISIG NOT with the first pubkey invalid, and both signatures validly encoded."
], ],
[ [
"0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0", "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 1",
"2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT", "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT",
"STRICTENC", "STRICTENC",
"2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but first signature invalid." "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but first signature invalid."

5
src/test/data/script_valid.json

@ -662,6 +662,11 @@
["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", ""], ["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", ""],
["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", ""], ["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", ""],
["While not really correctly DER encoded, the empty signature is allowed by"],
["STRICTENC to provide a compact way to provide a delibrately invalid signature."],
["0", "0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 CHECKSIG NOT", "STRICTENC"],
["0 0", "1 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 1 CHECKMULTISIG NOT", "STRICTENC"],
["CHECKMULTISIG evaluation order tests. CHECKMULTISIG evaluates signatures and"], ["CHECKMULTISIG evaluation order tests. CHECKMULTISIG evaluates signatures and"],
["pubkeys in a specific order, and will exit early if the number of signatures"], ["pubkeys in a specific order, and will exit early if the number of signatures"],
["left to check is greater than the number of keys left. As STRICTENC fails the"], ["left to check is greater than the number of keys left. As STRICTENC fails the"],

4
src/test/multisig_tests.cpp

@ -116,10 +116,6 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
} }
} }
s.clear(); s.clear();
s << OP_0 << OP_0;
BOOST_CHECK(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));
s.clear();
s << OP_0 << OP_1; s << OP_0 << OP_1;
BOOST_CHECK(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0), &err)); BOOST_CHECK(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));

Loading…
Cancel
Save