UNPKG

asn1-ts

Version:

ASN.1 encoding and decoding, including BER, CER, and DER.

123 lines (122 loc) 5.02 kB
import * as errors from "../../../errors.mjs"; import convertBytesToText from "../../../utils/convertBytesToText.mjs"; import validateDateTime from "../../../validators/validateDateTime.mjs"; const SMALLEST_CORRECT_GENERALIZED_TIME = "2000120123".length; const PERIOD = ".".charCodeAt(0); const COMMA = ",".charCodeAt(0); const Z = "Z".charCodeAt(0); const PLUS = "+".charCodeAt(0); const MINUS = "-".charCodeAt(0); var FractionalUnits; (function (FractionalUnits) { FractionalUnits[FractionalUnits["Hours"] = 0] = "Hours"; FractionalUnits[FractionalUnits["Minutes"] = 1] = "Minutes"; FractionalUnits[FractionalUnits["Seconds"] = 2] = "Seconds"; })(FractionalUnits || (FractionalUnits = {})); ; function isStop(s, i) { const char = s.charCodeAt(i); return (char === PERIOD) || (char === COMMA); } export default function decodeGeneralizedTime(value) { if (value.length < SMALLEST_CORRECT_GENERALIZED_TIME) { throw new errors.ASN1Error("Malformed GeneralizedTime string."); } if (value.length > 32) { throw new errors.ASN1Error("Outrageously large GeneralizedTime string."); } const dateString = convertBytesToText(value); const year = Number(dateString.slice(0, 4)); const month = (Number(dateString.slice(4, 6)) - 1); const date = Number(dateString.slice(6, 8)); const hours = Number(dateString.slice(8, 10)); if (value.length === 10) { validateDateTime("GeneralizedTime", year, month, date, hours, 0, 0); return new Date(year, month, date, hours, 0, 0); } let i = 10; while (value[i] && value[i] >= 0x30 && value[i] <= 0x39) i++; let minutes = 0; let seconds = 0; let milliseconds = 0; let fractionUnits = FractionalUnits.Hours; if (i == 14) { minutes = Number.parseInt(dateString.slice(10, 12), 10); seconds = Number.parseInt(dateString.slice(12, 14), 10); fractionUnits = 2; } else if (i == 12) { minutes = Number.parseInt(dateString.slice(10, 12), 10); fractionUnits = 1; } else if (i != 10) { throw new errors.ASN1Error("Malformed GeneralizedTime string."); } if (value[i] === undefined) { validateDateTime("GeneralizedTime", year, month, date, hours, minutes, seconds); return new Date(year, month, date, hours, minutes, seconds); } if (isStop(dateString, i)) { i++; let j = i; while (value[j] && value[j] >= 0x30 && value[j] <= 0x39) j++; const fractionString = `0.${dateString.slice(i, j)}`; i = j; const fraction = Number.parseFloat(fractionString); if (fractionUnits === FractionalUnits.Hours) { minutes = Math.floor(60 * fraction); seconds = Math.floor((60 * 60 * fraction) % 60); } else if (fractionUnits === FractionalUnits.Minutes) { seconds = Math.floor(60 * fraction); } else if (fractionUnits === FractionalUnits.Seconds) { milliseconds = Math.floor(1000 * fraction); } else { throw new Error("internal asn1-ts error: invalid FractionalUnits"); } } if (value[i] === undefined) { validateDateTime("GeneralizedTime", year, month, date, hours, minutes, seconds); return new Date(year, month, date, hours, minutes, seconds, milliseconds); } if (value[i] === Z) { validateDateTime("GeneralizedTime", year, month, date, hours, minutes, seconds); return new Date(Date.UTC(year, month, date, hours, minutes, seconds, milliseconds)); } if (value[i] === PLUS || value[i] === MINUS) { const isPositive = value[i] === PLUS; i++; let j = i; while (value[j] && value[j] >= 0x30 && value[j] <= 0x39) j++; const offsetSize = j - i; if (value[j] !== undefined) { throw new errors.ASN1Error("Malformed GeneralizedTime string."); } let offsetHour = 0; let offsetMinute = 0; if (offsetSize === 4) { offsetHour = Number.parseInt(dateString.slice(j - 4, j - 2), 10); offsetMinute = Number.parseInt(dateString.slice(j - 2, j), 10); } else if (offsetSize === 2) { offsetHour = Number.parseInt(dateString.slice(j - 2, j)); } else { throw new errors.ASN1Error("Malformed GeneralizedTime string."); } let epochTimeInMS = Date.UTC(year, month, date, hours, minutes, seconds, milliseconds); const sign = isPositive ? -1 : 1; epochTimeInMS += sign * ((offsetHour * 60 * 60 * 1000) + (offsetMinute * 60 * 1000)); return new Date(epochTimeInMS); } if (value[i] !== undefined) { throw new errors.ASN1Error("Malformed GeneralizedTime string."); } validateDateTime("GeneralizedTime", year, month, date, hours, minutes, seconds); return new Date(Date.UTC(year, month, date, hours, minutes, seconds, milliseconds)); }