Changeset View
Changeset View
Standalone View
Standalone View
src/script/sigencoding.cpp
Show All 32 Lines | static bool IsValidSignatureEncoding(const valtype &sig) { | ||||
// 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 | // * sighash: 1-byte value indicating what data is hashed (not part of the | ||||
// DER signature) | // DER signature) | ||||
// Minimum and maximum size constraints. | // Minimum and maximum size constraints. | ||||
if (sig.size() < 9) return false; | if (sig.size() < 9 || sig.size() > 73) { | ||||
if (sig.size() > 73) return false; | return false; | ||||
} | |||||
// | |||||
// 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) return false; | if (sig[0] != 0x30) { | ||||
return false; | |||||
} | |||||
// Make sure the length covers the entire signature. | // Make sure the length covers the entire signature. | ||||
if (sig[1] != sig.size() - 3) return false; | // Remove: | ||||
// * 1 byte for the coupound type. | |||||
// Extract the length of the R element. | // * 1 byte for the length of the signature. | ||||
unsigned int lenR = sig[3]; | // * 1 byte for the sighash type. | ||||
if (sig[1] != sig.size() - 3) { | |||||
// Make sure the length of the S element is still inside the signature. | return false; | ||||
if (5 + lenR >= sig.size()) return false; | } | ||||
// Extract the length of the S element. | |||||
unsigned int lenS = sig[5 + lenR]; | |||||
// Verify that the length of the signature matches the sum of the length | // | ||||
// of the elements. | // Check that R is an positive integer of sensible size. | ||||
if (size_t(lenR + lenS + 7) != sig.size()) return false; | // | ||||
// Check whether the R element is an integer. | // Check whether the R element is an integer. | ||||
if (sig[2] != 0x02) return false; | if (sig[2] != 0x02) { | ||||
return false; | |||||
} | |||||
// Extract the length of the R element. | |||||
const uint32_t lenR = sig[3]; | |||||
// Zero-length integers are not allowed for R. | // Zero-length integers are not allowed for R. | ||||
if (lenR == 0) return false; | if (lenR == 0) { | ||||
return false; | |||||
} | |||||
// Negative numbers are not allowed for R. | // Negative numbers are not allowed for R. | ||||
if (sig[4] & 0x80) return false; | if (sig[4] & 0x80) { | ||||
return false; | |||||
} | |||||
// Make sure the length of the R element is consistent with the signature | |||||
// size. | |||||
// Remove: | |||||
// * 1 byte for the coumpound type. | |||||
// * 1 byte for the length of the signature. | |||||
// * 2 bytes for the integer type of R and S. | |||||
// * 2 bytes for the size of R and S. | |||||
// * 1 byte for S itself. | |||||
// * 1 byte for the sighash type. | |||||
if (lenR > (sig.size() - 8)) { | |||||
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. | ||||
if (lenR > 1 && (sig[4] == 0x00) && !(sig[5] & 0x80)) return false; | // | ||||
// /!\ 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 | |||||
// bound elements. | |||||
if (lenR > 1 && (sig[4] == 0x00) && !(sig[5] & 0x80)) { | |||||
return false; | |||||
} | |||||
// | |||||
// Check that S is an positive integer of sensible size. | |||||
// | |||||
// S's definition starts after R's definition: | |||||
// * 1 byte for the coumpound type. | |||||
// * 1 byte for the length of the signature. | |||||
// * 1 byte for the size of R. | |||||
// * lenR bytes for R itself. | |||||
// * 1 byte to get to S. | |||||
const uint32_t startS = lenR + 4; | |||||
// Check whether the S element is an integer. | // Check whether the S element is an integer. | ||||
if (sig[lenR + 4] != 0x02) return false; | if (sig[startS] != 0x02) { | ||||
return false; | |||||
} | |||||
// Extract the length of the S element. | |||||
const uint32_t lenS = sig[startS + 1]; | |||||
// Zero-length integers are not allowed for S. | // Zero-length integers are not allowed for S. | ||||
if (lenS == 0) return false; | if (lenS == 0) { | ||||
return false; | |||||
} | |||||
// Negative numbers are not allowed for S. | // Negative numbers are not allowed for S. | ||||
if (sig[lenR + 6] & 0x80) return false; | if (sig[startS + 2] & 0x80) { | ||||
return false; | |||||
} | |||||
// Verify that the length of S is consistent with the size of the signature | |||||
// including metadatas: | |||||
// * 1 byte for the integer type of S. | |||||
// * 1 byte for the size of S. | |||||
// * 1 byte for the sighash type. | |||||
if (size_t(startS + lenS + 3) != sig.size()) { | |||||
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. | ||||
if (lenS > 1 && (sig[lenR + 6] == 0x00) && !(sig[lenR + 7] & 0x80)) { | // | ||||
// /!\ 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 | |||||
// out of bound elements. | |||||
if (lenS > 1 && (sig[startS + 2] == 0x00) && !(sig[startS + 3] & 0x80)) { | |||||
return false; | return false; | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
static bool IsLowDERSignature(const valtype &vchSig, ScriptError *serror) { | static bool IsLowDERSignature(const valtype &vchSig, ScriptError *serror) { | ||||
assert(vchSig.size() > 0); | assert(vchSig.size() > 0); | ||||
▲ Show 20 Lines • Show All 82 Lines • Show Last 20 Lines |