node-opcua-crypto 2.1.2 → 2.2.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.
Files changed (65) hide show
  1. package/.fossa.yml +18 -18
  2. package/.github/FUNDING.yml +12 -12
  3. package/.github/workflows/main.yml +106 -106
  4. package/.prettierrc.js +6 -6
  5. package/LICENSE +23 -23
  6. package/README.md +14 -14
  7. package/dist/source/asn1.d.ts +73 -73
  8. package/dist/source/asn1.js +359 -359
  9. package/dist/source/buffer_utils.d.ts +6 -6
  10. package/dist/source/buffer_utils.js +21 -21
  11. package/dist/source/common.d.ts +14 -14
  12. package/dist/source/common.js +2 -2
  13. package/dist/source/crypto_explore_certificate.d.ts +107 -107
  14. package/dist/source/crypto_explore_certificate.js +601 -601
  15. package/dist/source/crypto_utils.d.ts +76 -76
  16. package/dist/source/crypto_utils.js +329 -329
  17. package/dist/source/derived_keys.d.ts +72 -72
  18. package/dist/source/derived_keys.js +248 -248
  19. package/dist/source/explore_certificate.d.ts +30 -30
  20. package/dist/source/explore_certificate.js +43 -43
  21. package/dist/source/explore_certificate_revocation_list.d.ts +28 -28
  22. package/dist/source/explore_certificate_revocation_list.js +69 -69
  23. package/dist/source/explore_certificate_signing_request.d.ts +13 -13
  24. package/dist/source/explore_certificate_signing_request.js +44 -44
  25. package/dist/source/explore_private_key.d.ts +29 -29
  26. package/dist/source/explore_private_key.js +97 -97
  27. package/dist/source/index.d.ts +13 -13
  28. package/dist/source/index.js +29 -29
  29. package/dist/source/oid_map.d.ts +7 -7
  30. package/dist/source/oid_map.js +303 -303
  31. package/dist/source/public_private_match.d.ts +3 -3
  32. package/dist/source/public_private_match.js +36 -36
  33. package/dist/source/verify_certificate_signature.d.ts +10 -10
  34. package/dist/source/verify_certificate_signature.js +101 -101
  35. package/dist/source_nodejs/index.d.ts +3 -3
  36. package/dist/source_nodejs/index.js +19 -19
  37. package/dist/source_nodejs/read.d.ts +23 -23
  38. package/dist/source_nodejs/read.js +106 -106
  39. package/dist/source_nodejs/read_certificate_revocation_list.d.ts +2 -2
  40. package/dist/source_nodejs/read_certificate_revocation_list.js +27 -27
  41. package/dist/source_nodejs/read_certificate_signing_request.d.ts +3 -3
  42. package/dist/source_nodejs/read_certificate_signing_request.js +27 -27
  43. package/index.d.ts +2 -2
  44. package/index.js +4 -4
  45. package/index_web.js +3 -3
  46. package/package.json +9 -9
  47. package/source/asn1.ts +404 -404
  48. package/source/buffer_utils.ts +18 -18
  49. package/source/crypto_explore_certificate.ts +764 -764
  50. package/source/derived_keys.ts +287 -287
  51. package/source/explore_certificate.ts +66 -66
  52. package/source/explore_certificate_revocation_list.ts +122 -122
  53. package/source/explore_certificate_signing_request.ts +58 -58
  54. package/source/index.ts +13 -13
  55. package/source/oid_map.ts +310 -310
  56. package/source/verify_certificate_signature.ts +105 -105
  57. package/source_nodejs/index.ts +2 -2
  58. package/source_nodejs/read_certificate_revocation_list.ts +14 -14
  59. package/source_nodejs/read_certificate_signing_request.ts +17 -17
  60. package/test_certificate.ts +34 -34
  61. package/tsconfig.json +18 -18
  62. package/tslint.json +34 -34
  63. package/dist/source/certificate_matches_private_key.d.ts +0 -2
  64. package/dist/source/certificate_matches_private_key.js +0 -22
  65. package/dist/source/certificate_matches_private_key.js.map +0 -1
