|
1 | 1 | import * as semver from 'semver';
|
2 | 2 | import * as process from 'node:process';
|
3 |
| -import * as crypto from 'node:crypto'; |
4 | 3 | import * as path from 'node:path';
|
5 | 4 | import * as fs from 'node:fs';
|
6 | 5 | import * as sinon from 'sinon';
|
7 | 6 | import { EJSON, BSON, Binary } from 'bson';
|
8 |
| -import { MongoCrypt, MongoCryptConstructor } from '../src'; |
| 7 | +import { MongoCrypt, MongoCryptConstructor, cryptoCallbacks } from '../src'; |
9 | 8 | import { expect } from 'chai';
|
10 | 9 |
|
11 |
| -function makeAES256Hook(method, mode) { |
12 |
| - return function (key, iv, input, output) { |
13 |
| - let result; |
14 |
| - try { |
15 |
| - const cipher = crypto[method](mode, key, iv); |
16 |
| - cipher.setAutoPadding(false); |
17 |
| - result = cipher.update(input); |
18 |
| - const final = cipher.final(); |
19 |
| - if (final.length > 0) { |
20 |
| - result = Buffer.concat([result, final]); |
21 |
| - } |
22 |
| - } catch (e) { |
23 |
| - return e; |
24 |
| - } |
25 |
| - result.copy(output); |
26 |
| - return result.length; |
27 |
| - }; |
28 |
| -} |
29 |
| - |
30 |
| -function randomHook(buffer, count) { |
31 |
| - try { |
32 |
| - crypto.randomFillSync(buffer, 0, count); |
33 |
| - } catch (e) { |
34 |
| - return e; |
35 |
| - } |
36 |
| - return count; |
37 |
| -} |
38 |
| - |
39 |
| -function sha256Hook(input, output) { |
40 |
| - let result; |
41 |
| - try { |
42 |
| - result = crypto.createHash('sha256').update(input).digest(); |
43 |
| - } catch (e) { |
44 |
| - return e; |
45 |
| - } |
46 |
| - result.copy(output); |
47 |
| - return result.length; |
48 |
| -} |
49 |
| - |
50 |
| -function makeHmacHook(algorithm) { |
51 |
| - return (key, input, output) => { |
52 |
| - let result; |
53 |
| - try { |
54 |
| - result = crypto.createHmac(algorithm, key).update(input).digest(); |
55 |
| - } catch (e) { |
56 |
| - return e; |
57 |
| - } |
58 |
| - result.copy(output); |
59 |
| - return result.length; |
60 |
| - }; |
61 |
| -} |
62 |
| - |
63 |
| -function signRsaSha256Hook(key, input, output) { |
64 |
| - let result; |
65 |
| - try { |
66 |
| - const signer = crypto.createSign('sha256WithRSAEncryption'); |
67 |
| - const privateKey = Buffer.from( |
68 |
| - `-----BEGIN PRIVATE KEY-----\n${key.toString('base64')}\n-----END PRIVATE KEY-----\n` |
69 |
| - ); |
70 |
| - result = signer.update(input).end().sign(privateKey); |
71 |
| - } catch (e) { |
72 |
| - return e; |
73 |
| - } |
74 |
| - result.copy(output); |
75 |
| - return result.length; |
76 |
| -} |
77 |
| - |
78 |
| -const aes256CbcEncryptHook = makeAES256Hook('createCipheriv', 'aes-256-cbc'); |
79 |
| -const aes256CbcDecryptHook = makeAES256Hook('createDecipheriv', 'aes-256-cbc'); |
80 |
| -const aes256CtrEncryptHook = makeAES256Hook('createCipheriv', 'aes-256-ctr'); |
81 |
| -const aes256CtrDecryptHook = makeAES256Hook('createDecipheriv', 'aes-256-ctr'); |
82 |
| -const hmacSha512Hook = makeHmacHook('sha512'); |
83 |
| -const hmacSha256Hook = makeHmacHook('sha256'); |
84 |
| - |
85 |
| -export const cryptoCallbacks = { |
86 |
| - randomHook, |
87 |
| - sha256Hook, |
88 |
| - signRsaSha256Hook, |
89 |
| - aes256CbcEncryptHook, |
90 |
| - aes256CbcDecryptHook, |
91 |
| - aes256CtrEncryptHook, |
92 |
| - aes256CtrDecryptHook, |
93 |
| - hmacSha512Hook, |
94 |
| - hmacSha256Hook |
95 |
| -}; |
96 |
| - |
97 | 10 | const NEED_MONGO_KEYS = 3;
|
98 | 11 | const READY = 5;
|
99 | 12 | const ERROR = 0;
|
@@ -154,6 +67,17 @@ describe('Crypto hooks', () => {
|
154 | 67 | }
|
155 | 68 | });
|
156 | 69 |
|
| 70 | + it('reports crypto hook provider as `native_openssl`', () => { |
| 71 | + const mongoCryptOptions: ConstructorParameters<MongoCryptConstructor>[0] = { |
| 72 | + kmsProviders: BSON.serialize(kmsProviders), |
| 73 | + cryptoCallbacks |
| 74 | + }; |
| 75 | + |
| 76 | + const mongoCrypt = new MongoCrypt(mongoCryptOptions); |
| 77 | + |
| 78 | + expect(mongoCrypt).to.have.property('cryptoHooksProvider', 'native_openssl'); |
| 79 | + }); |
| 80 | + |
157 | 81 | it('should use native crypto hooks', async () => {
|
158 | 82 | const spiedCallbacks = Object.fromEntries(
|
159 | 83 | Object.entries(cryptoCallbacks).map(([name, hook]) => [name, sinon.spy(hook)])
|
@@ -184,6 +108,17 @@ describe('Crypto hooks', () => {
|
184 | 108 | }
|
185 | 109 | });
|
186 | 110 |
|
| 111 | + it('reports crypto hook provider as `js`', () => { |
| 112 | + const mongoCryptOptions: ConstructorParameters<MongoCryptConstructor>[0] = { |
| 113 | + kmsProviders: BSON.serialize(kmsProviders), |
| 114 | + cryptoCallbacks |
| 115 | + }; |
| 116 | + |
| 117 | + const mongoCrypt = new MongoCrypt(mongoCryptOptions); |
| 118 | + |
| 119 | + expect(mongoCrypt).to.have.property('cryptoHooksProvider', 'js'); |
| 120 | + }); |
| 121 | + |
187 | 122 | it('should use js crypto hooks', async () => {
|
188 | 123 | const spiedCallbacks = Object.fromEntries(
|
189 | 124 | Object.entries(cryptoCallbacks).map(([name, hook]) => [name, sinon.spy(hook)])
|
|
0 commit comments