Changeset View
Changeset View
Standalone View
Standalone View
src/script/sigencoding.cpp
Show All 30 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 of proper size. | |||||
jasonbcox: A compound what? | |||||
deadalnixAuthorUnsubmitted Not Done Inline Actionsdeadalnix: http://luca.ntop.org/Teaching/Appunti/asn1.html | |||||
jasonbcoxUnsubmitted Not Done Inline ActionsBetter explanation: https://bitcoin.stackexchange.com/questions/12554/why-the-signature-is-always-65-13232-bytes-long jasonbcox: Better explanation: https://bitcoin.stackexchange.com/questions/12554/why-the-signature-is… | |||||
*/ | |||||
// A signature is of type 0x30 (compound). | // A signature is of type 0x30 (compound). | ||||
jasonbcoxUnsubmitted Not Done Inline ActionsMerge with this comment so we don't have mixed comment styles jasonbcox: Merge with this comment so we don't have mixed comment styles | |||||
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: | ||||
jasonbcoxUnsubmitted Not Done Inline ActionsMake doxygen-style and explain not just what is being removed, but what sig[1] represents such that this comparison makes sense. jasonbcox: Make doxygen-style and explain not just what is being removed, but what sig[1] represents such… | |||||
// * 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. | |||||
if (size_t(lenR + lenS + 7) != sig.size()) return false; | |||||
/** | |||||
* 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. | ||||
jasonbcoxUnsubmitted Not Done Inline ActionsMixed comment styles jasonbcox: Mixed comment styles | |||||
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 S element is still inside the signature. | |||||
jasonbcoxUnsubmitted Not Done Inline ActionsDoxygen-style jasonbcox: Doxygen-style | |||||
// 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 | |||||
jasonbcoxUnsubmitted Not Done Inline ActionsDoxygen-style jasonbcox: Doxygen-style | |||||
// consistent with the size of the signature or we risk to access our of | |||||
jasonbcoxUnsubmitted Not Done Inline Actionsour -> out jasonbcox: our -> out | |||||
// 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: | |||||
jasonbcoxUnsubmitted Not Done Inline ActionsMixed comment styles jasonbcox: Mixed comment styles | |||||
// * 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 | |||||
jasonbcoxUnsubmitted Not Done Inline ActionsDoxygen-style jasonbcox: Doxygen-style | |||||
// 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 | |||||
jasonbcoxUnsubmitted Not Done Inline ActionsDoxygen-style jasonbcox: Doxygen-style | |||||
// are consistent with the size of the signature or we risk to access | |||||
// our of bound elements. | |||||
jasonbcoxUnsubmitted Not Done Inline Actionsour -> out jasonbcox: our -> out | |||||
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) { | ||||
if (!IsValidSignatureEncoding(vchSig)) { | if (!IsValidSignatureEncoding(vchSig)) { | ||||
▲ Show 20 Lines • Show All 91 Lines • Show Last 20 Lines |
A compound what?