asn1-ts 10.0.0 → 11.0.0

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.
@@ -1,13 +1,5 @@
1
- import isGeneralCharacter from "../../../validators/isGeneralCharacter.mjs";
2
1
  import convertTextToBytes from "../../../utils/convertTextToBytes.mjs";
3
- import { ASN1CharactersError } from "../../../errors.mjs";
4
2
  export default function encodeGeneralString(value) {
5
3
  const bytes = convertTextToBytes(value);
6
- for (const char of bytes) {
7
- if (!isGeneralCharacter(char)) {
8
- throw new ASN1CharactersError("GeneralString can only contain ASCII characters."
9
- + `Encountered character code ${char}.`);
10
- }
11
- }
12
4
  return bytes;
13
5
  }
@@ -1,13 +1,5 @@
1
- import isGraphicCharacter from "../../../validators/isGraphicCharacter.mjs";
2
1
  import convertTextToBytes from "../../../utils/convertTextToBytes.mjs";
3
- import { ASN1CharactersError } from "../../../errors.mjs";
4
2
  export default function encodeGraphicString(value) {
5
3
  const bytes = convertTextToBytes(value);
6
- for (const char of bytes) {
7
- if (!isGraphicCharacter(char)) {
8
- throw new ASN1CharactersError("GraphicString can only contain characters between 0x20 and 0x7E. "
9
- + `Encountered character code ${char}.`);
10
- }
11
- }
12
4
  return bytes;
13
5
  }
@@ -1,13 +1,5 @@
1
- import isNumericCharacter from "../../../validators/isNumericCharacter.mjs";
2
1
  import convertTextToBytes from "../../../utils/convertTextToBytes.mjs";
3
- import { ASN1CharactersError } from "../../../errors.mjs";
4
2
  export default function encodeNumericString(value) {
5
3
  const bytes = convertTextToBytes(value);
6
- for (const char of bytes) {
7
- if (!isNumericCharacter(char)) {
8
- throw new ASN1CharactersError("NumericString can only contain characters 0 - 9 and space. "
9
- + `Encountered character code ${char}.`);
10
- }
11
- }
12
4
  return bytes;
13
5
  }
@@ -1,13 +1,5 @@
1
- import isObjectDescriptorCharacter from "../../../validators/isObjectDescriptorCharacter.mjs";
2
1
  import convertTextToBytes from "../../../utils/convertTextToBytes.mjs";
3
- import { ASN1CharactersError } from "../../../errors.mjs";
4
2
  export default function encodeObjectDescriptor(value) {
5
3
  const bytes = convertTextToBytes(value);
6
- for (const char of bytes) {
7
- if (!isObjectDescriptorCharacter(char)) {
8
- throw new ASN1CharactersError("ObjectDescriptor can only contain characters between 0x20 and 0x7E. "
9
- + `Encountered character code ${char}.`);
10
- }
11
- }
12
4
  return bytes;
13
5
  }
@@ -1,14 +1,5 @@
1
- import isPrintableCharacter from "../../../validators/isPrintableCharacter.mjs";
2
1
  import convertTextToBytes from "../../../utils/convertTextToBytes.mjs";
3
- import { ASN1CharactersError } from "../../../errors.mjs";
4
- import { printableStringCharacters } from "../../../values.mjs";
5
2
  export default function encodeNumericString(value) {
6
3
  const bytes = convertTextToBytes(value);
7
- for (const char of bytes) {
8
- if (!isPrintableCharacter(char)) {
9
- throw new ASN1CharactersError(`PrintableString can only contain these characters: ${printableStringCharacters}. `
10
- + `Encountered character code ${char}.`);
11
- }
12
- }
13
4
  return bytes;
14
5
  }
@@ -1,13 +1,5 @@
1
- import isGraphicCharacter from "../../../validators/isGraphicCharacter.mjs";
2
1
  import convertTextToBytes from "../../../utils/convertTextToBytes.mjs";