@@ -1,602 +1,602 @@
1
- "use strict";
2
- /**
3
- * @module node_opcua_crypto
4
- */
5
- // ---------------------------------------------------------------------------------------------------------------------
6
- // crypto_explore_certificate
7
- // ---------------------------------------------------------------------------------------------------------------------
8
- // Copyright (c) 2014-2022 - Etienne Rossignon
9
- // Copyright (c) 2022 - Sterfive.com
10
- // ---------------------------------------------------------------------------------------------------------------------
11
- //
12
- // This project is licensed under the terms of the MIT license.
13
- //
14
- // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
15
- // documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
16
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
17
- // permit persons to whom the Software is furnished to do so, subject to the following conditions:
18
- //
19
- // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
20
- // Software.
21
- //
22
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
23
- // WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
24
- // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
25
- // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
- //
27
- //
28
- // ---------------------------------------------------------------------------------------------------------------------
29
- // ASN.1 JavaScript decoder Copyright (c) 2008-2014 Lapo Luchini lapo@lapo.it
30
- // Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby
31
- // granted, provided that the above copyright notice and this permission notice appear in all copies.
32
- // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
33
- // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
34
- // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
35
- // AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
36
- // PERFORMANCE OF THIS SOFTWARE.
37
- // ---------------------------------------------------------------------------------------------------------------------
38
- /*jslint bitwise: true */
39
- // tslint:disable:no-shadowed-variable
40
- Object.defineProperty(exports, "__esModule", { value: true });
41
- exports.combine_der = exports.split_der = exports.exploreCertificate = exports.readTbsCertificate = exports._readExtension = void 0;
42
- // references:
43
- // - http://tools.ietf.org/html/rfc5280
44
- // - http://www-lor.int-evry.fr/~michel/Supports/presentation.pdf
45
- // - ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc
46
- // - pubs.opengroup.org/onlinepubs/009609799/7a_nch02.htm#tagcjh_49_03
47
- // - https://github.com/lapo-luchini/asn1js/blob/master/asn1.js
48
- // - http://lapo.it/asn1js
49
- // - https://www.cs.auckland.ac.nz/~pgut001/dumpasn1.cfg
50
- // - http://pubs.opengroup.org/onlinepubs/009609799/7a_nch02.htm
51
- // - http://stackoverflow.com/questions/5929050/how-does-asn-1-encode-an-object-identifier
52
- // - http://luca.ntop.org/Teaching/Appunti/asn1.html
53
- // note:
54
- // - http://commandlinefanatic.com/cgi-bin/showarticle.cgi?article=art030
55
- // openssl can be also used to discover the content of a DER file
56
- // $ openssl asn1parse -in cert.pem
57
- const assert = require("assert");
58
- const asn1_1 = require("./asn1");
59
- const crypto_utils_1 = require("./crypto_utils");
60
- // Converted from: https://www.cs.auckland.ac.nz/~pgut001/dumpasn1.cfg
61
- // which is made by Peter Gutmann and whose license states:
62
- // You can use this code in whatever way you want,
63
- // as long as you don't try to claim you wrote it.
64
- const doDebug = false;
65
- function _readAttributeTypeAndValue(buffer, block) {
66
- let inner_blocks = (0, asn1_1._readStruct)(buffer, block);
67
- inner_blocks = (0, asn1_1._readStruct)(buffer, inner_blocks[0]);
68
- const data = {
69
- identifier: (0, asn1_1._readObjectIdentifier)(buffer, inner_blocks[0]).name,
70
- value: (0, asn1_1._readValue)(buffer, inner_blocks[1]),
71
- };
72
- const result = {};
73
- for (const [key, value] of Object.entries(data)) {
74
- result[key] = value;
75
- }
76
- return result;
77
- }
78
- function _readRelativeDistinguishedName(buffer, block) {
79
- const inner_blocks = (0, asn1_1._readStruct)(buffer, block);
80
- const data = inner_blocks.map((block) => _readAttributeTypeAndValue(buffer, block));
81
- const result = {};
82
- for (const e of data) {
83
- result[e.identifier] = e.value;
84
- }
85
- return result;
86
- }
87
- function _readName(buffer, block) {
88
- return _readRelativeDistinguishedName(buffer, block);
89
- }
90
- function _readValidity(buffer, block) {
91
- const inner_blocks = (0, asn1_1._readStruct)(buffer, block);
92
- return {
93
- notBefore: (0, asn1_1._readTime)(buffer, inner_blocks[0]),
94
- notAfter: (0, asn1_1._readTime)(buffer, inner_blocks[1]),
95
- };
96
- }
97
- function _readAuthorityKeyIdentifier(buffer) {
98
- /**
99
- * where a CA distributes its public key in the form of a "self-signed"
100
- * certificate, the authority key identifier MAY be omitted. Th
101
- * signature on a self-signed certificate is generated with the private
102
- * key associated with the certificate's subject public key. (This
103
- * proves that the issuer possesses both the public and private keys.)
104
- * In this case, the subject and authority key identifiers would be
105
- * identical, but only the subject key identifier is needed for
106
- * certification path building.
107
- */
108
- // see: https://www.ietf.org/rfc/rfc3280.txt page 25
109
- // AuthorityKeyIdentifier ::= SEQUENCE {
110
- // keyIdentifier [0] KeyIdentifier OPTIONAL,
111
- // authorityCertIssuer [1] GeneralNames OPTIONAL,
112
- // authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
113
- // KeyIdentifier ::= OCTET STRING
114
- const block_info = (0, asn1_1.readTag)(buffer, 0);
115
- const blocks = (0, asn1_1._readStruct)(buffer, block_info);
116
- const keyIdentifier_block = (0, asn1_1._findBlockAtIndex)(blocks, 0);
117
- const authorityCertIssuer_block = (0, asn1_1._findBlockAtIndex)(blocks, 1);
118
- const authorityCertSerialNumber_block = (0, asn1_1._findBlockAtIndex)(blocks, 2);
119
- function _readAuthorityCertIssuer(block) {
120
- const inner_blocks = (0, asn1_1._readStruct)(buffer, block);
121
- const directoryName_block = (0, asn1_1._findBlockAtIndex)(inner_blocks, 4);
122
- if (directoryName_block) {
123
- const a = (0, asn1_1._readStruct)(buffer, directoryName_block);
124
- return (0, asn1_1._readDirectoryName)(buffer, a[0]);
125
- }
126
- else {
127
- throw new Error("Invalid _readAuthorityCertIssuer");
128
- }
129
- }
130
- function _readAuthorityCertIssuerFingerPrint(block) {
131
- const inner_blocks = (0, asn1_1._readStruct)(buffer, block);
132
- const directoryName_block = (0, asn1_1._findBlockAtIndex)(inner_blocks, 4);
133
- if (!directoryName_block) {
134
- return "";
135
- }
136
- const a = (0, asn1_1._readStruct)(buffer, directoryName_block);
137
- if (a.length < 1) {
138
- return "";
139
- }
140
- return directoryName_block ? (0, asn1_1.formatBuffer2DigitHexWithColum)((0, crypto_utils_1.makeSHA1Thumbprint)((0, asn1_1._getBlock)(buffer, a[0]))) : "";
141
- }
142
- const authorityCertIssuer = authorityCertIssuer_block ? _readAuthorityCertIssuer(authorityCertIssuer_block) : null;
143
- const authorityCertIssuerFingerPrint = authorityCertIssuer_block
144
- ? _readAuthorityCertIssuerFingerPrint(authorityCertIssuer_block)
145
- : "";
146
- return {
147
- authorityCertIssuer,
148
- authorityCertIssuerFingerPrint,
149
- serial: authorityCertSerialNumber_block
150
- ? (0, asn1_1.formatBuffer2DigitHexWithColum)((0, asn1_1._getBlock)(buffer, authorityCertSerialNumber_block))
151
- : null,
152
- keyIdentifier: keyIdentifier_block ? (0, asn1_1.formatBuffer2DigitHexWithColum)((0, asn1_1._getBlock)(buffer, keyIdentifier_block)) : null, // can be null for self-signed certf
153
- };
154
- }
155
- /*
156
- Extension ::= SEQUENCE {
157
- extnID OBJECT IDENTIFIER,
158
- critical BOOLEAN DEFAULT FALSE,
159
- extnValue OCTET STRING
160
- -- contains the DER encoding of an ASN.1 value
161
- -- corresponding to the extension type identified
162
- -- by extnID
163
- }
164
-
165
- id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 }
166
-
167
- KeyUsage ::= BIT STRING {
168
- digitalSignature (0),
169
- nonRepudiation (1), -- recent editions of X.509 have
170
- -- renamed this bit to contentCommitment
171
- keyEncipherment (2),
172
- dataEncipherment (3),
173
- keyAgreement (4),
174
- keyCertSign (5),
175
- cRLSign (6),
176
- encipherOnly (7),
177
- decipherOnly (8) }
178
-
179
- extKeyUsage
180
- */
181
- function readBasicConstraint2_5_29_19(buffer, block) {
182
- const block_info = (0, asn1_1.readTag)(buffer, 0);
183
- const inner_blocks = (0, asn1_1._readStruct)(buffer, block_info);
184
- const cA = inner_blocks.length > 0 ? (0, asn1_1._readBooleanValue)(buffer, inner_blocks[0]) : false;
185
- // console.log("buffer[block_info.position] = ", buffer[block_info.position]);
186
- // const cA = buffer[block_info.position] ? true : false;
187
- let pathLengthConstraint = 0;
188
- if (inner_blocks.length > 1) {
189
- pathLengthConstraint = (0, asn1_1._readIntegerValue)(buffer, inner_blocks[1]);
190
- }
191
- return { critical: true, cA, pathLengthConstraint };
192
- }
193
- // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
194
- // GeneralName ::= CHOICE {
195
- // otherName [0] AnotherName,
196
- // rfc822Name [1] IA5String,
197
- // dNSName [2] IA5String,
198
- // x400Address [3] ORAddress,
199
- // directoryName [4] Name,
200
- // ediPartyName [5] EDIPartyName,
201
- // uniformResourceIdentifier [6] IA5String,
202
- // iPAddress [7] OCTET STRING,
203
- // registeredID [8] OBJECT IDENTIFIER }
204
- function _readGeneralNames(buffer, block) {
205
- const _data = {
206
- 1: { name: "rfc822Name", type: "IA5String" },
207
- 2: { name: "dNSName", type: "IA5String" },
208
- 3: { name: "x400Address", type: "ORAddress" },
209
- 4: { name: "directoryName", type: "Name" },
210
- 5: { name: "ediPartyName", type: "EDIPartyName" },
211
- 6: { name: "uniformResourceIdentifier", type: "IA5String" },
212
- 7: { name: "iPAddress", type: "OCTET_STRING" },
213
- 8: { name: "registeredID", type: "OBJECT_IDENTIFIER" },
214
- };
215
- const blocks = (0, asn1_1._readStruct)(buffer, block);
216
- function _readFromType(buffer, block, type) {
217
- switch (type) {
218
- case "IA5String":
219
- return buffer.slice(block.position, block.position + block.length).toString("ascii");
220
- default:
221
- return buffer.slice(block.position, block.position + block.length).toString("hex");
222
- }
223
- }
224
- const n = {};
225
- for (const block of blocks) {
226
- // tslint:disable-next-line: no-bitwise
227
- assert((block.tag & 0x80) === 0x80);
228
- // tslint:disable-next-line: no-bitwise
229
- const t = block.tag & 0x7f;
230
- const type = _data[t];
231
- // istanbul ignore next
232
- if (!type) {
233
- throw new Error(" INVALID TYPE => " + t + "0x" + t.toString(16));
234
- }
235
- n[type.name] = n[type.name] || [];
236
- n[type.name].push(_readFromType(buffer, block, type.type));
237
- }
238
- return n;
239
- }
240
- function _readSubjectAltNames(buffer) {
241
- const block_info = (0, asn1_1.readTag)(buffer, 0);
242
- return _readGeneralNames(buffer, block_info);
243
- }
244
- function readKeyUsage(oid, buffer) {
245
- const block_info = (0, asn1_1.readTag)(buffer, 0);
246
- // get value as BIT STRING
247
- let b2 = 0x00;
248
- let b3 = 0x00;
249
- if (block_info.length > 1) {
250
- // skip first byte, just indicates unused bits which
251
- // will be padded with 0s anyway
252
- // get bytes with flag bits
253
- b2 = buffer[block_info.position + 1];
254
- b3 = block_info.length > 2 ? buffer[block_info.position + 2] : 0;
255
- }
256
- // set flags
257
- return {
258
- // tslint:disable-next-line: no-bitwise
259
- digitalSignature: (b2 & 0x80) === 0x80,
260
- // tslint:disable-next-line: no-bitwise
261
- nonRepudiation: (b2 & 0x40) === 0x40,
262
- // tslint:disable-next-line: no-bitwise
263
- keyEncipherment: (b2 & 0x20) === 0x20,
264
- // tslint:disable-next-line: no-bitwise
265
- dataEncipherment: (b2 & 0x10) === 0x10,
266
- // tslint:disable-next-line: no-bitwise
267
- keyAgreement: (b2 & 0x08) === 0x08,
268
- // tslint:disable-next-line: no-bitwise
269
- keyCertSign: (b2 & 0x04) === 0x04,
270
- // tslint:disable-next-line: no-bitwise
271
- cRLSign: (b2 & 0x02) === 0x02,
272
- // tslint:disable-next-line: no-bitwise
273
- encipherOnly: (b2 & 0x01) === 0x01,
274
- // tslint:disable-next-line: no-bitwise
275
- decipherOnly: (b3 & 0x80) === 0x80,
276
- };
277
- }
278
- function readExtKeyUsage(oid, buffer) {
279
- assert(oid === "2.5.29.37");
280
- // see https://tools.ietf.org/html/rfc5280#section-4.2.1.12
281
- const block_info = (0, asn1_1.readTag)(buffer, 0);
282
- const inner_blocks = (0, asn1_1._readStruct)(buffer, block_info);
283
- const extKeyUsage = {
284
- serverAuth: false,
285
- clientAuth: false,
286
- codeSigning: false,
287
- emailProtection: false,
288
- timeStamping: false,
289
- ipsecEndSystem: false,
290
- ipsecTunnel: false,
291
- ipsecUser: false,
292
- ocspSigning: false,
293
- };
294
- for (const block of inner_blocks) {
295
- const identifier = (0, asn1_1._readObjectIdentifier)(buffer, block);
296
- extKeyUsage[identifier.name] = true;
297
- }
298
- /*
299
-
300
- id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }
301
-
302
- id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 }
303
- -- TLS WWW server authentication
304
- -- Key usage bits that may be consistent: digitalSignature,
305
- -- keyEncipherment or keyAgreement
306
-
307
- id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 }
308
- -- TLS WWW client authentication
309
- -- Key usage bits that may be consistent: digitalSignature
310
- -- and/or keyAgreement
311
-
312
- id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 }
313
- -- Signing of downloadable executable code
314
- -- Key usage bits that may be consistent: digitalSignature
315
-
316
- id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 }
317
- -- Email protection
318
- -- Key usage bits that may be consistent: digitalSignature,
319
- -- nonRepudiation, and/or (keyEncipherment or keyAgreement)
320
-
321
- id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 }
322
- -- Binding the hash of an object to a time
323
- -- Key usage bits that may be consistent: digitalSignature
324
- -- and/or nonRepudiation
325
-
326
- id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 }
327
- -- Signing OCSP responses
328
- -- Key usage bits that may be consistent: digitalSignature
329
- -- and/or nonRepudiation
330
-
331
- */
332
- // set flags
333
- return extKeyUsage;
334
- }
335
- function _readSubjectPublicKey(buffer) {
336
- const block_info = (0, asn1_1.readTag)(buffer, 0);
337
- const blocks = (0, asn1_1._readStruct)(buffer, block_info);
338
- return {
339
- modulus: buffer.slice(blocks[0].position + 1, blocks[0].position + blocks[0].length),
340
- };
341
- }
342
- /*
343
- Extension ::= SEQUENCE {
344
- extnID OBJECT IDENTIFIER,
345
- critical BOOLEAN DEFAULT FALSE,
346
- extnValue OCTET STRING
347
- -- contains the DER encoding of an ASN.1 value
348
- -- corresponding to the extension type identified
349
- -- by extnID
350
- }
351
- */
352
- function _readExtension(buffer, block) {
353
- const inner_blocks = (0, asn1_1._readStruct)(buffer, block);
354
- if (inner_blocks.length === 3) {
355
- assert(inner_blocks[1].tag === asn1_1.TagType.BOOLEAN);
356
- inner_blocks[1] = inner_blocks[2];
357
- }
358
- const identifier = (0, asn1_1._readObjectIdentifier)(buffer, inner_blocks[0]);
359
- const buf = (0, asn1_1._getBlock)(buffer, inner_blocks[1]);
360
- let value = null;
361
- switch (identifier.name) {
362
- case "subjectKeyIdentifier":
363
- /* from https://tools.ietf.org/html/rfc3280#section-4.1 :
364
- For CA certificates, subject key identifiers SHOULD be derived from
365
- the public key or a method that generates unique values. Two common
366
- methods for generating key identifiers from the public key are:
367
-
368
- (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
369
- value of the BIT STRING subjectPublicKey (excluding the tag,
370
- length, and number of unused bits).
371
-
372
- (2) The keyIdentifier is composed of a four bit type field with
373
- the value 0100 followed by the least significant 60 bits of the
374
- SHA-1 hash of the value of the BIT STRING subjectPublicKey
375
- (excluding the tag, length, and number of unused bit string bits).
376
- */
377
- value = (0, asn1_1.formatBuffer2DigitHexWithColum)((0, asn1_1._readOctetString)(buffer, inner_blocks[1]));
378
- break;
379
- case "subjectAltName":
380
- value = _readSubjectAltNames(buf);
381
- break;
382
- case "authorityKeyIdentifier":
383
- value = _readAuthorityKeyIdentifier(buf);
384
- break;
385
- case "basicConstraints":
386
- value = readBasicConstraint2_5_29_19(buf, inner_blocks[1]); // "2.5.29.19":
387
- // "basicConstraints ( not implemented yet) " + buf.toString("hex");
388
- break;
389
- case "certExtension": // Netscape
390
- value = "basicConstraints ( not implemented yet) " + buf.toString("hex");
391
- break;
392
- case "extKeyUsage":
393
- value = readExtKeyUsage(identifier.oid, buf);
394
- break;
395
- case "keyUsage":
396
- value = readKeyUsage(identifier.oid, buf);
397
- break;
398
- default:
399
- value = "Unknown " + identifier.name + buf.toString("hex");
400
- }
401
- return {
402
- identifier,
403
- value,
404
- };
405
- }
406
- exports._readExtension = _readExtension;
407
- // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
408
- function _readExtensions(buffer, block) {
409
- assert(block.tag === 0xa3);
410
- let inner_blocks = (0, asn1_1._readStruct)(buffer, block);
411
- inner_blocks = (0, asn1_1._readStruct)(buffer, inner_blocks[0]);
412
- const extensions = inner_blocks.map((block) => _readExtension(buffer, block));
413
- const result = {};
414
- for (const e of extensions) {
415
- result[e.identifier.name] = e.value;
416
- }
417
- return result;
418
- }
419
- /*
420
- SEQUENCE {
421
- 204 13: SEQUENCE {
422
- 206 9: OBJECT IDENTIFIER
423
- : rsaEncryption (1 2 840 113549 1 1 1)
424
- 217 0: NULL
425
- : }
426
- 219 141: BIT STRING, encapsulates {
427
- 223 137: SEQUENCE {
428
- 226 129: INTEGER
429
- : 00 C2 D7 97 6D 28 70 AA 5B CF 23 2E 80 70 39 EE
430
- : DB 6F D5 2D D5 6A 4F 7A 34 2D F9 22 72 47 70 1D
431
- : EF 80 E9 CA 30 8C 00 C4 9A 6E 5B 45 B4 6E A5 E6
432
- : 6C 94 0D FA 91 E9 40 FC 25 9D C7 B7 68 19 56 8F
433
- : 11 70 6A D7 F1 C9 11 4F 3A 7E 3F 99 8D 6E 76 A5
434
- : 74 5F 5E A4 55 53 E5 C7 68 36 53 C7 1D 3B 12 A6
435
- : 85 FE BD 6E A1 CA DF 35 50 AC 08 D7 B9 B4 7E 5C
436
- : FE E2 A3 2C D1 23 84 AA 98 C0 9B 66 18 9A 68 47
437
- : E9
438
- 358 3: INTEGER 65537
439
- : }
440
- : }
441
- : }
442
- */
443
- function _readSubjectPublicKeyInfo(buffer, block) {
444
- const inner_blocks = (0, asn1_1._readStruct)(buffer, block);
445
- // algorithm identifier
446
- const algorithm = (0, asn1_1._readAlgorithmIdentifier)(buffer, inner_blocks[0]);
447
- //const parameters = _readBitString(buffer,inner_blocks[1]);
448
- const subjectPublicKey = (0, asn1_1._readBitString)(buffer, inner_blocks[1]);
449
- // read the 2 big integers of the key
450
- const data = subjectPublicKey.data;
451
- const values = (0, asn1_1._readListOfInteger)(data);
452
- // xx const value = _readListOfInteger(data);
453
- return {
454
- algorithm: algorithm.identifier,
455
- keyLength: (values[0].length - 1),
456
- subjectPublicKey: _readSubjectPublicKey(subjectPublicKey.data),
457
- //xx values: values,
458
- //xx values_length : values.map(function (a){ return a.length; })
459
- };
460
- }
461
- function _readSubjectECCPublicKeyInfo(buffer, block) {
462
- const inner_blocks = (0, asn1_1._readStruct)(buffer, block);
463
- // first parameter is the second element of the first block, which is why we have another algorithm
464
- const algorithm = (0, asn1_1._readECCAlgorithmIdentifier)(buffer, inner_blocks[0]);
465
- // the public key is already in bit format, we just need to read it
466
- const subjectPublicKey = (0, asn1_1._readBitString)(buffer, inner_blocks[1]);
467
- // take out the data which is the entirity of our public key
468
- const data = subjectPublicKey.data;
469
- return {
470
- algorithm: algorithm.identifier,
471
- keyLength: (data.length - 1),
472
- subjectPublicKey: {
473
- modulus: data
474
- }
475
- };
476
- }
477
- function readTbsCertificate(buffer, block) {
478
- const blocks = (0, asn1_1._readStruct)(buffer, block);
479
- let version, serialNumber, signature, issuer, validity, subject, subjectFingerPrint, extensions;
480
- let subjectPublicKeyInfo;
481
- if (blocks.length === 6) {
482
- // X509 Version 1:
483
- version = 1;
484
- serialNumber = (0, asn1_1.formatBuffer2DigitHexWithColum)((0, asn1_1._readLongIntegerValue)(buffer, blocks[0]));
485
- signature = (0, asn1_1._readAlgorithmIdentifier)(buffer, blocks[1]);
486
- issuer = _readName(buffer, blocks[2]);
487
- validity = _readValidity(buffer, blocks[3]);
488
- subject = _readName(buffer, blocks[4]);
489
- subjectFingerPrint = (0, asn1_1.formatBuffer2DigitHexWithColum)((0, crypto_utils_1.makeSHA1Thumbprint)((0, asn1_1._getBlock)(buffer, blocks[4])));
490
- subjectPublicKeyInfo = _readSubjectPublicKeyInfo(buffer, blocks[5]);
491
- extensions = null;
492
- }
493
- else {
494
- // X509 Version 3:
495
- const version_block = (0, asn1_1._findBlockAtIndex)(blocks, 0);
496
- if (!version_block) {
497
- throw new Error("cannot find version block");
498
- }
499
- version = (0, asn1_1._readVersionValue)(buffer, version_block) + 1;
500
- serialNumber = (0, asn1_1.formatBuffer2DigitHexWithColum)((0, asn1_1._readLongIntegerValue)(buffer, blocks[1]));
501
- signature = (0, asn1_1._readAlgorithmIdentifier)(buffer, blocks[2]);
502
- issuer = _readName(buffer, blocks[3]);
503
- validity = _readValidity(buffer, blocks[4]);
504
- subject = _readName(buffer, blocks[5]);
505
- subjectFingerPrint = (0, asn1_1.formatBuffer2DigitHexWithColum)((0, crypto_utils_1.makeSHA1Thumbprint)((0, asn1_1._getBlock)(buffer, blocks[5])));
506
- const inner_block = (0, asn1_1._readStruct)(buffer, blocks[6]);
507
- const what_type = (0, asn1_1._readAlgorithmIdentifier)(buffer, inner_block[0]).identifier;
508
- switch (what_type) {
509
- case "rsaEncryption": {
510
- subjectPublicKeyInfo = _readSubjectPublicKeyInfo(buffer, blocks[6]);
511
- break;
512
- }
513
- case "ecPublicKey":
514
- default: {
515
- subjectPublicKeyInfo = _readSubjectECCPublicKeyInfo(buffer, blocks[6]);
516
- break;
517
- }
518
- }
519
- const extensionBlock = (0, asn1_1._findBlockAtIndex)(blocks, 3);
520
- if (!extensionBlock) {
521
- // tslint:disable-next-line: no-console
522
- console.log("X509 certificate is invalid : cannot find extension block version =" + version_block);
523
- extensions = null;
524
- }
525
- else {
526
- extensions = _readExtensions(buffer, extensionBlock);
527
- }
528
- }
529
- return {
530
- version,
531
- serialNumber,
532
- signature,
533
- issuer,
534
- validity,
535
- subject,
536
- subjectFingerPrint,
537
- subjectPublicKeyInfo,
538
- extensions,
539
- };
540
- }
541
- exports.readTbsCertificate = readTbsCertificate;
542
- /**
543
- * explore a certificate structure
544
- * @param certificate
545
- * @returns a json object that exhibits the internal data of the certificate
546
- */
547
- function exploreCertificate(certificate) {
548
- assert(certificate instanceof Buffer);
549
- if (!certificate._exploreCertificate_cache) {
550
- const block_info = (0, asn1_1.readTag)(certificate, 0);
551
- const blocks = (0, asn1_1._readStruct)(certificate, block_info);
552
- certificate._exploreCertificate_cache = {
553
- tbsCertificate: readTbsCertificate(certificate, blocks[0]),
554
- signatureAlgorithm: (0, asn1_1._readAlgorithmIdentifier)(certificate, blocks[1]),
555
- signatureValue: (0, asn1_1._readSignatureValue)(certificate, blocks[2]),
556
- };
557
- }
558
- return certificate._exploreCertificate_cache;
559
- }
560
- exports.exploreCertificate = exploreCertificate;
561
- /**
562
- * @method split_der
563
- * split a multi chain certificates
564
- * @param certificateChain the certificate chain in der (binary) format}
565
- * @returns an array of Der , each element of the array is one certificate of the chain
566
- */
567
- function split_der(certificateChain) {
568
- const certificate_chain = [];
569
- do {
570
- const block_info = (0, asn1_1.readTag)(certificateChain, 0);
571
- const length = block_info.position + block_info.length;
572
- const der_certificate = certificateChain.slice(0, length);
573
- certificate_chain.push(der_certificate);
574
- certificateChain = certificateChain.slice(length);
575
- } while (certificateChain.length > 0);
576
- return certificate_chain;
577
- }
578
- exports.split_der = split_der;
579
- /**
580
- * @method combine_der
581
- * combine an array of certificates into a single blob
582
- * @param certificates a array with the individual DER certificates of the chain
583
- * @return a concatenated buffer containing the certificates
584
- */
585
- function combine_der(certificates) {
586
- // perform some sanity check
587
- for (const cert of certificates) {
588
- const b = split_der(cert);
589
- let sum = 0;
590
- b.forEach((block) => {
591
- const block_info = (0, asn1_1.readTag)(block, 0);
592
- //xx console.log("xxxx" ,cert.length,block_info);
593
- //xx console.log(cert.toString("base64"));
594
- assert(block_info.position + block_info.length === block.length);
595
- sum += block.length;
596
- });
597
- assert(sum === cert.length);
598
- }
599
- return Buffer.concat(certificates);
600
- }
601
- exports.combine_der = combine_der;
1
+ "use strict";
2
+ /**
3
+ * @module node_opcua_crypto
4
+ */
5
+ // ---------------------------------------------------------------------------------------------------------------------
6
+ // crypto_explore_certificate
7
+ // ---------------------------------------------------------------------------------------------------------------------
8
+ // Copyright (c) 2014-2022 - Etienne Rossignon
9
+ // Copyright (c) 2022 - Sterfive.com
10
+ // ---------------------------------------------------------------------------------------------------------------------
11
+ //
12
+ // This project is licensed under the terms of the MIT license.
13
+ //
14
+ // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
15
+ // documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
16
+ // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
17
+ // permit persons to whom the Software is furnished to do so, subject to the following conditions:
18
+ //
19
+ // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
20
+ // Software.
21
+ //
22
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
23
+ // WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
24
+ // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
25
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
+ //
27
+ //
28
+ // ---------------------------------------------------------------------------------------------------------------------
29
+ // ASN.1 JavaScript decoder Copyright (c) 2008-2014 Lapo Luchini lapo@lapo.it
30
+ // Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby
31
+ // granted, provided that the above copyright notice and this permission notice appear in all copies.
32
+ // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
33
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
34
+ // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
35
+ // AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
36
+ // PERFORMANCE OF THIS SOFTWARE.
37
+ // ---------------------------------------------------------------------------------------------------------------------
38
+ /*jslint bitwise: true */
39
+ // tslint:disable:no-shadowed-variable
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.combine_der = exports.split_der = exports.exploreCertificate = exports.readTbsCertificate = exports._readExtension = void 0;
42
+ // references:
43
+ // - http://tools.ietf.org/html/rfc5280
44
+ // - http://www-lor.int-evry.fr/~michel/Supports/presentation.pdf
45
+ // - ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc
46
+ // - pubs.opengroup.org/onlinepubs/009609799/7a_nch02.htm#tagcjh_49_03
47
+ // - https://github.com/lapo-luchini/asn1js/blob/master/asn1.js
48
+ // - http://lapo.it/asn1js
49
+ // - https://www.cs.auckland.ac.nz/~pgut001/dumpasn1.cfg
50
+ // - http://pubs.opengroup.org/onlinepubs/009609799/7a_nch02.htm
51
+ // - http://stackoverflow.com/questions/5929050/how-does-asn-1-encode-an-object-identifier
52
+ // - http://luca.ntop.org/Teaching/Appunti/asn1.html
53
+ // note:
54
+ // - http://commandlinefanatic.com/cgi-bin/showarticle.cgi?article=art030
55
+ // openssl can be also used to discover the content of a DER file
56
+ // $ openssl asn1parse -in cert.pem
57
+ const assert = require("assert");
58
+ const asn1_1 = require("./asn1");
59
+ const crypto_utils_1 = require("./crypto_utils");
60
+ // Converted from: https://www.cs.auckland.ac.nz/~pgut001/dumpasn1.cfg
61
+ // which is made by Peter Gutmann and whose license states:
62
+ // You can use this code in whatever way you want,
63
+ // as long as you don't try to claim you wrote it.
64
+ const doDebug = false;
65
+ function _readAttributeTypeAndValue(buffer, block) {
66
+ let inner_blocks = (0, asn1_1._readStruct)(buffer, block);
67
+ inner_blocks = (0, asn1_1._readStruct)(buffer, inner_blocks[0]);
68
+ const data = {
69
+ identifier: (0, asn1_1._readObjectIdentifier)(buffer, inner_blocks[0]).name,
70
+ value: (0, asn1_1._readValue)(buffer, inner_blocks[1]),
71
+ };
72
+ const result = {};
73
+ for (const [key, value] of Object.entries(data)) {
74
+ result[key] = value;
75
+ }
76
+ return result;
77
+ }
78
+ function _readRelativeDistinguishedName(buffer, block) {
79
+ const inner_blocks = (0, asn1_1._readStruct)(buffer, block);
80
+ const data = inner_blocks.map((block) => _readAttributeTypeAndValue(buffer, block));
81
+ const result = {};
82
+ for (const e of data) {
83
+ result[e.identifier] = e.value;
84
+ }
85
+ return result;
86
+ }
87
+ function _readName(buffer, block) {
88
+ return _readRelativeDistinguishedName(buffer, block);
89
+ }
90
+ function _readValidity(buffer, block) {
91
+ const inner_blocks = (0, asn1_1._readStruct)(buffer, block);
92
+ return {
93
+ notBefore: (0, asn1_1._readTime)(buffer, inner_blocks[0]),
94
+ notAfter: (0, asn1_1._readTime)(buffer, inner_blocks[1]),
95
+ };
96
+ }
97
+ function _readAuthorityKeyIdentifier(buffer) {
98
+ /**
99
+ * where a CA distributes its public key in the form of a "self-signed"
100
+ * certificate, the authority key identifier MAY be omitted. Th
101
+ * signature on a self-signed certificate is generated with the private
102
+ * key associated with the certificate's subject public key. (This
103
+ * proves that the issuer possesses both the public and private keys.)
104
+ * In this case, the subject and authority key identifiers would be
105
+ * identical, but only the subject key identifier is needed for
106
+ * certification path building.
107
+ */
108
+ // see: https://www.ietf.org/rfc/rfc3280.txt page 25
109
+ // AuthorityKeyIdentifier ::= SEQUENCE {
110
+ // keyIdentifier [0] KeyIdentifier OPTIONAL,
111
+ // authorityCertIssuer [1] GeneralNames OPTIONAL,
112
+ // authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
113
+ // KeyIdentifier ::= OCTET STRING
114
+ const block_info = (0, asn1_1.readTag)(buffer, 0);
115
+ const blocks = (0, asn1_1._readStruct)(buffer, block_info);
116
+ const keyIdentifier_block = (0, asn1_1._findBlockAtIndex)(blocks, 0);
117
+ const authorityCertIssuer_block = (0, asn1_1._findBlockAtIndex)(blocks, 1);
118
+ const authorityCertSerialNumber_block = (0, asn1_1._findBlockAtIndex)(blocks, 2);
119
+ function _readAuthorityCertIssuer(block) {
120
+ const inner_blocks = (0, asn1_1._readStruct)(buffer, block);
121
+ const directoryName_block = (0, asn1_1._findBlockAtIndex)(inner_blocks, 4);
122
+ if (directoryName_block) {
123
+ const a = (0, asn1_1._readStruct)(buffer, directoryName_block);
124
+ return (0, asn1_1._readDirectoryName)(buffer, a[0]);
125
+ }
126
+ else {
127
+ throw new Error("Invalid _readAuthorityCertIssuer");
128
+ }
129
+ }
130
+ function _readAuthorityCertIssuerFingerPrint(block) {
131
+ const inner_blocks = (0, asn1_1._readStruct)(buffer, block);
132
+ const directoryName_block = (0, asn1_1._findBlockAtIndex)(inner_blocks, 4);
133
+ if (!directoryName_block) {
134
+ return "";
135
+ }
136
+ const a = (0, asn1_1._readStruct)(buffer, directoryName_block);
137
+ if (a.length < 1) {
138
+ return "";
139
+ }
140
+ return directoryName_block ? (0, asn1_1.formatBuffer2DigitHexWithColum)((0, crypto_utils_1.makeSHA1Thumbprint)((0, asn1_1._getBlock)(buffer, a[0]))) : "";
141
+ }
142
+ const authorityCertIssuer = authorityCertIssuer_block ? _readAuthorityCertIssuer(authorityCertIssuer_block) : null;
143
+ const authorityCertIssuerFingerPrint = authorityCertIssuer_block
144
+ ? _readAuthorityCertIssuerFingerPrint(authorityCertIssuer_block)
145
+ : "";
146
+ return {
147
+ authorityCertIssuer,
148
+ authorityCertIssuerFingerPrint,
149
+ serial: authorityCertSerialNumber_block
150
+ ? (0, asn1_1.formatBuffer2DigitHexWithColum)((0, asn1_1._getBlock)(buffer, authorityCertSerialNumber_block))
151
+ : null,
152
+ keyIdentifier: keyIdentifier_block ? (0, asn1_1.formatBuffer2DigitHexWithColum)((0, asn1_1._getBlock)(buffer, keyIdentifier_block)) : null, // can be null for self-signed certf
153
+ };
154
+ }
155
+ /*
156
+ Extension ::= SEQUENCE {
157
+ extnID OBJECT IDENTIFIER,
158
+ critical BOOLEAN DEFAULT FALSE,
159
+ extnValue OCTET STRING
160
+ -- contains the DER encoding of an ASN.1 value
161
+ -- corresponding to the extension type identified
162
+ -- by extnID
163
+ }
164
+
165
+ id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 }
166
+
167
+ KeyUsage ::= BIT STRING {
168
+ digitalSignature (0),
169
+ nonRepudiation (1), -- recent editions of X.509 have
170
+ -- renamed this bit to contentCommitment
171
+ keyEncipherment (2),
172
+ dataEncipherment (3),
173
+ keyAgreement (4),
174
+ keyCertSign (5),
175
+ cRLSign (6),
176
+ encipherOnly (7),
177
+ decipherOnly (8) }
178
+
179
+ extKeyUsage
180
+ */
181
+ function readBasicConstraint2_5_29_19(buffer, block) {
182
+ const block_info = (0, asn1_1.readTag)(buffer, 0);
183
+ const inner_blocks = (0, asn1_1._readStruct)(buffer, block_info);
184
+ const cA = inner_blocks.length > 0 ? (0, asn1_1._readBooleanValue)(buffer, inner_blocks[0]) : false;
185
+ // console.log("buffer[block_info.position] = ", buffer[block_info.position]);
186
+ // const cA = buffer[block_info.position] ? true : false;
187
+ let pathLengthConstraint = 0;
188
+ if (inner_blocks.length > 1) {
189
+ pathLengthConstraint = (0, asn1_1._readIntegerValue)(buffer, inner_blocks[1]);
190
+ }
191
+ return { critical: true, cA, pathLengthConstraint };
192
+ }
193
+ // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
194
+ // GeneralName ::= CHOICE {
195
+ // otherName [0] AnotherName,
196
+ // rfc822Name [1] IA5String,
197
+ // dNSName [2] IA5String,
198
+ // x400Address [3] ORAddress,
199
+ // directoryName [4] Name,
200
+ // ediPartyName [5] EDIPartyName,
201
+ // uniformResourceIdentifier [6] IA5String,
202
+ // iPAddress [7] OCTET STRING,
203
+ // registeredID [8] OBJECT IDENTIFIER }
204
+ function _readGeneralNames(buffer, block) {
205
+ const _data = {
206
+ 1: { name: "rfc822Name", type: "IA5String" },
207
+ 2: { name: "dNSName", type: "IA5String" },
208
+ 3: { name: "x400Address", type: "ORAddress" },
209
+ 4: { name: "directoryName", type: "Name" },
210
+ 5: { name: "ediPartyName", type: "EDIPartyName" },
211
+ 6: { name: "uniformResourceIdentifier", type: "IA5String" },
212
+ 7: { name: "iPAddress", type: "OCTET_STRING" },
213
+ 8: { name: "registeredID", type: "OBJECT_IDENTIFIER" },
214
+ };
215
+ const blocks = (0, asn1_1._readStruct)(buffer, block);
216
+ function _readFromType(buffer, block, type) {
217
+ switch (type) {
218
+ case "IA5String":
219
+ return buffer.slice(block.position, block.position + block.length).toString("ascii");
220
+ default:
221
+ return buffer.slice(block.position, block.position + block.length).toString("hex");
222
+ }
223
+ }
224
+ const n = {};
225
+ for (const block of blocks) {
226
+ // tslint:disable-next-line: no-bitwise
227
+ assert((block.tag & 0x80) === 0x80);
228
+ // tslint:disable-next-line: no-bitwise
229
+ const t = block.tag & 0x7f;
230
+ const type = _data[t];
231
+ // istanbul ignore next
232
+ if (!type) {
233
+ throw new Error(" INVALID TYPE => " + t + "0x" + t.toString(16));
234
+ }
235
+ n[type.name] = n[type.name] || [];
236
+ n[type.name].push(_readFromType(buffer, block, type.type));
237
+ }
238
+ return n;
239
+ }
240
+ function _readSubjectAltNames(buffer) {
241
+ const block_info = (0, asn1_1.readTag)(buffer, 0);
242
+ return _readGeneralNames(buffer, block_info);
243
+ }
244
+ function readKeyUsage(oid, buffer) {
245
+ const block_info = (0, asn1_1.readTag)(buffer, 0);
246
+ // get value as BIT STRING
247
+ let b2 = 0x00;
248
+ let b3 = 0x00;
249
+ if (block_info.length > 1) {
250
+ // skip first byte, just indicates unused bits which
251
+ // will be padded with 0s anyway
252
+ // get bytes with flag bits
253
+ b2 = buffer[block_info.position + 1];
254
+ b3 = block_info.length > 2 ? buffer[block_info.position + 2] : 0;
255
+ }
256
+ // set flags
257
+ return {
258
+ // tslint:disable-next-line: no-bitwise
259
+ digitalSignature: (b2 & 0x80) === 0x80,
260
+ // tslint:disable-next-line: no-bitwise
261
+ nonRepudiation: (b2 & 0x40) === 0x40,
262
+ // tslint:disable-next-line: no-bitwise
263
+ keyEncipherment: (b2 & 0x20) === 0x20,
264
+ // tslint:disable-next-line: no-bitwise
265
+ dataEncipherment: (b2 & 0x10) === 0x10,
266
+ // tslint:disable-next-line: no-bitwise
267
+ keyAgreement: (b2 & 0x08) === 0x08,
268
+ // tslint:disable-next-line: no-bitwise
269
+ keyCertSign: (b2 & 0x04) === 0x04,
270
+ // tslint:disable-next-line: no-bitwise
271
+ cRLSign: (b2 & 0x02) === 0x02,
272
+ // tslint:disable-next-line: no-bitwise
273
+ encipherOnly: (b2 & 0x01) === 0x01,
274
+ // tslint:disable-next-line: no-bitwise
275
+ decipherOnly: (b3 & 0x80) === 0x80,
276
+ };
277
+ }
278
+ function readExtKeyUsage(oid, buffer) {
279
+ assert(oid === "2.5.29.37");
280
+ // see https://tools.ietf.org/html/rfc5280#section-4.2.1.12
281
+ const block_info = (0, asn1_1.readTag)(buffer, 0);
282
+ const inner_blocks = (0, asn1_1._readStruct)(buffer, block_info);
283
+ const extKeyUsage = {
284
+ serverAuth: false,
285
+ clientAuth: false,
286
+ codeSigning: false,
287
+ emailProtection: false,
288
+ timeStamping: false,
289
+ ipsecEndSystem: false,
290
+ ipsecTunnel: false,
291
+ ipsecUser: false,
292
+ ocspSigning: false,
293
+ };
294
+ for (const block of inner_blocks) {
295
+ const identifier = (0, asn1_1._readObjectIdentifier)(buffer, block);
296
+ extKeyUsage[identifier.name] = true;
297
+ }
298
+ /*
299
+
300
+ id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }
301
+
302
+ id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 }
303
+ -- TLS WWW server authentication
304
+ -- Key usage bits that may be consistent: digitalSignature,
305
+ -- keyEncipherment or keyAgreement
306
+
307
+ id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 }
308
+ -- TLS WWW client authentication
309
+ -- Key usage bits that may be consistent: digitalSignature
310
+ -- and/or keyAgreement
311
+
312
+ id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 }
313
+ -- Signing of downloadable executable code
314
+ -- Key usage bits that may be consistent: digitalSignature
315
+
316
+ id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 }
317
+ -- Email protection
318
+ -- Key usage bits that may be consistent: digitalSignature,
319
+ -- nonRepudiation, and/or (keyEncipherment or keyAgreement)
320
+
321
+ id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 }
322
+ -- Binding the hash of an object to a time
323
+ -- Key usage bits that may be consistent: digitalSignature
324
+ -- and/or nonRepudiation
325
+
326
+ id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 }
327
+ -- Signing OCSP responses
328
+ -- Key usage bits that may be consistent: digitalSignature
329
+ -- and/or nonRepudiation
330
+
331
+ */
332
+ // set flags
333
+ return extKeyUsage;
334
+ }
335
+ function _readSubjectPublicKey(buffer) {
336
+ const block_info = (0, asn1_1.readTag)(buffer, 0);
337
+ const blocks = (0, asn1_1._readStruct)(buffer, block_info);
338
+ return {
339
+ modulus: buffer.slice(blocks[0].position + 1, blocks[0].position + blocks[0].length),
340
+ };
341
+ }
342
+ /*
343
+ Extension ::= SEQUENCE {
344
+ extnID OBJECT IDENTIFIER,
345
+ critical BOOLEAN DEFAULT FALSE,
346
+ extnValue OCTET STRING
347
+ -- contains the DER encoding of an ASN.1 value
348
+ -- corresponding to the extension type identified
349
+ -- by extnID
350
+ }
351
+ */
352
+ function _readExtension(buffer, block) {
353
+ const inner_blocks = (0, asn1_1._readStruct)(buffer, block);
354
+ if (inner_blocks.length === 3) {
355
+ assert(inner_blocks[1].tag === asn1_1.TagType.BOOLEAN);
356
+ inner_blocks[1] = inner_blocks[2];
357
+ }
358
+ const identifier = (0, asn1_1._readObjectIdentifier)(buffer, inner_blocks[0]);
359
+ const buf = (0, asn1_1._getBlock)(buffer, inner_blocks[1]);
360
+ let value = null;
361
+ switch (identifier.name) {
362
+ case "subjectKeyIdentifier":
363
+ /* from https://tools.ietf.org/html/rfc3280#section-4.1 :
364
+ For CA certificates, subject key identifiers SHOULD be derived from
365
+ the public key or a method that generates unique values. Two common
366
+ methods for generating key identifiers from the public key are:
367
+
368
+ (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
369
+ value of the BIT STRING subjectPublicKey (excluding the tag,
370
+ length, and number of unused bits).
371
+
372
+ (2) The keyIdentifier is composed of a four bit type field with
373
+ the value 0100 followed by the least significant 60 bits of the
374
+ SHA-1 hash of the value of the BIT STRING subjectPublicKey
375
+ (excluding the tag, length, and number of unused bit string bits).
376
+ */
377
+ value = (0, asn1_1.formatBuffer2DigitHexWithColum)((0, asn1_1._readOctetString)(buffer, inner_blocks[1]));
378
+ break;
379
+ case "subjectAltName":
380
+ value = _readSubjectAltNames(buf);
381
+ break;
382
+ case "authorityKeyIdentifier":
383
+ value = _readAuthorityKeyIdentifier(buf);
384
+ break;
385
+ case "basicConstraints":
386
+ value = readBasicConstraint2_5_29_19(buf, inner_blocks[1]); // "2.5.29.19":
387
+ // "basicConstraints ( not implemented yet) " + buf.toString("hex");
388
+ break;
389
+ case "certExtension": // Netscape
390
+ value = "basicConstraints ( not implemented yet) " + buf.toString("hex");
391
+ break;
392
+ case "extKeyUsage":
393
+ value = readExtKeyUsage(identifier.oid, buf);
394
+ break;
395
+ case "keyUsage":
396
+ value = readKeyUsage(identifier.oid, buf);
397
+ break;
398
+ default:
399
+ value = "Unknown " + identifier.name + buf.toString("hex");
400
+ }
401
+ return {
402
+ identifier,
403
+ value,
404
+ };
405
+ }
406
+ exports._readExtension = _readExtension;
407
+ // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
408
+ function _readExtensions(buffer, block) {
409
+ assert(block.tag === 0xa3);
410
+ let inner_blocks = (0, asn1_1._readStruct)(buffer, block);
411
+ inner_blocks = (0, asn1_1._readStruct)(buffer, inner_blocks[0]);
412
+ const extensions = inner_blocks.map((block) => _readExtension(buffer, block));
413
+ const result = {};
414
+ for (const e of extensions) {
415
+ result[e.identifier.name] = e.value;
416
+ }
417
+ return result;
418
+ }
419
+ /*
420
+ SEQUENCE {
421
+ 204 13: SEQUENCE {
422
+ 206 9: OBJECT IDENTIFIER
423
+ : rsaEncryption (1 2 840 113549 1 1 1)
424
+ 217 0: NULL
425
+ : }
426
+ 219 141: BIT STRING, encapsulates {
427
+ 223 137: SEQUENCE {
428
+ 226 129: INTEGER
429
+ : 00 C2 D7 97 6D 28 70 AA 5B CF 23 2E 80 70 39 EE
430
+ : DB 6F D5 2D D5 6A 4F 7A 34 2D F9 22 72 47 70 1D
431
+ : EF 80 E9 CA 30 8C 00 C4 9A 6E 5B 45 B4 6E A5 E6
432
+ : 6C 94 0D FA 91 E9 40 FC 25 9D C7 B7 68 19 56 8F
433
+ : 11 70 6A D7 F1 C9 11 4F 3A 7E 3F 99 8D 6E 76 A5
434
+ : 74 5F 5E A4 55 53 E5 C7 68 36 53 C7 1D 3B 12 A6
435
+ : 85 FE BD 6E A1 CA DF 35 50 AC 08 D7 B9 B4 7E 5C
436
+ : FE E2 A3 2C D1 23 84 AA 98 C0 9B 66 18 9A 68 47
437
+ : E9
438
+ 358 3: INTEGER 65537
439
+ : }
440
+ : }
441
+ : }
442
+ */
443
+ function _readSubjectPublicKeyInfo(buffer, block) {
444
+ const inner_blocks = (0, asn1_1._readStruct)(buffer, block);
445
+ // algorithm identifier
446
+ const algorithm = (0, asn1_1._readAlgorithmIdentifier)(buffer, inner_blocks[0]);
447
+ //const parameters = _readBitString(buffer,inner_blocks[1]);
448
+ const subjectPublicKey = (0, asn1_1._readBitString)(buffer, inner_blocks[1]);
449
+ // read the 2 big integers of the key
450
+ const data = subjectPublicKey.data;
451
+ const values = (0, asn1_1._readListOfInteger)(data);
452
+ // xx const value = _readListOfInteger(data);
453
+ return {
454
+ algorithm: algorithm.identifier,
455
+ keyLength: (values[0].length - 1),
456
+ subjectPublicKey: _readSubjectPublicKey(subjectPublicKey.data),
457
+ //xx values: values,
458
+ //xx values_length : values.map(function (a){ return a.length; })
459
+ };
460
+ }
461
+ function _readSubjectECCPublicKeyInfo(buffer, block) {
462
+ const inner_blocks = (0, asn1_1._readStruct)(buffer, block);
463
+ // first parameter is the second element of the first block, which is why we have another algorithm
464
+ const algorithm = (0, asn1_1._readECCAlgorithmIdentifier)(buffer, inner_blocks[0]);
465
+ // the public key is already in bit format, we just need to read it
466
+ const subjectPublicKey = (0, asn1_1._readBitString)(buffer, inner_blocks[1]);
467
+ // take out the data which is the entirity of our public key
468
+ const data = subjectPublicKey.data;
469
+ return {
470
+ algorithm: algorithm.identifier,
471
+ keyLength: (data.length - 1),
472
+ subjectPublicKey: {
473
+ modulus: data
474
+ }
475
+ };
476
+ }
477
+ function readTbsCertificate(buffer, block) {
478
+ const blocks = (0, asn1_1._readStruct)(buffer, block);
479
+ let version, serialNumber, signature, issuer, validity, subject, subjectFingerPrint, extensions;
480
+ let subjectPublicKeyInfo;
481
+ if (blocks.length === 6) {
482
+ // X509 Version 1:
483
+ version = 1;
484
+ serialNumber = (0, asn1_1.formatBuffer2DigitHexWithColum)((0, asn1_1._readLongIntegerValue)(buffer, blocks[0]));
485
+ signature = (0, asn1_1._readAlgorithmIdentifier)(buffer, blocks[1]);
486
+ issuer = _readName(buffer, blocks[2]);
487
+ validity = _readValidity(buffer, blocks[3]);
488
+ subject = _readName(buffer, blocks[4]);
489
+ subjectFingerPrint = (0, asn1_1.formatBuffer2DigitHexWithColum)((0, crypto_utils_1.makeSHA1Thumbprint)((0, asn1_1._getBlock)(buffer, blocks[4])));
490
+ subjectPublicKeyInfo = _readSubjectPublicKeyInfo(buffer, blocks[5]);
491
+ extensions = null;
492
+ }
493
+ else {
494
+ // X509 Version 3:
495
+ const version_block = (0, asn1_1._findBlockAtIndex)(blocks, 0);
496
+ if (!version_block) {
497
+ throw new Error("cannot find version block");
498
+ }
499
+ version = (0, asn1_1._readVersionValue)(buffer, version_block) + 1;
500
+ serialNumber = (0, asn1_1.formatBuffer2DigitHexWithColum)((0, asn1_1._readLongIntegerValue)(buffer, blocks[1]));
501
+ signature = (0, asn1_1._readAlgorithmIdentifier)(buffer, blocks[2]);
502
+ issuer = _readName(buffer, blocks[3]);
503
+ validity = _readValidity(buffer, blocks[4]);
504
+ subject = _readName(buffer, blocks[5]);
505
+ subjectFingerPrint = (0, asn1_1.formatBuffer2DigitHexWithColum)((0, crypto_utils_1.makeSHA1Thumbprint)((0, asn1_1._getBlock)(buffer, blocks[5])));
506
+ const inner_block = (0, asn1_1._readStruct)(buffer, blocks[6]);
507
+ const what_type = (0, asn1_1._readAlgorithmIdentifier)(buffer, inner_block[0]).identifier;
508
+ switch (what_type) {
509
+ case "rsaEncryption": {
510
+ subjectPublicKeyInfo = _readSubjectPublicKeyInfo(buffer, blocks[6]);
511
+ break;
512
+ }
513
+ case "ecPublicKey":
514
+ default: {
515
+ subjectPublicKeyInfo = _readSubjectECCPublicKeyInfo(buffer, blocks[6]);
516
+ break;
517
+ }
518
+ }
519
+ const extensionBlock = (0, asn1_1._findBlockAtIndex)(blocks, 3);
520
+ if (!extensionBlock) {
521
+ // tslint:disable-next-line: no-console
522
+ console.log("X509 certificate is invalid : cannot find extension block version =" + version_block);
523
+ extensions = null;
524
+ }
525
+ else {
526
+ extensions = _readExtensions(buffer, extensionBlock);
527
+ }
528
+ }
529
+ return {
530
+ version,
531
+ serialNumber,
532
+ signature,
533
+ issuer,
534
+ validity,
535
+ subject,
536
+ subjectFingerPrint,
537
+ subjectPublicKeyInfo,
538
+ extensions,
539
+ };
540
+ }
541
+ exports.readTbsCertificate = readTbsCertificate;
542
+ /**
543
+ * explore a certificate structure
544
+ * @param certificate
545
+ * @returns a json object that exhibits the internal data of the certificate
546
+ */
547
+ function exploreCertificate(certificate) {
548
+ assert(certificate instanceof Buffer);
549
+ if (!certificate._exploreCertificate_cache) {
550
+ const block_info = (0, asn1_1.readTag)(certificate, 0);
551
+ const blocks = (0, asn1_1._readStruct)(certificate, block_info);
552
+ certificate._exploreCertificate_cache = {
553
+ tbsCertificate: readTbsCertificate(certificate, blocks[0]),
554
+ signatureAlgorithm: (0, asn1_1._readAlgorithmIdentifier)(certificate, blocks[1]),
555
+ signatureValue: (0, asn1_1._readSignatureValue)(certificate, blocks[2]),
556
+ };
557
+ }
558
+ return certificate._exploreCertificate_cache;
559
+ }
560
+ exports.exploreCertificate = exploreCertificate;
561
+ /**
562
+ * @method split_der
563
+ * split a multi chain certificates
564
+ * @param certificateChain the certificate chain in der (binary) format}
565
+ * @returns an array of Der , each element of the array is one certificate of the chain
566
+ */
567
+ function split_der(certificateChain) {
568
+ const certificate_chain = [];
569
+ do {
570
+ const block_info = (0, asn1_1.readTag)(certificateChain, 0);
571
+ const length = block_info.position + block_info.length;
572
+ const der_certificate = certificateChain.slice(0, length);
573
+ certificate_chain.push(der_certificate);
574
+ certificateChain = certificateChain.slice(length);
575
+ } while (certificateChain.length > 0);
576
+ return certificate_chain;
577
+ }
578
+ exports.split_der = split_der;
579
+ /**
580
+ * @method combine_der
581
+ * combine an array of certificates into a single blob
582
+ * @param certificates a array with the individual DER certificates of the chain
583
+ * @return a concatenated buffer containing the certificates
584
+ */
585
+ function combine_der(certificates) {
586
+ // perform some sanity check
587
+ for (const cert of certificates) {
588
+ const b = split_der(cert);
589
+ let sum = 0;
590
+ b.forEach((block) => {
591
+ const block_info = (0, asn1_1.readTag)(block, 0);
592
+ //xx console.log("xxxx" ,cert.length,block_info);
593
+ //xx console.log(cert.toString("base64"));
594
+ assert(block_info.position + block_info.length === block.length);
595
+ sum += block.length;
596
+ });
597
+ assert(sum === cert.length);
598
+ }
599
+ return Buffer.concat(certificates);
600
+ }
601
+ exports.combine_der = combine_der;
602
602
  //# sourceMappingURL=crypto_explore_certificate.js.map