node-opcua-crypto 1.8.0 → 1.9.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 (115) hide show
  1. package/.fossa.yml +18 -18
  2. package/.github/FUNDING.yml +12 -12
  3. package/.github/workflows/main.yml +32 -0
  4. package/.prettierrc.js +6 -6
  5. package/LICENSE +22 -22
  6. package/README.md +14 -14
  7. package/dist/asn1.d.ts +69 -0
  8. package/dist/asn1.js +349 -0
  9. package/dist/asn1.js.map +1 -0
  10. package/dist/buffer_utils.d.ts +6 -0
  11. package/dist/buffer_utils.js +22 -0
  12. package/dist/buffer_utils.js.map +1 -0
  13. package/dist/common.d.ts +11 -0
  14. package/dist/common.js +3 -0
  15. package/dist/common.js.map +1 -0
  16. package/dist/crypto_explore_certificate.d.ts +95 -0
  17. package/dist/crypto_explore_certificate.js +547 -0
  18. package/dist/crypto_explore_certificate.js.map +1 -0
  19. package/dist/crypto_utils.d.ts +106 -0
  20. package/dist/crypto_utils.js +370 -0
  21. package/dist/crypto_utils.js.map +1 -0
  22. package/dist/derived_keys.d.ts +72 -0
  23. package/dist/derived_keys.js +247 -0
  24. package/dist/derived_keys.js.map +1 -0
  25. package/dist/explore_certificate.d.ts +30 -0
  26. package/dist/explore_certificate.js +44 -0
  27. package/dist/explore_certificate.js.map +1 -0
  28. package/dist/explore_certificate_revocation_list.d.ts +30 -0
  29. package/dist/explore_certificate_revocation_list.js +67 -0
  30. package/dist/explore_certificate_revocation_list.js.map +1 -0
  31. package/dist/index.d.ts +10 -0
  32. package/dist/index.js +23 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/oid_map.d.ts +7 -0
  35. package/dist/oid_map.js +262 -0
  36. package/dist/oid_map.js.map +1 -0
  37. package/dist/source/asn1.d.ts +73 -72
  38. package/dist/source/asn1.js +359 -350
  39. package/dist/source/asn1.js.map +1 -1
  40. package/dist/source/buffer_utils.d.ts +6 -6
  41. package/dist/source/buffer_utils.js +21 -21
  42. package/dist/source/common.d.ts +12 -12
  43. package/dist/source/common.js +2 -2
  44. package/dist/source/crypto_explore_certificate.d.ts +107 -107
  45. package/dist/source/crypto_explore_certificate.js +600 -571
  46. package/dist/source/crypto_explore_certificate.js.map +1 -1
  47. package/dist/source/crypto_utils.d.ts +78 -78
  48. package/dist/source/crypto_utils.js +280 -280
  49. package/dist/source/crypto_utils.js.map +1 -1
  50. package/dist/source/derived_keys.d.ts +72 -72
  51. package/dist/source/derived_keys.js +248 -245
  52. package/dist/source/derived_keys.js.map +1 -1
  53. package/dist/source/explore_certificate.d.ts +30 -30
  54. package/dist/source/explore_certificate.js +43 -43
  55. package/dist/source/explore_certificate.js.map +1 -1
  56. package/dist/source/explore_certificate_revocation_list.d.ts +28 -28
  57. package/dist/source/explore_certificate_revocation_list.js +44 -44
  58. package/dist/source/explore_certificate_revocation_list.js.map +1 -1
  59. package/dist/source/explore_certificate_signing_request.d.ts +13 -13
  60. package/dist/source/explore_certificate_signing_request.js +44 -44
  61. package/dist/source/explore_certificate_signing_request.js.map +1 -1
  62. package/dist/source/explore_private_key.d.ts +29 -29
  63. package/dist/source/explore_private_key.js +96 -96
  64. package/dist/source/explore_private_key.js.map +1 -1
  65. package/dist/source/index.d.ts +13 -13
  66. package/dist/source/index.js +25 -25
  67. package/dist/source/oid_map.d.ts +7 -7
  68. package/dist/source/oid_map.js +303 -261
  69. package/dist/source/oid_map.js.map +1 -1
  70. package/dist/source/public_private_match.d.ts +3 -3
  71. package/dist/source/public_private_match.js +16 -16
  72. package/dist/source/public_private_match.js.map +1 -1
  73. package/dist/source/verify_certificate_signature.d.ts +10 -10
  74. package/dist/source/verify_certificate_signature.js +101 -101
  75. package/dist/source/verify_certificate_signature.js.map +1 -1
  76. package/dist/source_nodejs/index.d.ts +3 -3
  77. package/dist/source_nodejs/index.js +15 -15
  78. package/dist/source_nodejs/read.d.ts +29 -29
  79. package/dist/source_nodejs/read.js +94 -94
  80. package/dist/source_nodejs/read.js.map +1 -1
  81. package/dist/source_nodejs/read_certificate_revocation_list.d.ts +2 -2
  82. package/dist/source_nodejs/read_certificate_revocation_list.js +27 -27
  83. package/dist/source_nodejs/read_certificate_revocation_list.js.map +1 -1
  84. package/dist/source_nodejs/read_certificate_signing_request.d.ts +3 -3
  85. package/dist/source_nodejs/read_certificate_signing_request.js +27 -27
  86. package/dist/source_nodejs/read_certificate_signing_request.js.map +1 -1
  87. package/dist/verify_cerficate_signature.d.ts +10 -0
  88. package/dist/verify_cerficate_signature.js +102 -0
  89. package/dist/verify_cerficate_signature.js.map +1 -0
  90. package/index.d.ts +2 -2
  91. package/index.js +4 -4
  92. package/index_web.js +3 -3
  93. package/package.json +19 -22
  94. package/source/asn1.ts +404 -398
  95. package/source/buffer_utils.ts +18 -18
  96. package/source/common.ts +13 -13
  97. package/source/crypto_explore_certificate.ts +763 -728
  98. package/source/crypto_utils.ts +321 -321
  99. package/source/derived_keys.ts +287 -284
  100. package/source/explore_certificate.ts +66 -66
  101. package/source/explore_certificate_revocation_list.ts +93 -93
  102. package/source/explore_certificate_signing_request.ts +58 -58
  103. package/source/explore_private_key.ts +121 -121
  104. package/source/index.ts +13 -13
  105. package/source/oid_map.ts +310 -265
  106. package/source/public_private_match.ts +17 -17
  107. package/source/verify_certificate_signature.ts +105 -105
  108. package/source_nodejs/index.ts +2 -2
  109. package/source_nodejs/read.ts +95 -95
  110. package/source_nodejs/read_certificate_revocation_list.ts +14 -14
  111. package/source_nodejs/read_certificate_signing_request.ts +17 -17
  112. package/test_certificate.ts +34 -34
  113. package/tsconfig.json +18 -18
  114. package/tslint.json +34 -34
  115. package/pnpm-lock.yaml +0 -1767