3
- import { ASN1CharactersError } from "../../../errors.mjs";
4
2
  export default function encodeVisibleString(value) {
5
3
  const bytes = convertTextToBytes(value);
6
- for (const char of bytes) {
7
- if (!isGraphicCharacter(char)) {
8
- throw new ASN1CharactersError("VisibleString can only contain characters between 0x20 and 0x7E. "
9
- + `Encountered character code ${char}.`);
10
- }
11
- }
12
4
  return bytes;
13
5
  }
@@ -1,46 +1,4 @@
1
1
  import ObjectIdentifier from "../../../types/ObjectIdentifier.mjs";
2
- import * as errors from "../../../errors.mjs";
3
2
  export default function decodeObjectIdentifier(value) {
4
- if (value.length === 0) {
5
- throw new errors.ASN1TruncationError("Encoded value was too short to be an OBJECT IDENTIFIER!");
6
- }
7
- const nodes = [0, 0];
8
- if (value[0] >= 0x50) {
9
- nodes[0] = 2;
10
- nodes[1] = (value[0] - 0x50);
11
- }
12
- else if (value[0] >= 0x28) {
13
- nodes[0] = 1;
14
- nodes[1] = (value[0] - 0x28);
15
- }
16
- else {
17
- nodes[0] = 0;
18
- nodes[1] = value[0];
19
- }
20
- if (value.length === 1) {
21
- return new ObjectIdentifier(nodes);
22
- }
23
- if (value[value.length - 1] & 0b10000000) {
24
- throw new errors.ASN1TruncationError("OID was truncated.");
25
- }
26
- let current_node = 0;
27
- for (let i = 1; i < value.length; i++) {
28
- const byte = value[i];
29
- if (current_node === 0) {
30
- if (byte < 128) {
31
- nodes.push(byte);
32
- continue;
33
- }
34
- if (byte === 0x80) {
35
- throw new errors.ASN1PaddingError("Prohibited padding on OBJECT IDENTIFIER node.");
36
- }
37
- }
38
- current_node <<= 7;
39
- current_node += (byte & 127);
40
- if ((byte & 128) === 0) {
41
- nodes.push(current_node);
42
- current_node = 0;
43
- }
44
- }
45
- return new ObjectIdentifier(nodes);
3
+ return ObjectIdentifier.fromBytes(value);
46
4
  }
@@ -1,29 +1,4 @@
1
1
  import { Buffer } from "node:buffer";
2
2
  export default function encodeObjectIdentifier(value) {
3
- const arcs = value.uint32ArrayRef;
4
- const node0 = arcs[0];
5
- const node1 = arcs[1];
6
- const byte0 = (node0 * 40) + node1;
7
- const ret = [byte0];
8
- for (const arc of arcs.slice(2)) {
9
- if (arc < 128) {
10
- ret.push(arc);
11
- continue;
12
- }
13
- let l = 0;
14
- let i = arc;
15
- while (i > 0) {
16
- l++;
17
- i >>>= 7;
18
- }
19
- for (let j = l - 1; j >= 0; j--) {
20
- let o = (arc >>> (j * 7));
21
- o &= 0x7f;
22
- if (j !== 0) {
23
- o |= 0x80;
24
- }
25
- ret.push(o);
26
- }
27
- }
28
- return Buffer.from(ret);
3
+ return value.toBytes();
29
4
  }
