UNPKG

node-webtokens

Version:

Simple, opinionated implementation of JWS and JWE compact serialization

79 lines (75 loc) 2.7 kB
const ERR_MSG = 'Could not extract parameters from DER signature'; exports.derToConcat = (signature, size) => { let offset = 0; if (signature[offset++] !== 0x30) throw new Error(ERR_MSG); let seqLength = signature[offset++]; if (seqLength === 0x81) seqLength = signature[offset++]; if (seqLength > signature.length - offset || signature[offset++] !== 0x02) { throw new Error(ERR_MSG); } let rLength = signature[offset++]; if (rLength > signature.length - offset - 2 || rLength > size + 1) { throw new Error(ERR_MSG); } let rOffset = offset; offset += rLength; if (signature[offset++] !== 0x02) throw new Error(ERR_MSG); let sLength = signature[offset++]; if (sLength !== signature.length - offset || sLength > size + 1) { throw new Error(ERR_MSG); } let sOffset = offset; offset += sLength; if (offset !== signature.length) throw new Error(ERR_MSG); let rPadding = size - rLength; let sPadding = size - sLength; let dst = Buffer.allocUnsafe(rPadding + rLength + sPadding + sLength); for (offset = 0; offset < rPadding; offset++) dst[offset] = 0; let rPad = Math.max(-rPadding, 0); signature.copy(dst, offset, rOffset + rPad, rOffset + rLength); offset = size; for (let o = offset; offset < o + sPadding; offset++) dst[offset] = 0; let sPad = Math.max(-sPadding, 0); signature.copy(dst, offset, sOffset + sPad, sOffset + sLength); return dst; } exports.concatToDer = (signature, size) => { let rPadding = countPadding(signature, 0, size); let sPadding = countPadding(signature, size, signature.length); let rLength = size - rPadding; let sLength = size - sPadding; let rsBytes = rLength + sLength + 4; let shortLength = rsBytes < 0x80; let dst = Buffer.allocUnsafe((shortLength ? 2 : 3) + rsBytes); let offset = 0; dst[offset++] = 0x30; if (shortLength) { dst[offset++] = rsBytes; } else { dst[offset++] = 0x81; dst[offset++] = rsBytes & 0xFF; } dst[offset++] = 0x02; dst[offset++] = rLength; if (rPadding < 0) { dst[offset++] = 0; offset += signature.copy(dst, offset, 0, size); } else { offset += signature.copy(dst, offset, rPadding, size); } dst[offset++] = 0x02; dst[offset++] = sLength; if (sPadding < 0) { dst[offset++] = 0; signature.copy(dst, offset, size); } else { signature.copy(dst, offset, size + sPadding); } return dst; } function countPadding(buf, start, stop) { let padding = 0; while (start + padding < stop && buf[start + padding] === 0) padding++; let needsSign = buf[start + padding] >= 0x80; return needsSign ? --padding : padding; }