@@ -1,284 +1,287 @@
1
- /**
2
- * @module node_opcua_crypto
3
- */
4
- import * as crypto from "crypto";
5
-
6
- import { createFastUninitializedBuffer } from "./buffer_utils";
7
- import { Nonce } from "./common";
8
- import { verifyMessageChunkSignature, VerifyMessageChunkSignatureOptions } from "./crypto_utils";
9
- import { exploreCertificateInfo } from "./explore_certificate";
10
- import * as assert from "assert";
11
-
12
- function HMAC_HASH(sha1or256: "SHA1" | "SHA256", secret: Buffer, message: Buffer) {
13
- return crypto.createHmac(sha1or256, secret).update(message).digest();
14
- }
15
-
16
- function plus(buf1: Buffer, buf2: Buffer): Buffer {
17
- return Buffer.concat([buf1, buf2]);
18
- }
19
-
20
- // OPC-UA Spec 1.02 part 6 - 6.7.5 Deriving Keys page 42
21
- // Once the SecureChannel is established the Messages are signed and encrypted with keys derived
22
- // from the Nonces exchanged in t he OpenSecureChannel call. These keys are derived by passing the
23
- // Nonces to a pseudo - random function which produces a sequence of bytes from a set of inputs. A
24
- // pseudo- random function is represented by the following function declaration:
25
- // Byte[] PRF(
26
- // Byte[] secret,
27
- // Byte[] seed,
28
- // Int32 length,
29
- // Int32 offset
30
- // )
31
- // Where length is the number of bytes to return and offset is a number of bytes from the beginning of
32
- // the sequence.
33
- // The lengths of the keys that need to be generated depend on the SecurityPolicy used for the
34
- // channel. The following information is specified by the SecurityPolicy:
35
- // a) SigningKeyLength (from the DerivedSignatureKeyLength);
36
- // b) EncryptingKeyLength (implied by the SymmetricEncryptionAlgorithm);
37
- // c) EncryptingBlockSize (implied by the SymmetricEncryptionAlgorithm).
38
- // The parameters passed to the pseudo random function are specified in Table 36.
39
- // Table 36 - Cryptography Key Generation Parameters
40
- //
41
- // Key Secret Seed Length Offset
42
- // ClientSigningKey ServerNonce ClientNonce SigningKeyLength 0
43
- // ClientEncryptingKey ServerNonce ClientNonce EncryptingKeyLength SigningKeyLength
44
- // ClientInitializationVector ServerNonce ClientNonce EncryptingBlockSize SigningKeyLength+ EncryptingKeyLength
45
- // ServerSigningKey ClientNonce ServerNonce SigningKeyLength 0
46
- // ServerEncryptingKey ClientNonce ServerNonce EncryptingKeyLength SigningKeyLength
47
- // ServerInitializationVector ClientNonce ServerNonce EncryptingBlockSize SigningKeyLength+ EncryptingKeyLength
48
- //
49
- // The Client keys are used to secure Messages sent by the Client. The Server keys are used to
50
- // secure Messages sent by the Server.
51
- // The SSL/TLS specification defines a pseudo random function called P_HASH which is used for this purpose.
52
- //
53
- // The P_HASH algorithm is defined as follows:
54
- //
55
- // P_HASH(secret, seed) = HMAC_HASH(secret, A(1) + seed) +
56
- // HMAC_HASH(secret, A(2) + seed) +
57
- // HMAC_HASH(secret, A(3) + seed) + ...
58
- // Where A(n) is defined as:
59
- // A(0) = seed
60
- // A(n) = HMAC_HASH(secret, A(n-1))
61
- // + indicates that the results are appended to previous results.
62
- // Where HASH is a hash function such as SHA1 or SHA256. The hash function to use depends on the SecurityPolicyUri.
63
- //
64
- //
65
- // see also http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512/ws-secureconversation-1.3-os.html
66
- // http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
67
- export function makePseudoRandomBuffer(secret: Nonce, seed: Nonce, minLength: number, sha1or256: "SHA1" | "SHA256"): Buffer {
68
- assert(seed instanceof Buffer);
69
- assert(sha1or256 === "SHA1" || sha1or256 === "SHA256");
70
-
71
- const a = [];
72
- a[0] = seed;
73
- let index = 1;
74
- let p_hash = createFastUninitializedBuffer(0);
75
- while (p_hash.length <= minLength) {
76
- /* eslint new-cap:0 */
77
- a[index] = HMAC_HASH(sha1or256, secret, a[index - 1]);
78
- p_hash = plus(p_hash, HMAC_HASH(sha1or256, secret, plus(a[index], seed)));
79
- index += 1;
80
- }
81
- return p_hash.slice(0, minLength);
82
- }
83
-
84
- export interface ComputeDerivedKeysOptions {
85
- signatureLength: number;
86
- signingKeyLength: number;
87
- encryptingKeyLength: number;
88
-
89
- encryptingBlockSize: number;
90
- algorithm: string;
91
- sha1or256?: "SHA1" | "SHA256";
92
- }
93
-
94
- export interface DerivedKeys extends ComputeDerivedKeysOptions {
95
- signatureLength: number;
96
- signingKeyLength: number;
97
- encryptingKeyLength: number;
98
-
99
- encryptingBlockSize: number;
100
- algorithm: string;
101
- sha1or256: "SHA1" | "SHA256";
102
-
103
- signingKey: Buffer;
104
- encryptingKey: Buffer;
105
- initializationVector: Buffer;
106
- }
107
-
108
- export function computeDerivedKeys(secret: Nonce, seed: Nonce, options: ComputeDerivedKeysOptions): DerivedKeys {
109
- assert(Number.isFinite(options.signatureLength));
110
- assert(Number.isFinite(options.encryptingKeyLength));
111
- assert(Number.isFinite(options.encryptingBlockSize));
112
- assert(typeof options.algorithm === "string");
113
- options.sha1or256 = options.sha1or256 || "SHA1";
114
- assert(typeof options.sha1or256 === "string");
115
-
116
- const offset1 = options.signingKeyLength;
117
- const offset2 = offset1 + options.encryptingKeyLength;
118
- const minLength = offset2 + options.encryptingBlockSize;
119
-
120
- const buf = makePseudoRandomBuffer(secret, seed, minLength, options.sha1or256);
121
-
122
- return {
123
- signatureLength: options.signatureLength,
124
- signingKeyLength: options.signingKeyLength,
125
- encryptingKeyLength: options.encryptingKeyLength,
126
-
127
- encryptingBlockSize: options.encryptingBlockSize,
128
- algorithm: options.algorithm,
129
- sha1or256: options.sha1or256,
130
-
131
- signingKey: buf.slice(0, offset1),
132
- encryptingKey: buf.slice(offset1, offset2),
133
- initializationVector: buf.slice(offset2, minLength),
134
- };
135
- }
136
-
137
- /**
138
- * @method reduceLength
139
- * @param buffer
140
- * @param byteToRemove
141
- * @return buffer
142
- */
143
- export function reduceLength(buffer: Buffer, byteToRemove: number): Buffer {
144
- return buffer.slice(0, buffer.length - byteToRemove);
145
- }
146
-
147
- /**
148
- * @method removePadding
149
- * @param buffer
150
- * @return buffer with padding removed
151
- */
152
- export function removePadding(buffer: Buffer): Buffer {
153
- const nbPaddingBytes = buffer.readUInt8(buffer.length - 1) + 1;
154
- return reduceLength(buffer, nbPaddingBytes);
155
- }
156
-
157
- export type VerifyChunkSignatureOptions = VerifyMessageChunkSignatureOptions;
158
-
159
- /**
160
- * @method verifyChunkSignature
161
- *
162
- * const signer = {
163
- * signatureLength : 128,
164
- * algorithm : "RSA-SHA256",
165
- * public_key: "qsdqsdqsd"
166
- * };
167
- *
168
- * @param chunk The message chunk to verify.
169
- * @param options
170
- * @param options.signatureLength
171
- * @param options.algorithm the algorithm.
172
- * @param options.publicKey
173
- * @return {*}
174
- */
175
- export function verifyChunkSignature(chunk: Buffer, options: VerifyChunkSignatureOptions): boolean {
176
- assert(chunk instanceof Buffer);
177
- let signatureLength = options.signatureLength || 0;
178
- if (signatureLength === 0) {
179
- // let's get the signatureLength by checking the size
180
- // of the certificate's public key
181
- const cert = exploreCertificateInfo(options.publicKey);
182
- signatureLength = cert.publicKeyLength || 0; // 1024 bits = 128Bytes or 2048=256Bytes
183
- }
184
- const block_to_verify = chunk.slice(0, chunk.length - signatureLength);
185
- const signature = chunk.slice(chunk.length - signatureLength);
186
- return verifyMessageChunkSignature(block_to_verify, signature, options);
187
- }
188
-
189
- // /**
190
- // * extract the public key from a certificate - using the pem module
191
- // *
192
- // * @method extractPublicKeyFromCertificate_WithPem
193
- // * @async
194
- // * @param certificate
195
- // * @param callback {Function}
196
- // * @param callback.err
197
- // * @param callback.publicKey as pem
198
- // */
199
- // exports.extractPublicKeyFromCertificate_WithPem = function (certificate, callback) {
200
- //
201
- // const err1 = new Error();
202
- // const cert_pem = crypto_utils.toPem(certificate, "CERTIFICATE");
203
- // require("pem").getPublicKey(cert_pem, function (err, data) {
204
- // if (err) {
205
- // console.log(err1.stack);
206
- // console.log(" CANNOT EXTRAT PUBLIC KEY from Certificate".red, certificate);
207
- // return callback(err);
208
- // }
209
- // callback(err, data.publicKey);
210
- // });
211
- // };
212
- //
213
-
214
- export function computePaddingFooter(buffer: Buffer, derivedKeys: DerivedKeys): Buffer {
215
- assert(derivedKeys.hasOwnProperty("encryptingBlockSize"));
216
- const paddingSize = derivedKeys.encryptingBlockSize - ((buffer.length + 1) % derivedKeys.encryptingBlockSize);
217
- const padding = createFastUninitializedBuffer(paddingSize + 1);
218
- padding.fill(paddingSize);
219
- return padding;
220
- }
221
-
222
- function derivedKeys_algorithm(derivedKeys: DerivedKeys) {
223
- assert(derivedKeys.hasOwnProperty("algorithm"));
224
- const algorithm = derivedKeys.algorithm || "aes-128-cbc";
225
- assert(algorithm === "aes-128-cbc" || algorithm === "aes-256-cbc");
226
- return algorithm;
227
- }
228
-
229
- export function encryptBufferWithDerivedKeys(buffer: Buffer, derivedKeys: DerivedKeys): Buffer {
230
- const algorithm = derivedKeys_algorithm(derivedKeys);
231
- const key = derivedKeys.encryptingKey;
232
- const initVector = derivedKeys.initializationVector;
233
- const cypher = crypto.createCipheriv(algorithm, key, initVector);
234
-
235
- cypher.setAutoPadding(false);
236
- const encrypted_chunks = [];
237
- encrypted_chunks.push(cypher.update(buffer));
238
- encrypted_chunks.push(cypher.final());
239
- return Buffer.concat(encrypted_chunks);
240
- }
241
-
242
- export function decryptBufferWithDerivedKeys(buffer: Buffer, derivedKeys: DerivedKeys): Buffer {
243
- const algorithm = derivedKeys_algorithm(derivedKeys);
244
- const key = derivedKeys.encryptingKey;
245
- const initVector = derivedKeys.initializationVector;
246
- const cypher = crypto.createDecipheriv(algorithm, key, initVector);
247
-
248
- cypher.setAutoPadding(false);
249
-
250
- const decrypted_chunks = [];
251
- decrypted_chunks.push(cypher.update(buffer));
252
- decrypted_chunks.push(cypher.final());
253
-
254
- return Buffer.concat(decrypted_chunks);
255
- }
256
-
257
- /**
258
- * @method makeMessageChunkSignatureWithDerivedKeys
259
- * @param message
260
- * @param derivedKeys
261
- * @return
262
- */
263
- export function makeMessageChunkSignatureWithDerivedKeys(message: Buffer, derivedKeys: DerivedKeys): Buffer {
264
- assert(message instanceof Buffer);
265
- assert(derivedKeys.signingKey instanceof Buffer);
266
- assert(typeof derivedKeys.sha1or256 === "string");
267
- assert(derivedKeys.sha1or256 === "SHA1" || derivedKeys.sha1or256 === "SHA256");
268
- const signature = crypto.createHmac(derivedKeys.sha1or256, derivedKeys.signingKey).update(message).digest();
269
- assert(signature.length === derivedKeys.signatureLength);
270
- return signature;
271
- }
272
-
273
- /**
274
- * @method verifyChunkSignatureWithDerivedKeys
275
- * @param chunk
276
- * @param derivedKeys
277
- * @return
278
- */
279
- export function verifyChunkSignatureWithDerivedKeys(chunk: Buffer, derivedKeys: DerivedKeys): boolean {
280
- const message = chunk.slice(0, chunk.length - derivedKeys.signatureLength);
281
- const signature = chunk.slice(chunk.length - derivedKeys.signatureLength);
282
- const verif = makeMessageChunkSignatureWithDerivedKeys(message, derivedKeys);
283
- return verif.toString("hex") === signature.toString("hex");
284
- }
1
+ /**
2
+ * @module node_opcua_crypto
3
+ */
4
+ import * as crypto from "crypto";
5
+
6
+ import { createFastUninitializedBuffer } from "./buffer_utils";
7
+ import { Nonce } from "./common";
8
+ import { verifyMessageChunkSignature, VerifyMessageChunkSignatureOptions } from "./crypto_utils";
9
+ import { exploreCertificateInfo } from "./explore_certificate";
10
+ import * as assert from "assert";
11
+
12
+ function HMAC_HASH(sha1or256: "SHA1" | "SHA256", secret: Buffer, message: Buffer) {
13
+ return crypto.createHmac(sha1or256, secret).update(message).digest();
14
+ }
15
+
16
+ function plus(buf1: Buffer, buf2: Buffer): Buffer {
17
+ return Buffer.concat([buf1, buf2]);
18
+ }
19
+
20
+ // OPC-UA Spec 1.02 part 6 - 6.7.5 Deriving Keys page 42
21
+ // Once the SecureChannel is established the Messages are signed and encrypted with keys derived
22
+ // from the Nonces exchanged in t he OpenSecureChannel call. These keys are derived by passing the
23
+ // Nonces to a pseudo - random function which produces a sequence of bytes from a set of inputs. A
24
+ // pseudo- random function is represented by the following function declaration:
25
+ // Byte[] PRF(
26
+ // Byte[] secret,
27
+ // Byte[] seed,
28
+ // Int32 length,
29
+ // Int32 offset
30
+ // )
31
+ // Where length is the number of bytes to return and offset is a number of bytes from the beginning of
32
+ // the sequence.
33
+ // The lengths of the keys that need to be generated depend on the SecurityPolicy used for the
34
+ // channel. The following information is specified by the SecurityPolicy:
35
+ // a) SigningKeyLength (from the DerivedSignatureKeyLength);
36
+ // b) EncryptingKeyLength (implied by the SymmetricEncryptionAlgorithm);
37
+ // c) EncryptingBlockSize (implied by the SymmetricEncryptionAlgorithm).
38
+ // The parameters passed to the pseudo random function are specified in Table 36.
39
+ // Table 36 - Cryptography Key Generation Parameters
40
+ //
41
+ // Key Secret Seed Length Offset
42
+ // ClientSigningKey ServerNonce ClientNonce SigningKeyLength 0
43
+ // ClientEncryptingKey ServerNonce ClientNonce EncryptingKeyLength SigningKeyLength
44
+ // ClientInitializationVector ServerNonce ClientNonce EncryptingBlockSize SigningKeyLength+ EncryptingKeyLength
45
+ // ServerSigningKey ClientNonce ServerNonce SigningKeyLength 0
46
+ // ServerEncryptingKey ClientNonce ServerNonce EncryptingKeyLength SigningKeyLength
47
+ // ServerInitializationVector ClientNonce ServerNonce EncryptingBlockSize SigningKeyLength+ EncryptingKeyLength
48
+ //
49
+ // The Client keys are used to secure Messages sent by the Client. The Server keys are used to
50
+ // secure Messages sent by the Server.
51
+ // The SSL/TLS specification defines a pseudo random function called P_HASH which is used for this purpose.
52
+ //
53
+ // The P_HASH algorithm is defined as follows:
54
+ //
55
+ // P_HASH(secret, seed) = HMAC_HASH(secret, A(1) + seed) +
56
+ // HMAC_HASH(secret, A(2) + seed) +
57
+ // HMAC_HASH(secret, A(3) + seed) + ...
58
+ // Where A(n) is defined as:
59
+ // A(0) = seed
60
+ // A(n) = HMAC_HASH(secret, A(n-1))
61
+ // + indicates that the results are appended to previous results.
62
+ // Where HASH is a hash function such as SHA1 or SHA256. The hash function to use depends on the SecurityPolicyUri.
63
+ //
64
+ //
65
+ // see also http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512/ws-secureconversation-1.3-os.html
66
+ // http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
67
+ export function makePseudoRandomBuffer(secret: Nonce, seed: Nonce, minLength: number, sha1or256: "SHA1" | "SHA256"): Buffer {
68
+ assert(seed instanceof Buffer);
69
+ assert(sha1or256 === "SHA1" || sha1or256 === "SHA256");
70
+
71
+ const a = [];
72
+ a[0] = seed;
73
+ let index = 1;
74
+ let p_hash = createFastUninitializedBuffer(0);
75
+ while (p_hash.length <= minLength) {
76
+ /* eslint new-cap:0 */
77
+ a[index] = HMAC_HASH(sha1or256, secret, a[index - 1]);
78
+ p_hash = plus(p_hash, HMAC_HASH(sha1or256, secret, plus(a[index], seed)));
79
+ index += 1;
80
+ }
81
+ return p_hash.slice(0, minLength);
82
+ }
83
+
84
+ export interface ComputeDerivedKeysOptions {
85
+ signatureLength: number;
86
+ signingKeyLength: number;
87
+ encryptingKeyLength: number;
88
+
89
+ encryptingBlockSize: number;
90
+ algorithm: string;
91
+ sha1or256?: "SHA1" | "SHA256";
92
+ }
93
+
94
+ export interface DerivedKeys extends ComputeDerivedKeysOptions {
95
+ signatureLength: number;
96
+ signingKeyLength: number;
97
+ encryptingKeyLength: number;
98
+
99
+ encryptingBlockSize: number;
100
+ algorithm: string;
101
+ sha1or256: "SHA1" | "SHA256";
102
+
103
+ signingKey: Buffer;
104
+ encryptingKey: Buffer;
105
+ initializationVector: Buffer;
106
+ }
107
+
108
+ export function computeDerivedKeys(secret: Nonce, seed: Nonce, options: ComputeDerivedKeysOptions): DerivedKeys {
109
+ assert(Number.isFinite(options.signatureLength));
110
+ assert(Number.isFinite(options.encryptingKeyLength));
111
+ assert(Number.isFinite(options.encryptingBlockSize));
112
+ assert(typeof options.algorithm === "string");
113
+ options.sha1or256 = options.sha1or256 || "SHA1";
114
+ assert(typeof options.sha1or256 === "string");
115
+
116
+ const offset1 = options.signingKeyLength;
117
+ const offset2 = offset1 + options.encryptingKeyLength;
118
+ const minLength = offset2 + options.encryptingBlockSize;
119
+
120
+ const buf = makePseudoRandomBuffer(secret, seed, minLength, options.sha1or256);
121
+
122
+ // +---------------+---------------------+-----------------------+
123
+ // + signingKey + encryptingKey + initializationVector +
124
+ // +---------------+---------------------+-----------------------+
125
+ return {
126
+ signatureLength: options.signatureLength,
127
+ signingKeyLength: options.signingKeyLength,
128
+ encryptingKeyLength: options.encryptingKeyLength,
129
+
130
+ encryptingBlockSize: options.encryptingBlockSize,
131
+ algorithm: options.algorithm,
132
+ sha1or256: options.sha1or256,
133
+
134
+ signingKey: buf.slice(0, offset1),
135
+ encryptingKey: buf.slice(offset1, offset2),
136
+ initializationVector: buf.slice(offset2, minLength),
137
+ };
138
+ }
139
+
140
+ /**
141
+ * @method reduceLength
142
+ * @param buffer
143
+ * @param byteToRemove
144
+ * @return buffer
145
+ */
146
+ export function reduceLength(buffer: Buffer, byteToRemove: number): Buffer {
147
+ return buffer.slice(0, buffer.length - byteToRemove);
148
+ }
149
+
150
+ /**
151
+ * @method removePadding
152
+ * @param buffer
153
+ * @return buffer with padding removed
154
+ */
155
+ export function removePadding(buffer: Buffer): Buffer {
156
+ const nbPaddingBytes = buffer.readUInt8(buffer.length - 1) + 1;
157
+ return reduceLength(buffer, nbPaddingBytes);
158
+ }
159
+
160
+ export type VerifyChunkSignatureOptions = VerifyMessageChunkSignatureOptions;
161
+
162
+ /**
163
+ * @method verifyChunkSignature
164
+ *
165
+ * const signer = {
166
+ * signatureLength : 128,
167
+ * algorithm : "RSA-SHA256",
168
+ * public_key: "qsdqsdqsd"
169
+ * };
170
+ *
171
+ * @param chunk The message chunk to verify.
172
+ * @param options
173
+ * @param options.signatureLength
174
+ * @param options.algorithm the algorithm.
175
+ * @param options.publicKey
176
+ * @return {*}
177
+ */
178
+ export function verifyChunkSignature(chunk: Buffer, options: VerifyChunkSignatureOptions): boolean {
179
+ assert(chunk instanceof Buffer);
180
+ let signatureLength = options.signatureLength || 0;
181
+ if (signatureLength === 0) {
182
+ // let's get the signatureLength by checking the size
183
+ // of the certificate's public key
184
+ const cert = exploreCertificateInfo(options.publicKey);
185
+ signatureLength = cert.publicKeyLength || 0; // 1024 bits = 128Bytes or 2048=256Bytes
186
+ }
187
+ const block_to_verify = chunk.slice(0, chunk.length - signatureLength);
188
+ const signature = chunk.slice(chunk.length - signatureLength);
189
+ return verifyMessageChunkSignature(block_to_verify, signature, options);
190
+ }
191
+
192
+ // /**
193
+ // * extract the public key from a certificate - using the pem module
194
+ // *
195
+ // * @method extractPublicKeyFromCertificate_WithPem
196
+ // * @async
197
+ // * @param certificate
198
+ // * @param callback {Function}
199
+ // * @param callback.err
200
+ // * @param callback.publicKey as pem
201
+ // */
202
+ // exports.extractPublicKeyFromCertificate_WithPem = function (certificate, callback) {
203
+ //
204
+ // const err1 = new Error();
205
+ // const cert_pem = crypto_utils.toPem(certificate, "CERTIFICATE");
206
+ // require("pem").getPublicKey(cert_pem, function (err, data) {
207
+ // if (err) {
208
+ // console.log(err1.stack);
209
+ // console.log(" CANNOT EXTRAT PUBLIC KEY from Certificate".red, certificate);
210
+ // return callback(err);
211
+ // }
212
+ // callback(err, data.publicKey);
213
+ // });
214
+ // };
215
+ //
216
+
217
+ export function computePaddingFooter(buffer: Buffer, derivedKeys: DerivedKeys): Buffer {
218
+ assert(Object.prototype.hasOwnProperty.call(derivedKeys, "encryptingBlockSize"));
219
+ const paddingSize = derivedKeys.encryptingBlockSize - ((buffer.length + 1) % derivedKeys.encryptingBlockSize);
220
+ const padding = createFastUninitializedBuffer(paddingSize + 1);
221
+ padding.fill(paddingSize);
222
+ return padding;
223
+ }
224
+
225
+ function derivedKeys_algorithm(derivedKeys: DerivedKeys) {
226
+ assert(Object.prototype.hasOwnProperty.call(derivedKeys, "algorithm"));
227
+ const algorithm = derivedKeys.algorithm || "aes-128-cbc";
228
+ assert(algorithm === "aes-128-cbc" || algorithm === "aes-256-cbc");
229
+ return algorithm;
230
+ }
231
+
232
+ export function encryptBufferWithDerivedKeys(buffer: Buffer, derivedKeys: DerivedKeys): Buffer {
233
+ const algorithm = derivedKeys_algorithm(derivedKeys);
234
+ const key = derivedKeys.encryptingKey;
235
+ const initVector = derivedKeys.initializationVector;
236
+ const cypher = crypto.createCipheriv(algorithm, key, initVector);
237
+
238
+ cypher.setAutoPadding(false);
239
+ const encrypted_chunks = [];
240
+ encrypted_chunks.push(cypher.update(buffer));
241
+ encrypted_chunks.push(cypher.final());
242
+ return Buffer.concat(encrypted_chunks);
243
+ }
244
+
245
+ export function decryptBufferWithDerivedKeys(buffer: Buffer, derivedKeys: DerivedKeys): Buffer {
246
+ const algorithm = derivedKeys_algorithm(derivedKeys);
247
+ const key = derivedKeys.encryptingKey;
248
+ const initVector = derivedKeys.initializationVector;
249
+ const cypher = crypto.createDecipheriv(algorithm, key, initVector);
250
+
251
+ cypher.setAutoPadding(false);
252
+
253
+ const decrypted_chunks = [];
254
+ decrypted_chunks.push(cypher.update(buffer));
255
+ decrypted_chunks.push(cypher.final());
256
+
257
+ return Buffer.concat(decrypted_chunks);
258
+ }
259
+
260
+ /**
261
+ * @method makeMessageChunkSignatureWithDerivedKeys
262
+ * @param message
263
+ * @param derivedKeys
264
+ * @return
265
+ */
266
+ export function makeMessageChunkSignatureWithDerivedKeys(message: Buffer, derivedKeys: DerivedKeys): Buffer {
267
+ assert(message instanceof Buffer);
268
+ assert(derivedKeys.signingKey instanceof Buffer);
269
+ assert(typeof derivedKeys.sha1or256 === "string");
270
+ assert(derivedKeys.sha1or256 === "SHA1" || derivedKeys.sha1or256 === "SHA256");
271
+ const signature = crypto.createHmac(derivedKeys.sha1or256, derivedKeys.signingKey).update(message).digest();
272
+ assert(signature.length === derivedKeys.signatureLength);
273
+ return signature;
274
+ }
275
+
276
+ /**
277
+ * @method verifyChunkSignatureWithDerivedKeys
278
+ * @param chunk
279
+ * @param derivedKeys
280
+ * @return
281
+ */
282
+ export function verifyChunkSignatureWithDerivedKeys(chunk: Buffer, derivedKeys: DerivedKeys): boolean {
283
+ const message = chunk.slice(0, chunk.length - derivedKeys.signatureLength);
284
+ const signature = chunk.slice(chunk.length - derivedKeys.signatureLength);
285
+ const verif = makeMessageChunkSignatureWithDerivedKeys(message, derivedKeys);
286
+ return verif.toString("hex") === signature.toString("hex");
287
+ }