BIP: 66 Layer: Consensus (soft fork) Title: Strict DER signatures Author: Pieter WuilleComments-Summary: No comments yet. Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0066 Status: Final Type: Standards Track Created: 2015-01-10 License: BSD-2-Clause
One specifically critical area is the encoding of signatures. Until recently, OpenSSL's releases would accept various deviations from the DER standard and accept signatures as valid. When this changed in OpenSSL 1.0.0p and 1.0.1k, it made some nodes reject the chain.
This document proposes to restrict valid signatures to exactly what is mandated by DER, to make the consensus rules not depend on OpenSSL's signature parsing. A change like this is required if implementations would want to remove all of OpenSSL from the consensus code.
These operators all perform ECDSA verifications on pubkey/signature pairs, iterating from the top of the stack backwards. For each such verification, if the signature does not pass the IsValidSignatureEncoding check below, the entire script evaluates to false immediately. If the signature is valid DER, but does not pass ECDSA verification, opcode execution continues as it used to, causing opcode execution to stop and push false on the stack (but not immediately fail the script) in some cases, which potentially skips further signatures (and thus does not subject them to IsValidSignatureEncoding).
bool static IsValidSignatureEncoding(const std::vector&sig) { // Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S] [sighash] // * total-length: 1-byte length descriptor of everything that follows, // excluding the sighash byte. // * R-length: 1-byte length descriptor of the R value that follows. // * R: arbitrary-length big-endian encoded R value. It must use the 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 highest bit set). // * S-length: 1-byte length descriptor of the S value that follows. // * 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. if (sig.size() < 9) return false; if (sig.size() > 73) return false;
// A signature is of type 0x30 (compound). if (sig[0] != 0x30) return false;
// Make sure the length covers the entire signature. if (sig[1] != sig.size() - 3) return false;
// Extract the length of the R element. unsigned int lenR = sig[3];
// Make sure the length of the S element is still inside the signature. 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 whether the R element is an integer. if (sig[2] != 0x02) return false;
// Zero-length integers are not allowed for R. if (lenR == 0) return false;
// Negative numbers are not allowed for R. if (sig[4] & 0x80) return false;
// Null bytes at the start of R are not allowed, unless R would // otherwise be interpreted as a negative number. if (lenR > 1 && (sig[4] == 0x00) && !(sig[5] & 0x80)) return false;
// Check whether the S element is an integer. if (sig[lenR 4] != 0x02) return false;
// Zero-length integers are not allowed for S. if (lenS == 0) return false;
// Negative numbers are not allowed for S. if (sig[lenR 6] & 0x80) return false;
// Null bytes at the start of S are not allowed, unless S would otherwise be // interpreted as a negative number. if (lenS > 1 && (sig[lenR 6] == 0x00) && !(sig[lenR 7] & 0x80)) return false;
return true;}
Note that the examples above show that only additional failures are required by this change, as required for a soft forking change.