@@ -564,7 +564,7 @@ export function _parse_set(set, decodingCallbacks, rootComponentTypeList1, exten
564
564
  const missingRequiredComponents = rootComponents
565
565
  .filter((c) => (!c.optional && !encounteredComponents.has(c.name)))
566
566
  .map((c) => c.name);
567
- Array.from(encounteredExtensionGroups).forEach((exg) => {
567
+ for (const exg of encounteredExtensionGroups.values()) {
568
568
  for (const c of extensionAdditionsList) {
569
569
  if (!((c.groupIndex === exg)
570
570
  && !c.optional
@@ -573,7 +573,7 @@ export function _parse_set(set, decodingCallbacks, rootComponentTypeList1, exten
573
573
  }
574
574
  missingRequiredComponents.push(c.name);
575
575
  }
576
- });
576
+ }
577
577
  if (missingRequiredComponents.length > 0) {
578
578
  throw new Error(`SET '${set.name}' missing these required components: ${missingRequiredComponents.join(", ")}.`);
579
579
  }
@@ -647,9 +647,9 @@ function _parse_sequence_with_trailing_rctl(seq, decodingCallbacks, rootComponen
647
647
  const startOfRCTL2 = (startOfExtensions + numberOfExtensionElements);
648
648
  const numberOfExtensionsRead = _parse_component_type_list(extensionAdditionsList, decodingCallbacks, elements.slice(startOfExtensions, startOfRCTL2), true);
649
649
  const endOfRecognizedExtensions = (startOfExtensions + numberOfExtensionsRead);
650
- elements
651
- .slice(endOfRecognizedExtensions, startOfRCTL2)
652
- .forEach((x) => unrecognizedExtensionHandler(x));
650
+ for (let i = endOfRecognizedExtensions; i < startOfRCTL2; i++) {
651
+ unrecognizedExtensionHandler(elements[i]);
652
+ }
653
653
  const numberOfRCTL2ElementsRead = _parse_component_type_list(rootComponentTypeList2, decodingCallbacks, elements.slice(startOfRCTL2), false);
654
654
  if (startOfRCTL2 + numberOfRCTL2ElementsRead !== elements.length) {
655
655
  throw new Error(`SEQUENCE '${seq.name}' had excess elements at the end.`);
@@ -660,9 +660,9 @@ function _parse_sequence_without_trailing_rctl(seq, decodingCallbacks, rootCompo
660
660
  const startOfExtensions = _parse_component_type_list(rootComponentTypeList1, decodingCallbacks, elements, false);
661
661
  const numberOfExtensionsRead = _parse_component_type_list(extensionAdditionsList, decodingCallbacks, elements.slice(startOfExtensions), true);
662
662
  const endOfRecognizedExtensions = (startOfExtensions + numberOfExtensionsRead);
663
- elements
664
- .slice(endOfRecognizedExtensions)
665
- .forEach((x) => unrecognizedExtensionHandler(x));
663
+ for (let i = endOfRecognizedExtensions; i < elements.length; i++) {
664
+ unrecognizedExtensionHandler(elements[i]);
665
+ }
666
666
  }
667
667
  export function _parse_sequence(seq, decodingCallbacks, rootComponentTypeList1, extensionAdditionsList, rootComponentTypeList2, unrecognizedExtensionHandler = () => { }) {
668
668
  if (rootComponentTypeList2.length > 0) {
@@ -689,12 +689,14 @@ export function _encode_choice(choices, elGetter) {
689
689
  };
690
690
  }
691
691
  export function _decode_inextensible_choice(choices) {
692
+ const choiceMap = new Map(Object.entries(choices));
692
693
  return function (el) {
693
- const result = choices[`${tagClassName(el.tagClass)} ${el.tagNumber}`];
694
+ const result = choiceMap.get(`${tagClassName(el.tagClass)} ${el.tagNumber}`);
694
695
  if (!result) {
695
- if (choices["*"]) {
696
+ const star = choiceMap.get("*");
697
+ if (star) {
696
698
  const ret = {};
697
- ret[choices["*"][0]] = choices["*"][1](el);
699
+ ret[star[0]] = star[1](el);
698
700
  return ret;
699
701
  }
700
702
  else {
@@ -708,8 +710,9 @@ export function _decode_inextensible_choice(choices) {
708
710
  };
709
711
  }
710
712
  export function _decode_extensible_choice(choices) {
713
+ const choiceMap = new Map(Object.entries(choices));
711
714
  return function (el) {
712
- const result = choices[`${tagClassName(el.tagClass)} ${el.tagNumber}`];
715
+ const result = choiceMap.get(`${tagClassName(el.tagClass)} ${el.tagNumber}`);
713
716
  if (!result) {
714
717
  return el;
715
718
  }
@@ -720,30 +723,50 @@ export function _decode_extensible_choice(choices) {
720
723
  };
721
724
  }
722
725
  export function _decodeSequenceOf(decoderGetter) {
726
+ const decoder = decoderGetter();
723
727
  return function (el) {
724
- return el.sequence.map(decoderGetter());
728
+ const seq = el.sequence;
729
+ const result = new Array(seq.length);
730
+ for (let i = 0; i < seq.length; i++) {
731
+ result[i] = decoder(seq[i]);
732
+ }
733
+ return result;
725
734
  };
726
735
  }
727
736
  export function _encodeSequenceOf(encoderGetter, outerElGetter) {
737
+ const encoder = encoderGetter();
728
738
  return function (value) {
729
739
  const el = outerElGetter(value, outerElGetter);
730
- const encoder = encoderGetter();
731
- el.sequence = value.map((v) => encoder(v, outerElGetter));
740
+ const seq = new Array(value.length);
741
+ for (let i = 0; i < value.length; i++) {
742
+ seq[i] = encoder(value[i], outerElGetter);
743
+ }
744
+ el.sequence = seq;
732
745
  el.tagClass = ASN1TagClass.universal;
733
746
  el.tagNumber = ASN1UniversalType.sequence;
734
747
  return el;
735
748
  };
736
749
  }
737
750
  export function _decodeSetOf(decoderGetter) {
751
+ const decoder = decoderGetter();
738
752
  return function (el) {
739
- return el.setOf.map(decoderGetter());
753
+ const setOf = el.setOf;
754
+ const result = new Array(setOf.length);
755
+ for (let i = 0; i < setOf.length; i++) {
756
+ result[i] = decoder(setOf[i]);
757
+ }
758
+ return result;
740
759
  };
741
760
  }
742
761
  export function _encodeSetOf(encoderGetter, outerElGetter) {
762
+ const encoder = encoderGetter();
743
763
  return function (value) {
744
764
  const el = outerElGetter(value, outerElGetter);
745
- const encoder = encoderGetter();
746
- el.setOf = value.map((v) => encoder(v, outerElGetter));
765
+ const seq = new Array(value.length);
766
+ for (let i = 0; i < value.length; i++) {
767
+ seq[i] = encoder(value[i], outerElGetter);
768
+ }
769
+ el.setOf = seq;
747
770
  el.tagClass = ASN1TagClass.universal;
748
771
  el.tagNumber = ASN1UniversalType.set;
749
772
  return el;
@@ -1,8 +1,7 @@
1
- import type { Buffer } from "node:buffer";
1
+ import { Buffer } from "node:buffer";
2
2
  export default class ObjectIdentifier {
3
- private _nodes;
4
- constructor(nodes: number[], prefix?: ObjectIdentifier | number);
5
- get uint32ArrayRef(): Uint32Array;
3
+ protected encoding: Uint8Array;
4
+ static fromParts(nodes: number[], prefix?: ObjectIdentifier | number): ObjectIdentifier;
6
5
  get nodes(): number[];
7
6
  get dotDelimitedNotation(): string;
8
7
  get asn1Notation(): string;
@@ -11,6 +10,7 @@ export default class ObjectIdentifier {
11
10
  toBytes(): Buffer;
12
11
  static fromString(str: string): ObjectIdentifier;
13
12
  static fromBytes(bytes: Uint8Array): ObjectIdentifier;
13
+ static fromBytesUnsafe(bytes: Uint8Array): ObjectIdentifier;
14
14
  static compare(a: ObjectIdentifier, b: ObjectIdentifier): boolean;
15
15
  isEqualTo(other: ObjectIdentifier): boolean;
16
16
  }
@@ -1,36 +1,52 @@
1
- import decodeObjectIdentifier from "../codecs/x690/decoders/decodeObjectIdentifier.mjs";
2
- import encodeObjectIdentifier from "../codecs/x690/encoders/encodeObjectIdentifier.mjs";
1
+ import encodeRelativeObjectIdentifier from "../codecs/x690/encoders/encodeRelativeObjectIdentifier.mjs";
2
+ import decodeRelativeObjectIdentifier from "../codecs/x690/decoders/decodeRelativeObjectIdentifier.mjs";
3
+ import { Buffer } from "node:buffer";
4
+ import * as errors from "../errors.mjs";
3
5
  const PERIOD = ".".charCodeAt(0);
4
6
  export default class ObjectIdentifier {
5
- constructor(nodes, prefix) {
6
- const _nodes = prefix
7
- ? typeof prefix === "number"
8
- ? [prefix, ...nodes]
9
- : [...prefix.nodes, ...nodes]
10
- : nodes.slice(0);
11
- if (_nodes.length < 2) {
12
- throw new Error("Cannot construct an OID with less than two nodes!");
7
+ constructor() {
8
+ this.encoding = new Uint8Array(0);
9
+ }
10
+ static fromParts(nodes, prefix) {
11
+ let _nodes = typeof prefix === "number" ? [prefix, ...nodes] : nodes;
12
+ if (!prefix || typeof prefix === "number") {
13
+ if (_nodes.length < 2) {
14
+ throw new Error("Cannot construct an OID with less than two nodes!");
15
+ }
16
+ if ((_nodes[0] < 0) || (_nodes[0] > 2)) {
17
+ throw new Error("OIDs first node must be 0, 1, or 2!");
18
+ }
19
+ if (((_nodes[0] < 2) && (_nodes[1] > 39))) {
20
+ throw new Error(`OID Node #2 cannot exceed 39 if node #1 is 0 or 1. Received these nodes: ${_nodes}.`);
21
+ }
13
22
  }
14
- if ((_nodes[0] < 0) || (_nodes[0] > 2)) {
15
- throw new Error("OIDs first node must be 0, 1, or 2!");
23
+ const oid = new ObjectIdentifier();
24
+ if (prefix && typeof prefix !== "number") {
25
+ oid.encoding = Buffer.concat([prefix.encoding, encodeRelativeObjectIdentifier(_nodes)]);
16
26
  }
17
- if (((_nodes[0] < 2) && (_nodes[1] > 39)) || (_nodes[1] > 175)) {
18
- throw new Error("OID Node #2 cannot exceed 39 if node #1 is 0 or 1, and 175 "
19
- + `if node #1 is 2. Received these nodes: ${_nodes}.`);
27
+ else {
28
+ oid.encoding = encodeRelativeObjectIdentifier([
29
+ (_nodes[0] * 40) + _nodes[1],
30
+ ..._nodes.slice(2),
31
+ ]);
20
32
  }
21
- this._nodes = new Uint32Array(_nodes);
22
- }
23
- get uint32ArrayRef() {
24
- return this._nodes;
33
+ return oid;
25
34
  }
26
35
  get nodes() {
27
- return Array.from(this._nodes);
36
+ const subcomponents = decodeRelativeObjectIdentifier(this.encoding);
37
+ return [
38
+ Math.min(2, Math.floor(subcomponents[0] / 40)),
39
+ ((subcomponents[0] >= 80)
40
+ ? (subcomponents[0] - 80)
41
+ : (subcomponents[0] % 40)),
42
+ ...subcomponents.slice(1),
43
+ ];
28
44
  }
29
45
  get dotDelimitedNotation() {
30
- return this._nodes.join(".");
46
+ return this.nodes.join(".");
31
47
  }
32
48
  get asn1Notation() {
33
- return `{ ${Array.from(this._nodes).map((node) => node.toString()).join(" ")} }`;
49
+ return `{ ${Array.from(this.nodes).map((node) => node.toString()).join(" ")} }`;
34
50
  }
35
51
  toString() {
36
52
  return this.dotDelimitedNotation;
@@ -39,7 +55,7 @@ export default class ObjectIdentifier {
39
55
  return this.dotDelimitedNotation;
40
56
  }
41
57
  toBytes() {
42
- return encodeObjectIdentifier(this);
58
+ return Buffer.from(this.encoding);
43
59
  }
44
60
  static fromString(str) {
45
61
  const arcs = [];
@@ -55,24 +71,39 @@ export default class ObjectIdentifier {
55
71
  }
56
72
  const arc = Number.parseInt(str.slice(last, i), 10);
57
73
  arcs.push(arc);
58
- return new ObjectIdentifier(arcs);
74
+ return ObjectIdentifier.fromParts(arcs);
59
75
  }
60
76
  static fromBytes(bytes) {
61
- return decodeObjectIdentifier(bytes);
62
- }
63
- static compare(a, b) {
64
- if (a._nodes.length !== b._nodes.length) {
65
- return false;
77
+ if (bytes.length === 0) {
78
+ throw new errors.ASN1TruncationError("Encoded value was too short to be an OBJECT IDENTIFIER!");
66
79
  }
67
- const len = a._nodes.length;
68
- let i = len - 1;
69
- while (i >= 0) {
70
- if (a._nodes[i] !== b._nodes[i]) {
71
- return false;
80
+ if (bytes[bytes.length - 1] & 0b10000000) {
81
+ throw new errors.ASN1TruncationError("OID was truncated.");
82
+ }
83
+ let current_node = 0;
84
+ for (let i = 1; i < bytes.length; i++) {
85
+ const byte = bytes[i];
86
+ if ((current_node === 0) && (byte === 0x80)) {
87
+ throw new errors.ASN1PaddingError("Prohibited padding on OBJECT IDENTIFIER node.");
88
+ }
89
+ if (byte < 0x80) {
90
+ current_node = 0;
91
+ }
92
+ else {
93
+ current_node++;
72
94
  }
73
- i--;
74
95
  }
75
- return true;
96
+ const oid = new ObjectIdentifier();
97
+ oid.encoding = bytes;
98
+ return oid;
99
+ }
100
+ static fromBytesUnsafe(bytes) {
101
+ const oid = new ObjectIdentifier();
102
+ oid.encoding = bytes;
103
+ return oid;
104
+ }
105
+ static compare(a, b) {
106
+ return Buffer.compare(a.encoding, b.encoding) === 0;
76
107
  }
77
108
  isEqualTo(other) {
78
109
  return ObjectIdentifier.compare(this, other);
@@ -1 +1,3 @@
1
- export default function isObjectDescriptorCharacter(characterCode: number): boolean;
1
+ import isGraphicCharacter from "./isGraphicCharacter.mjs";
2
+ declare const isObjectDescriptorCharacter: typeof isGraphicCharacter;
3
+ export default isObjectDescriptorCharacter;
@@ -1,4 +1,3 @@
1
1
  import isGraphicCharacter from "./isGraphicCharacter.mjs";
2
- export default function isObjectDescriptorCharacter(characterCode) {
3
- return isGraphicCharacter(characterCode);
4
- }
2
+ const isObjectDescriptorCharacter = isGraphicCharacter;
3
+ export default isObjectDescriptorCharacter;
@@ -1 +1,3 @@
1
- export default function isVisibleCharacter(characterCode: number): boolean;
1
+ import isGraphicCharacter from "./isGraphicCharacter.mjs";
2
+ declare const isVisibleCharacter: typeof isGraphicCharacter;
3
+ export default isVisibleCharacter;
@@ -1,4 +1,3 @@
1
1
  import isGraphicCharacter from "./isGraphicCharacter.mjs";
2
- export default function isVisibleCharacter(characterCode) {
3
- return isGraphicCharacter(characterCode);
4
- }
2
+ const isVisibleCharacter = isGraphicCharacter;
3
+ export default isVisibleCharacter;
package/dist/x690.mjs CHANGED
@@ -36,9 +36,6 @@ export default class X690Element extends ASN1Element {
36
36
  if (this.construction !== ASN1Construction.primitive) {
37
37
  throw new errors.ASN1ConstructionError("OBJECT IDENTIFIER cannot be constructed.", this);
38
38
  }
39
- if (this.value.length === 0) {
40
- throw new errors.ASN1TruncationError("Encoded value was too short to be an OBJECT IDENTIFIER!", this);
41
- }
42
39
  return decodeObjectIdentifier(this.value);
43
40
  }
44
41
  set enumerated(value) {
package/package.json CHANGED
@@ -48,5 +48,5 @@
48
48
  "test": "node --test"
49
49
  },
50
50
  "types": "./dist/index.d.mts",
51
- "version": "10.0.0"
51
+ "version": "11.0.0"
52
52
  }