Changeset View
Changeset View
Standalone View
Standalone View
src/script/sigencoding.cpp
Show All 16 Lines | |||||
* highest bit not set), and not excessively padded (do not start with a 0 byte, | * highest bit not set), and not excessively padded (do not start with a 0 byte, | ||||
* unless an otherwise negative number follows, in which case a single 0 byte is | * unless an otherwise negative number follows, in which case a single 0 byte is | ||||
* necessary and even required). | * necessary and even required). | ||||
* | * | ||||
* See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623 | * See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623 | ||||
* | * | ||||
* This function is consensus-critical since BIP66. | * This function is consensus-critical since BIP66. | ||||
*/ | */ | ||||
static bool IsValidSignatureEncoding(const valtype &sig) { | static bool | ||||
IsValidSignatureEncoding(const boost::sliced_range<const valtype> &sig) { | |||||
// Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S] | // Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S] | ||||
// [sighash] | |||||
// * total-length: 1-byte length descriptor of everything that follows, | // * total-length: 1-byte length descriptor of everything that follows, | ||||
// excluding the sighash byte. | // excluding the sighash byte. | ||||
// * R-length: 1-byte length descriptor of the R value that follows. | // * R-length: 1-byte length descriptor of the R value that follows. | ||||
// * R: arbitrary-length big-endian encoded R value. It must use the | // * R: arbitrary-length big-endian encoded R value. It must use the | ||||
// shortest possible encoding for a positive integers (which means no null | // shortest possible encoding for a positive integers (which means no null | ||||
// bytes at the start, except a single one when the next byte has its | // bytes at the start, except a single one when the next byte has its | ||||
// highest bit set). | // highest bit set). | ||||
// * S-length: 1-byte length descriptor of the S value that follows. | // * S-length: 1-byte length descriptor of the S value that follows. | ||||
// * S: arbitrary-length big-endian encoded S value. The same rules apply. | // * S: arbitrary-length big-endian encoded S value. The same rules apply. | ||||
// * sighash: 1-byte value indicating what data is hashed (not part of the | |||||
// DER signature) | |||||
// Minimum and maximum size constraints. | // Minimum and maximum size constraints. | ||||
if (sig.size() < 9 || sig.size() > 73) { | if (sig.size() < 8 || sig.size() > 72) { | ||||
return false; | return false; | ||||
} | } | ||||
// | // | ||||
// Check that the signature is a coumpound structure of proper size. | // Check that the signature is a coumpound structure of proper size. | ||||
// | // | ||||
// A signature is of type 0x30 (compound). | // A signature is of type 0x30 (compound). | ||||
if (sig[0] != 0x30) { | if (sig[0] != 0x30) { | ||||
return false; | return false; | ||||
} | } | ||||
// Make sure the length covers the entire signature. | // Make sure the length covers the entire signature. | ||||
// Remove: | // Remove: | ||||
// * 1 byte for the coupound type. | // * 1 byte for the coupound type. | ||||
// * 1 byte for the length of the signature. | // * 1 byte for the length of the signature. | ||||
// * 1 byte for the sighash type. | if (sig[1] != sig.size() - 2) { | ||||
if (sig[1] != sig.size() - 3) { | |||||
return false; | return false; | ||||
} | } | ||||
// | // | ||||
// Check that R is an positive integer of sensible size. | // Check that R is an positive integer of sensible size. | ||||
// | // | ||||
// Check whether the R element is an integer. | // Check whether the R element is an integer. | ||||
Show All 17 Lines | IsValidSignatureEncoding(const boost::sliced_range<const valtype> &sig) { | ||||
// Make sure the length of the R element is consistent with the signature | // Make sure the length of the R element is consistent with the signature | ||||
// size. | // size. | ||||
// Remove: | // Remove: | ||||
// * 1 byte for the coumpound type. | // * 1 byte for the coumpound type. | ||||
// * 1 byte for the length of the signature. | // * 1 byte for the length of the signature. | ||||
// * 2 bytes for the integer type of R and S. | // * 2 bytes for the integer type of R and S. | ||||
// * 2 bytes for the size of R and S. | // * 2 bytes for the size of R and S. | ||||
// * 1 byte for S itself. | // * 1 byte for S itself. | ||||
// * 1 byte for the sighash type. | if (lenR > (sig.size() - 7)) { | ||||
if (lenR > (sig.size() - 8)) { | |||||
return false; | return false; | ||||
} | } | ||||
// Null bytes at the start of R are not allowed, unless R would otherwise be | // Null bytes at the start of R are not allowed, unless R would otherwise be | ||||
// interpreted as a negative number. | // interpreted as a negative number. | ||||
// | // | ||||
// /!\ This check can only be performed after we checked that lenR is | // /!\ This check can only be performed after we checked that lenR is | ||||
// consistent with the size of the signature or we risk to access out of | // consistent with the size of the signature or we risk to access out of | ||||
Show All 31 Lines | IsValidSignatureEncoding(const boost::sliced_range<const valtype> &sig) { | ||||
if (sig[startS + 2] & 0x80) { | if (sig[startS + 2] & 0x80) { | ||||
return false; | return false; | ||||
} | } | ||||
// Verify that the length of S is consistent with the size of the signature | // Verify that the length of S is consistent with the size of the signature | ||||
// including metadatas: | // including metadatas: | ||||
// * 1 byte for the integer type of S. | // * 1 byte for the integer type of S. | ||||
// * 1 byte for the size of S. | // * 1 byte for the size of S. | ||||
// * 1 byte for the sighash type. | if (size_t(startS + lenS + 2) != sig.size()) { | ||||
if (size_t(startS + lenS + 3) != sig.size()) { | |||||
return false; | return false; | ||||
} | } | ||||
// Null bytes at the start of S are not allowed, unless S would otherwise be | // Null bytes at the start of S are not allowed, unless S would otherwise be | ||||
// interpreted as a negative number. | // interpreted as a negative number. | ||||
// | // | ||||
// /!\ This check can only be performed after we checked that lenR and lenS | // /!\ This check can only be performed after we checked that lenR and lenS | ||||
// are consistent with the size of the signature or we risk to access | // are consistent with the size of the signature or we risk to access | ||||
Show All 18 Lines | bool CheckSignatureEncoding(const valtype &vchSig, uint32_t flags, | ||||
ScriptError *serror) { | ScriptError *serror) { | ||||
// Empty signature. Not strictly DER encoded, but allowed to provide a | // Empty signature. Not strictly DER encoded, but allowed to provide a | ||||
// compact way to provide an invalid signature for use with CHECK(MULTI)SIG | // compact way to provide an invalid signature for use with CHECK(MULTI)SIG | ||||
if (vchSig.size() == 0) { | if (vchSig.size() == 0) { | ||||
return true; | return true; | ||||
} | } | ||||
if ((flags & (SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | | if ((flags & (SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | | ||||
SCRIPT_VERIFY_STRICTENC)) != 0 && | SCRIPT_VERIFY_STRICTENC)) != 0 && | ||||
!IsValidSignatureEncoding(vchSig)) { | !IsValidSignatureEncoding( | ||||
vchSig | boost::adaptors::sliced(0, vchSig.size() - 1))) { | |||||
return set_error(serror, SCRIPT_ERR_SIG_DER); | return set_error(serror, SCRIPT_ERR_SIG_DER); | ||||
} | } | ||||
if ((flags & SCRIPT_VERIFY_LOW_S) != 0 && | if ((flags & SCRIPT_VERIFY_LOW_S) != 0 && | ||||
!IsLowDERSignature(vchSig, serror)) { | !IsLowDERSignature(vchSig, serror)) { | ||||
// serror is set | // serror is set | ||||
return false; | return false; | ||||
} | } | ||||
if ((flags & SCRIPT_VERIFY_STRICTENC) != 0) { | if ((flags & SCRIPT_VERIFY_STRICTENC) != 0) { | ||||
▲ Show 20 Lines • Show All 57 Lines • Show Last 20 Lines |