summaryrefslogtreecommitdiffstats
path: root/comm/third_party/asn1js/src/Integer.ts
blob: fd3d1d9e70d7242b93e9dc5255f367e8bc24d990 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import * as pvtsutils from "pvtsutils";
import { BaseBlock, BaseBlockJson, BaseBlockParams } from "./BaseBlock";
import { LocalIntegerValueBlockParams, LocalIntegerValueBlock, LocalIntegerValueBlockJson } from "./internals/LocalIntegerValueBlock";
import { assertBigInt } from "./internals/utils";
import { typeStore } from "./TypeStore";
import { ViewWriter } from "./ViewWriter";

export interface IntegerParams extends BaseBlockParams, LocalIntegerValueBlockParams { }
export type IntegerJson = BaseBlockJson<LocalIntegerValueBlockJson>;

export class Integer extends BaseBlock<LocalIntegerValueBlock, LocalIntegerValueBlockJson> {

  static {
    typeStore.Integer = this;
  }

  public static override NAME = "INTEGER";

  constructor(parameters: IntegerParams = {}) {
    super(parameters, LocalIntegerValueBlock);

    this.idBlock.tagClass = 1; // UNIVERSAL
    this.idBlock.tagNumber = 2; // Integer
  }

  /**
   * Converts Integer into BigInt
   * @throws Throws Error if BigInt is not supported
   * @since 3.0.0
   */
  public toBigInt(): bigint {
    assertBigInt();

    return BigInt(this.valueBlock.toString());
  }

  /**
   * Creates Integer from BigInt value
   * @param value BigInt value
   * @returns ASN.1 Integer
   * @throws Throws Error if BigInt is not supported
   * @since 3.0.0
   */
  public static fromBigInt(value: number | string | bigint | boolean): Integer {
    assertBigInt();

    const bigIntValue = BigInt(value);
    const writer = new ViewWriter();

    const hex = bigIntValue.toString(16).replace(/^-/, "");
    const view = new Uint8Array(pvtsutils.Convert.FromHex(hex));

    if (bigIntValue < 0) {
      // a negative number
      const first = new Uint8Array(view.length + (view[0] & 0x80 ? 1 : 0));
      first[0] |= 0x80;

      const firstInt = BigInt(`0x${pvtsutils.Convert.ToHex(first)}`);
      const secondInt = firstInt + bigIntValue;
      const second = pvtsutils.BufferSourceConverter.toUint8Array(pvtsutils.Convert.FromHex(secondInt.toString(16)));
      second[0] |= 0x80;

      writer.write(second);
    } else {
      // a positive number
      if (view[0] & 0x80) {
        writer.write(new Uint8Array([0]));
      }
      writer.write(view);
    }

    const res = new Integer({
      valueHex: writer.final(),
    });

    return res;
  }

  public convertToDER(): Integer {
    const integer = new Integer({ valueHex: this.valueBlock.valueHexView });

    integer.valueBlock.toDER();

    return integer;
  }

  /**
   * Convert current Integer value from DER to BER format
   * @returns
   */
  public convertFromDER(): Integer {
    return new Integer({
      valueHex: this.valueBlock.valueHexView[0] === 0
        ? this.valueBlock.valueHexView.subarray(1)
        : this.valueBlock.valueHexView,
    });
  }

  protected override onAsciiEncoding(): string {
    return `${(this.constructor as typeof Integer).NAME} : ${this.valueBlock.toString()}`;
  }

}