summaryrefslogtreecommitdiffhomepage
path: root/packages/server/src/helpers/asn1Utils.ts
blob: ecf5931914ab50273a4b47b5b5511787d038ced3 (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
import asn1 from '@lapo/asn1js';

/**
 * Decode an X.509 certificate's ASN1 document (e.g. attStmt.x5c[0])
 */
export function leafCertToASN1Object(leafCert: Buffer): ASN1Object {
  return asn1.decode(leafCert);
}

/**
 * Recursively map an ASN1 document to JSON
 */
export function asn1ObjectToJSON(asn1object: ASN1Object): JASN1 {
  const jasn: JASN1 = {
    type: asn1object.typeName(),
    data: [],
  };

  if (!asn1object.sub) {
    if (asn1object.typeName() === 'BIT_STRING' || asn1object.typeName() === 'OCTET_STRING')
      jasn.data = asn1object.stream.enc.slice(asn1object.posContent(), asn1object.posEnd());
    else jasn.data = asn1object.content();

    return jasn;
  }

  jasn.data = [];
  for (const sub of asn1object.sub) {
    jasn.data.push(asn1ObjectToJSON(sub));
  }

  return jasn;
}

/**
 * Find a specific extension in an ASN1 document by its OBJECT_IDENTIFIER
 */
export function findOID(asn1object: ASN1Object, oid: string): JASN1 | undefined {
  if (!asn1object.sub) {
    return;
  }

  for (const sub of asn1object.sub) {
    const type = sub.typeName();
    const content = sub.content();
    if (type !== 'OBJECT_IDENTIFIER' || (typeof content === 'string' && content.indexOf(oid) < 0)) {
      const result = findOID(sub, oid);
      if (result) {
        return result;
      }
    } else {
      return asn1ObjectToJSON(asn1object);
    }
  }
}

/**
 * Observed output from asn1.decode() relevant to the various helpers
 */
export type ASN1Object = {
  typeName: () => string;
  posContent: () => number;
  posEnd: () => number;
  content: () => string | null;
  stream: {
    enc: Buffer;
  };
  sub?: ASN1Object[];
};

/**
 * JSON-decoded values from an ASN1 document
 */
export type JASN1 = {
  type: string;
  data: JASN1[] | string | Buffer | null;
};