const tagInteger = 0x02 const tagSequence = 0x30 /** * The end justifies the means. */ export default class Asn1SequenceDecoder { buffer: Buffer offset: number constructor(buffer: Buffer) { if (buffer[0] !== tagSequence) { throw new TypeError() } this.buffer = buffer this.offset = 1 const len = this.decodeLength() if (len !== buffer.length - this.offset) { throw new TypeError() } } decodeLength() { let length = this.buffer[this.offset++] if (length & 0x80) { // Long form. const nBytes = length & ~0x80 length = 0 for (let i = 0; i < nBytes; i++) length = (length << 8) | this.buffer[this.offset + i] this.offset += nBytes } return length } unsignedInteger() { if (this.buffer[this.offset++] !== tagInteger) { throw new TypeError() } let length = this.decodeLength() // There may be exactly one leading zero (if the next byte's MSB is set). if (this.buffer[this.offset] === 0) { this.offset++ length-- } const result = this.buffer.slice(this.offset, this.offset + length) this.offset += length return result } end() { if (this.offset !== this.buffer.length) { throw new TypeError() } } }