asn1-ts 8.0.3 → 8.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -39,20 +39,117 @@ Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.default = decodeGeneralizedTime;
40
40
  const errors = __importStar(require("../../../errors"));
41
41
  const convertBytesToText_1 = __importDefault(require("../../../utils/convertBytesToText"));
42
- const values_1 = require("../../../values");
43
42
  const validateDateTime_1 = __importDefault(require("../../../validators/validateDateTime"));
43
+ const SMALLEST_CORRECT_GENERALIZED_TIME = "2000120123".length;
44
+ const PERIOD = ".".charCodeAt(0);
45
+ const COMMA = ",".charCodeAt(0);
46
+ const Z = "Z".charCodeAt(0);
47
+ const PLUS = "+".charCodeAt(0);
48
+ const MINUS = "-".charCodeAt(0);
49
+ ;
50
+ function isStop(s, i) {
51
+ const char = s.charCodeAt(i);
52
+ return (char === PERIOD) || (char === COMMA);
53
+ }
44
54
  function decodeGeneralizedTime(value) {
55
+ if (value.length < SMALLEST_CORRECT_GENERALIZED_TIME) {
56
+ throw new errors.ASN1Error("Malformed GeneralizedTime string.");
57
+ }
58
+ if (value.length > 32) {
59
+ throw new errors.ASN1Error("Outrageously large GeneralizedTime string.");
60
+ }
45
61
  const dateString = (0, convertBytesToText_1.default)(value);
46
- const match = values_1.generalizedTimeRegex.exec(dateString);
47
- if (match === null) {
62
+ const year = Number(dateString.slice(0, 4));
63
+ const month = (Number(dateString.slice(4, 6)) - 1);
64
+ const date = Number(dateString.slice(6, 8));
65
+ const hours = Number(dateString.slice(8, 10));
66
+ if (value.length === 10) {
67
+ (0, validateDateTime_1.default)("GeneralizedTime", year, month, date, hours, 0, 0);
68
+ return new Date(year, month, date, hours, 0, 0);
69
+ }
70
+ let i = 10;
71
+ while (value[i] && value[i] >= 0x30 && value[i] <= 0x39)
72
+ i++;
73
+ let minutes = 0;
74
+ let seconds = 0;
75
+ let milliseconds = 0;
76
+ let fractionUnits = 0;
77
+ if (i == 14) {
78
+ minutes = Number.parseInt(dateString.slice(10, 12), 10);
79
+ seconds = Number.parseInt(dateString.slice(12, 14), 10);
80
+ fractionUnits = 2;
81
+ }
82
+ else if (i == 12) {
83
+ minutes = Number.parseInt(dateString.slice(10, 12), 10);
84
+ fractionUnits = 1;
85
+ }
86
+ else if (i != 10) {
87
+ throw new errors.ASN1Error("Malformed GeneralizedTime string.");
88
+ }
89
+ if (value[i] === undefined) {
90
+ (0, validateDateTime_1.default)("GeneralizedTime", year, month, date, hours, minutes, seconds);
91
+ return new Date(year, month, date, hours, minutes, seconds);
92
+ }
93
+ if (isStop(dateString, i)) {
94
+ i++;
95
+ let j = i;
96
+ while (value[j] && value[j] >= 0x30 && value[j] <= 0x39)
97
+ j++;
98
+ const fractionString = `0.${dateString.slice(i, j)}`;
99
+ i = j;
100
+ const fraction = Number.parseFloat(fractionString);
101
+ if (fractionUnits === 0) {
102
+ minutes = Math.floor(60 * fraction);
103
+ seconds = Math.floor((60 * 60 * fraction) % 60);
104
+ }
105
+ else if (fractionUnits === 1) {
106
+ seconds = Math.floor(60 * fraction);
107
+ }
108
+ else if (fractionUnits === 2) {
109
+ milliseconds = Math.floor(1000 * fraction);
110
+ }
111
+ else {
112
+ throw new Error("internal asn1-ts error: invalid FractionalUnits");
113
+ }
114
+ }
115
+ if (value[i] === undefined) {
116
+ (0, validateDateTime_1.default)("GeneralizedTime", year, month, date, hours, minutes, seconds);
117
+ return new Date(year, month, date, hours, minutes, seconds, milliseconds);
118
+ }
119
+ if (value[i] === Z) {
120
+ (0, validateDateTime_1.default)("GeneralizedTime", year, month, date, hours, minutes, seconds);
121
+ return new Date(Date.UTC(year, month, date, hours, minutes, seconds, milliseconds));
122
+ }
123
+ if (value[i] === PLUS || value[i] === MINUS) {
124
+ const isPositive = value[i] === PLUS;
125
+ i++;
126
+ let j = i;
127
+ while (value[j] && value[j] >= 0x30 && value[j] <= 0x39)
128
+ j++;
129
+ const offsetSize = j - i;
130
+ if (value[j] !== undefined) {
131
+ throw new errors.ASN1Error("Malformed GeneralizedTime string.");
132
+ }
133
+ let offsetHour = 0;
134
+ let offsetMinute = 0;
135
+ if (offsetSize === 4) {
136
+ offsetHour = Number.parseInt(dateString.slice(j - 4, j - 2), 10);
137
+ offsetMinute = Number.parseInt(dateString.slice(j - 2, j), 10);
138
+ }
139
+ else if (offsetSize === 2) {
140
+ offsetHour = Number.parseInt(dateString.slice(j - 2, j));
141
+ }
142
+ else {
143
+ throw new errors.ASN1Error("Malformed GeneralizedTime string.");
144
+ }
145
+ let epochTimeInMS = Date.UTC(year, month, date, hours, minutes, seconds, milliseconds);
146
+ const sign = isPositive ? -1 : 1;
147
+ epochTimeInMS += sign * ((offsetHour * 60 * 60 * 1000) + (offsetMinute * 60 * 1000));
148
+ return new Date(epochTimeInMS);
149
+ }
150
+ if (value[i] !== undefined) {
48
151
  throw new errors.ASN1Error("Malformed GeneralizedTime string.");
49
152
  }
50
- const year = Number(match[1]);
51
- const month = (Number(match[2]) - 1);
52
- const date = Number(match[3]);
53
- const hours = Number(match[4]);
54
- const minutes = Number(match[5]);
55
- const seconds = Number(match[6]);
56
153
  (0, validateDateTime_1.default)("GeneralizedTime", year, month, date, hours, minutes, seconds);
57
- return new Date(Date.UTC(year, month, date, hours, minutes, seconds));
154
+ return new Date(Date.UTC(year, month, date, hours, minutes, seconds, milliseconds));
58
155
  }
@@ -39,23 +39,46 @@ Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.default = decodeUTCTime;
40
40
  const convertBytesToText_1 = __importDefault(require("../../../utils/convertBytesToText"));
41
41
  const errors = __importStar(require("../../../errors"));
42
- const values_1 = require("../../../values");
43
42
  const validateDateTime_1 = __importDefault(require("../../../validators/validateDateTime"));
44
43
  function decodeUTCTime(value) {
45
44
  const dateString = (0, convertBytesToText_1.default)(value);
46
- const match = values_1.utcTimeRegex.exec(dateString);
47
- if (match === null) {
48
- throw new errors.ASN1Error("Malformed UTCTime string.");
49
- }
50
- let year = Number(match[1]);
45
+ let year = Number(dateString.slice(0, 2));
51
46
  year = (year <= 49)
52
47
  ? (2000 + year)
53
48
  : (1900 + year);
54
- const month = (Number(match[2]) - 1);
55
- const date = Number(match[3]);
56
- const hours = Number(match[4]);
57
- const minutes = Number(match[5]);
58
- const seconds = Number(match[6]);
59
- (0, validateDateTime_1.default)("UTCTime", year, month, date, hours, minutes, seconds);
60
- return new Date(Date.UTC(year, month, date, hours, minutes, seconds));
49
+ const month = (Number(dateString.slice(2, 4)) - 1);
50
+ const date = Number(dateString.slice(4, 6));
51
+ const hours = Number(dateString.slice(6, 8));
52
+ const minutes = Number(dateString.slice(8, 10));
53
+ const char10 = dateString.charCodeAt(10);
54
+ const secondsFieldPresent = (char10 >= 0x30 && char10 <= 0x39);
55
+ const seconds = secondsFieldPresent
56
+ ? Number(dateString.slice(10, 12))
57
+ : 0;
58
+ let i = secondsFieldPresent ? 12 : 10;
59
+ if (dateString[i] === 'Z') {
60
+ (0, validateDateTime_1.default)("UTCTime", year, month, date, hours, minutes, seconds);
61
+ return new Date(Date.UTC(year, month, date, hours, minutes, seconds));
62
+ }
63
+ if ((dateString[i] !== '+') && (dateString[i] !== '-')) {
64
+ throw new errors.ASN1Error(`Malformed BER UTCTime: non +/- offset: ${dateString[i]}`);
65
+ }
66
+ const isPositive = dateString[i] === '+';
67
+ i++;
68
+ let j = 0;
69
+ while (value[i + j] && value[i + j] >= 0x30 && value[i + j] <= 0x39)
70
+ j++;
71
+ if (j !== 4) {
72
+ throw new errors.ASN1Error("Malformed BER UTCTime: non four-digit offset");
73
+ }
74
+ i += j;
75
+ if (dateString[i] !== undefined) {
76
+ throw new errors.ASN1Error("Malformed BER UTCTime: trailing data");
77
+ }
78
+ const offsetHour = Number.parseInt(dateString.slice(i - 4, i - 2), 10);
79
+ const offsetMinute = Number.parseInt(dateString.slice(i - 2, i), 10);
80
+ let epochTimeInMS = Date.UTC(year, month, date, hours, minutes, seconds);
81
+ const sign = isPositive ? -1 : 1;
82
+ epochTimeInMS += sign * ((offsetHour * 60 * 60 * 1000) + (offsetMinute * 60 * 1000));
83
+ return new Date(epochTimeInMS);
61
84
  }
@@ -539,12 +539,6 @@ class BERElement extends x690_1.default {
539
539
  throw new errors.ASN1UndefinedError("Length byte with undefined meaning encountered.", this);
540
540
  }
541
541
  if (numberOfLengthOctets > 4) {
542
- if (bytes instanceof Buffer) {
543
- console.log(bytes.toString("hex"));
544
- }
545
- else {
546
- console.log(Buffer.from(bytes).toString("hex"));
547
- }
548
542
  throw new errors.ASN1OverflowError(`Element length too long to decode to an integer. Content octets occupied ${numberOfLengthOctets} bytes.`, this);
549
543
  }
550
544
  if (cursor + numberOfLengthOctets >= bytes.length) {
@@ -38,21 +38,44 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.default = decodeGeneralizedTime;
40
40
  const convertBytesToText_1 = __importDefault(require("../../../utils/convertBytesToText"));
41
- const values_1 = require("../../../values");
42
41
  const errors = __importStar(require("../../../errors"));
43
42
  const validateDateTime_1 = __importDefault(require("../../../validators/validateDateTime"));
44
43
  function decodeGeneralizedTime(value) {
45
44
  const dateString = (0, convertBytesToText_1.default)(value);
46
- const match = values_1.distinguishedGeneralizedTimeRegex.exec(dateString);
47
- if (match === null) {
48
- throw new errors.ASN1Error("Malformed GeneralizedTime string.");
45
+ if (!dateString.endsWith("Z")) {
46
+ throw new errors.ASN1Error("Malformed DER GeneralizedTime string: must use UTC timezone");
47
+ }
48
+ const year = Number(dateString.slice(0, 4));
49
+ const month = (Number(dateString.slice(4, 6)) - 1);
50
+ const date = Number(dateString.slice(6, 8));
51
+ const hours = Number(dateString.slice(8, 10));
52
+ const minutes = Number(dateString.slice(10, 12));
53
+ const seconds = Number(dateString.slice(12, 14));
54
+ if (dateString[14] === '.') {
55
+ let i = 15;
56
+ while (value[i] && value[i] >= 0x30 && value[i] <= 0x39)
57
+ i++;
58
+ if (i === 15) {
59
+ throw new errors.ASN1Error("Malformed DER GeneralizedTime string: trailing stop character");
60
+ }
61
+ if (dateString[i] === 'Z') {
62
+ i++;
63
+ }
64
+ if (dateString[i] !== undefined) {
65
+ throw new errors.ASN1Error("Malformed DER GeneralizedTime string: trailing data");
66
+ }
67
+ const fractionString = `0.${dateString.slice(15, i)}`;
68
+ if (fractionString.endsWith("0")) {
69
+ throw new errors.ASN1Error("Malformed DER GeneralizedTime string: trailing 0 in milliseconds");
70
+ }
71
+ const fraction = Number.parseFloat(fractionString);
72
+ const milliseconds = Math.floor(1000 * fraction);
73
+ (0, validateDateTime_1.default)("GeneralizedTime", year, month, date, hours, minutes, seconds);
74
+ return new Date(Date.UTC(year, month, date, hours, minutes, seconds, milliseconds));
75
+ }
76
+ else if (dateString[14] !== 'Z') {
77
+ throw new errors.ASN1Error("Malformed DER GeneralizedTime string: trailing data");
49
78
  }
50
- const year = Number(match[1]);
51
- const month = (Number(match[2]) - 1);
52
- const date = Number(match[3]);
53
- const hours = Number(match[4]);
54
- const minutes = Number(match[5]);
55
- const seconds = Number(match[6]);
56
79
  (0, validateDateTime_1.default)("GeneralizedTime", year, month, date, hours, minutes, seconds);
57
80
  return new Date(Date.UTC(year, month, date, hours, minutes, seconds));
58
81
  }
@@ -38,24 +38,26 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.default = decodeUTCTime;
40
40
  const convertBytesToText_1 = __importDefault(require("../../../utils/convertBytesToText"));
41
- const values_1 = require("../../../values");
42
41
  const errors = __importStar(require("../../../errors"));
43
42
  const validateDateTime_1 = __importDefault(require("../../../validators/validateDateTime"));
43
+ const DER_UTC_TIME_LENGTH = "920521000000Z".length;
44
44
  function decodeUTCTime(value) {
45
+ if (value.length !== DER_UTC_TIME_LENGTH) {
46
+ throw new errors.ASN1Error("Malformed DER UTCTime string: not a valid length");
47
+ }
45
48
  const dateString = (0, convertBytesToText_1.default)(value);
46
- const match = values_1.distinguishedUTCTimeRegex.exec(dateString);
47
- if (match === null) {
48
- throw new errors.ASN1Error("Malformed UTCTime string.");
49
+ if (!dateString.endsWith("Z")) {
50
+ throw new errors.ASN1Error("Malformed DER UTCTime string: not UTC timezone");
49
51
  }
50
- let year = Number(match[1]);
52
+ let year = Number(dateString.slice(0, 2));
53
+ const month = (Number(dateString.slice(2, 4)) - 1);
54
+ const date = Number(dateString.slice(4, 6));
55
+ const hours = Number(dateString.slice(6, 8));
56
+ const minutes = Number(dateString.slice(8, 10));
57
+ const seconds = Number(dateString.slice(10, 12));
51
58
  year = (year <= 49)
52
59
  ? (2000 + year)
53
60
  : (1900 + year);
54
- const month = (Number(match[2]) - 1);
55
- const date = Number(match[3]);
56
- const hours = Number(match[4]);
57
- const minutes = Number(match[5]);
58
- const seconds = Number(match[6]);
59
61
  (0, validateDateTime_1.default)("UTCTime", year, month, date, hours, minutes, seconds);
60
62
  return new Date(Date.UTC(year, month, date, hours, minutes, seconds));
61
63
  }
@@ -36,6 +36,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.default = validateDate;
37
37
  const errors = __importStar(require("../errors"));
38
38
  function validateDate(dataType, year, month, date) {
39
+ if (!Number.isSafeInteger(year)) {
40
+ throw new errors.ASN1Error(`Invalid year in ${dataType}`);
41
+ }
42
+ if (!Number.isSafeInteger(month)) {
43
+ throw new errors.ASN1Error(`Invalid month in ${dataType}`);
44
+ }
45
+ if (!Number.isSafeInteger(date) || (date < 1)) {
46
+ throw new errors.ASN1Error(`Invalid day in ${dataType}`);
47
+ }
39
48
  switch (month) {
40
49
  case 0:
41
50
  case 2:
@@ -71,6 +80,6 @@ function validateDate(dataType, year, month, date) {
71
80
  break;
72
81
  }
73
82
  default:
74
- throw new errors.ASN1Error(`Month greater than 12 encountered in ${dataType}.`);
83
+ throw new errors.ASN1Error(`Invalid month in ${dataType}`);
75
84
  }
76
85
  }
@@ -36,6 +36,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.default = validateTime;
37
37
  const errors = __importStar(require("../errors"));
38
38
  function validateTime(dataType, hours, minutes, seconds) {
39
+ if (!Number.isSafeInteger(hours)) {
40
+ throw new errors.ASN1Error(`Invalid hours in ${dataType}`);
41
+ }
42
+ if (!Number.isSafeInteger(minutes)) {
43
+ throw new errors.ASN1Error(`Invalid minutes in ${dataType}`);
44
+ }
45
+ if (!Number.isSafeInteger(seconds) || (seconds < 0)) {
46
+ throw new errors.ASN1Error(`Invalid seconds in ${dataType}`);
47
+ }
39
48
  if (hours > 23) {
40
49
  throw new errors.ASN1Error(`Hours > 23 encountered in ${dataType}.`);
41
50
  }
package/package.json CHANGED
@@ -47,5 +47,5 @@
47
47
  "test": "npx jest --ci --reporters=default --coverage"
48
48
  },
49
49
  "types": "./dist/node/index.d.ts",
50
- "version": "8.0.3"
50
+ "version": "8.0.4"
51
51
  }