isTxDER static method
ported from moneybutton/bsv
This function is translated from bitcoind's IsDERSignature and is used in
the script interpreter. This 'DER' format actually includes an extra byte,
the nhashtype, at the end. It is really the tx format, not DER format.
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).
See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623
Implementation
static bool isTxDER(String buffer) {
List<int> buf;
try {
buf = HEX.decode(buffer);
} catch (ex) {
return false;
}
if (buf.length < 9) {
// Non-canonical signature: too short
return false;
}
if (buf.length > 73) {
// Non-canonical signature: too long
return false;
}
if (buf[0] != 0x30) {
// Non-canonical signature: wrong type
return false;
}
if (buf[1] != buf.length - 3) {
// Non-canonical signature: wrong length marker
return false;
}
var nLenR = buf[3];
if (5 + nLenR >= buf.length) {
// Non-canonical signature: S length misplaced
return false;
}
var nLenS = buf[5 + nLenR];
if ((nLenR + nLenS + 7) != buf.length) {
// Non-canonical signature: R+S length mismatch
return false;
}
var R = buf.sublist(4, buf.length);
if (buf[4 - 2] != 0x02) {
// Non-canonical signature: R value type mismatch
return false;
}
if (nLenR == 0) {
// Non-canonical signature: R length is zero
return false;
}
if (R[0] & 0x80 != 0) {
// Non-canonical signature: R value negative
return false;
}
if (nLenR > 1 && (R[0] == 0x00) && !(R[1] & 0x80 != 0)) {
// Non-canonical signature: R value excessively padded
return false;
}
var S = buf.sublist(6 + nLenR, buf.length);
if (buf[6 + nLenR - 2] != 0x02) {
// Non-canonical signature: S value type mismatch
return false;
}
if (nLenS == 0) {
// Non-canonical signature: S length is zero
return false;
}
if (S[0] & 0x80 != 0) {
// Non-canonical signature: S value negative
return false;
}
if (nLenS > 1 && (S[0] == 0x00) && !(S[1] & 0x80 != 0)) {
// Non-canonical signature: S value excessively padded
return false;
}
return true;
}