nextMPInt method
Extracts a multiple precision integer from the range.
Extracts an uint32 which indicates the number of following bytes to be interpreted as a two's complement integer. See section 5 of RFC 4251 for a definition of this format.
Returns the integer value. The bytes making up the length and integer are removed from the range.
Throws a BadEncoding if there are insufficient bytes in the range or the bytes do not represent a valid multiple precision integer.
Implementation
BigInt nextMPInt() {
final length = nextUint32();
// mpint
// Represents multiple precision integers in two's complement format,
// stored as a string, 8 bits per byte, MSB first. Negative numbers
// have the value 1 as the most significant bit of the first byte of
// the data partition. If the most significant bit would be set for
// a positive number, the number MUST be preceded by a zero byte.
// Unnecessary leading bytes with the value 0 or 255 MUST NOT be
// included. The value zero MUST be stored as a string with zero
// bytes of data.
if (length == 0) {
// Zero is always represented by no bytes.
return BigInt.zero;
} else if (_begin + length <= _end) {
// Length is correct
// Process first byte
final firstByte = _bytes[_begin];
final negative = (firstByte & 0x80) != 0; // 1 MSB from first byte
var n = BigInt.from(firstByte & 0x7F); // other 7 LSB from first byte
_begin++; // skip first byte
if (_begin == _end) {
if (n == BigInt.zero && !negative) {
// Zero must be represented by no bytes
throw KeyBad('invalid mpint');
}
} else {
final secondByte = _bytes[_begin];
if (firstByte == 0x00 && (secondByte & 0x80 == 0x00) ||
firstByte == 0xFF && (secondByte & 0x80 == 0x80)) {
// Unnecessary leading bytes with 0 or 255 MUST NOT be included.
throw KeyBad('invalid mpint');
}
}
// Process remaining bytes
for (var i = 1; i < length; i++) {
n = (n << 8) | BigInt.from(_bytes[_begin++]);
}
// Return value (two's complement for negative numbers)
return (negative) ? n - BigInt.two.pow((8 * length) - 1) : n;
} else {
throw KeyBad('data incomplete (for $length byte MPint)');
}
}