public static boolean isEncodingCanonical ( byte [ ] signature ) { // See Bitcoin Core's IsCanonicalSignature, https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623 // A canonical signature exists of: <30> <total len> <02> <len R> <R> <02> <len S> <S> <hashtype> // Where R and S are not negative (their first byte has its 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 necessary and even required). // Empty signatures, while not strictly DER encoded, are allowed. if ( signature . length == 0 ) return true ; if ( signature . length < 9 || signature . length > 73 ) return false ; int hashType = ( signature [ signature . length - 1 ] & 0xff ) & ~ Transaction . SigHash . ANYONECANPAY . value ; // mask the byte to prevent sign-extension hurting us if ( hashType < Transaction . SigHash . ALL . value || hashType > Transaction . SigHash . SINGLE . value ) return false ; // "wrong type" "wrong length marker" if ( ( signature [ 0 ] & 0xff ) != 0x30 || ( signature [ 1 ] & 0xff ) != signature . length - 3 ) return false ; int lenR = signature [ 3 ] & 0xff ; if ( 5 + lenR >= signature . length || lenR == 0 ) return false ; int lenS = signature [ 5 + lenR ] & 0xff ; if ( lenR + lenS + 7 != signature . length || lenS == 0 ) return false ; // R value type mismatch R value negative if ( signature [ 4 - 2 ] != 0x02 || ( signature [ 4 ] & 0x80 ) == 0x80 ) return false ; if ( lenR > 1 && signature [ 4 ] == 0x00 && ( signature [ 4 + 1 ] & 0x80 ) != 0x80 ) return false ; // R value excessively padded // S value type mismatch S value negative if ( signature [ 6 + lenR - 2 ] != 0x02 || ( signature [ 6 + lenR ] & 0x80 ) == 0x80 ) return false ; if ( lenS > 1 && signature [ 6 + lenR ] == 0x00 && ( signature [ 6 + lenR + 1 ] & 0x80 ) != 0x80 ) return false ; // S value excessively padded return true ; }
Returns true if the given signature is has canonical encoding and will thus be accepted as standard by Bitcoin Core . DER and the SIGHASH encoding allow for quite some flexibility in how the same structures are encoded and this can open up novel attacks in which a man in the middle takes a transaction and then changes its signature such that the transaction hash is different but it s still valid . This can confuse wallets and generally violates people s mental model of how Bitcoin should work thus non - canonical signatures are now not relayed by default .