asn1-ts
Version:
ASN.1 encoding and decoding, including BER, CER, and DER.
43 lines (42 loc) • 2.07 kB
JavaScript
import convertBytesToText from "../../../utils/convertBytesToText.mjs";
import * as errors from "../../../errors.mjs";
import validateDateTime from "../../../validators/validateDateTime.mjs";
export default function decodeGeneralizedTime(value) {
const dateString = convertBytesToText(value);
if (!dateString.endsWith("Z")) {
throw new errors.ASN1Error("Malformed DER GeneralizedTime string: must use UTC timezone");
}
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));
const minutes = Number(dateString.slice(10, 12));
const seconds = Number(dateString.slice(12, 14));
if (dateString[14] === '.') {
let i = 15;
while (value[i] && value[i] >= 0x30 && value[i] <= 0x39)
i++;
if (i === 15) {
throw new errors.ASN1Error("Malformed DER GeneralizedTime string: trailing stop character");
}
if (dateString[i] === 'Z') {
i++;
}
if (dateString[i] !== undefined) {
throw new errors.ASN1Error("Malformed DER GeneralizedTime string: trailing data");
}
const fractionString = `0.${dateString.slice(15, i)}`;
if (fractionString.endsWith("0")) {
throw new errors.ASN1Error("Malformed DER GeneralizedTime string: trailing 0 in milliseconds");
}
const fraction = Number.parseFloat(fractionString);
const milliseconds = Math.floor(1000 * fraction);
validateDateTime("GeneralizedTime", year, month, date, hours, minutes, seconds);
return new Date(Date.UTC(year, month, date, hours, minutes, seconds, milliseconds));
}
else if (dateString[14] !== 'Z') {
throw new errors.ASN1Error("Malformed DER GeneralizedTime string: trailing data");
}
validateDateTime("GeneralizedTime", year, month, date, hours, minutes, seconds);
return new Date(Date.UTC(year, month, date, hours, minutes, seconds));
}