Skip to content

Commit 99dd2a6

Browse files
Revert "fix"
This reverts commit e3f2f2b.
1 parent bab766d commit 99dd2a6

File tree

1 file changed

+179
-0
lines changed

1 file changed

+179
-0
lines changed
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
import { expect } from 'chai';
2+
import * as sinon from 'sinon';
3+
4+
/* eslint-disable @typescript-eslint/no-restricted-imports */
5+
import { ClientEncryption } from '../../../src/client-side-encryption/client_encryption';
6+
/* eslint-disable @typescript-eslint/no-restricted-imports */
7+
import * as cryptoCallbacks from '../../../src/client-side-encryption/crypto_callbacks';
8+
import { type MongoClient } from '../../mongodb';
9+
10+
// Data Key Stuff
11+
const AWS_ACCESS_KEY_ID = process.env.AWS_ACCESS_KEY_ID;
12+
const AWS_SECRET_ACCESS_KEY = process.env.AWS_SECRET_ACCESS_KEY;
13+
const AWS_REGION = process.env.AWS_REGION;
14+
const AWS_CMK_ID = process.env.AWS_CMK_ID;
15+
16+
const kmsProviders = {
17+
aws: { accessKeyId: AWS_ACCESS_KEY_ID, secretAccessKey: AWS_SECRET_ACCESS_KEY }
18+
};
19+
const dataKeyOptions = { masterKey: { key: AWS_CMK_ID, region: AWS_REGION } };
20+
21+
const SKIP_AWS_TESTS = [AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, AWS_CMK_ID].some(
22+
secret => !secret
23+
);
24+
25+
describe('cryptoCallbacks', function () {
26+
let client: MongoClient;
27+
let sandbox;
28+
29+
const hookNames = new Set([
30+
'aes256CbcEncryptHook',
31+
'aes256CbcDecryptHook',
32+
'randomHook',
33+
'hmacSha512Hook',
34+
'hmacSha256Hook',
35+
'sha256Hook'
36+
]);
37+
38+
beforeEach(function () {
39+
if (SKIP_AWS_TESTS) {
40+
this.currentTest?.skip();
41+
return;
42+
}
43+
44+
sandbox = sinon.createSandbox();
45+
sandbox.spy(cryptoCallbacks);
46+
47+
client = this.configuration.newClient();
48+
49+
return client.connect();
50+
});
51+
52+
afterEach(async function () {
53+
sandbox?.restore();
54+
await client?.close();
55+
});
56+
57+
it('should support support crypto callback for signing RSA-SHA256', function () {
58+
const input = Buffer.from('data to sign');
59+
const pemFileData =
60+
'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC4JOyv5z05cL18ztpknRC7CFY2gYol4DAKerdVUoDJxCTmFMf39dVUEqD0WDiw/qcRtSO1/FRut08PlSPmvbyKetsLoxlpS8lukSzEFpFK7+L+R4miFOl6HvECyg7lbC1H/WGAhIz9yZRlXhRo9qmO/fB6PV9IeYtU+1xYuXicjCDPp36uuxBAnCz7JfvxJ3mdVc0vpSkbSb141nWuKNYR1mgyvvL6KzxO6mYsCo4hRAdhuizD9C4jDHk0V2gDCFBk0h8SLEdzStX8L0jG90/Og4y7J1b/cPo/kbYokkYisxe8cPlsvGBf+rZex7XPxc1yWaP080qeABJb+S88O//LAgMBAAECggEBAKVxP1m3FzHBUe2NZ3fYCc0Qa2zjK7xl1KPFp2u4CU+9sy0oZJUqQHUdm5CMprqWwIHPTftWboFenmCwrSXFOFzujljBO7Z3yc1WD3NJl1ZNepLcsRJ3WWFH5V+NLJ8Bdxlj1DMEZCwr7PC5+vpnCuYWzvT0qOPTl9RNVaW9VVjHouJ9Fg+s2DrShXDegFabl1iZEDdI4xScHoYBob06A5lw0WOCTayzw0Naf37lM8Y4psRAmI46XLiF/Vbuorna4hcChxDePlNLEfMipICcuxTcei1RBSlBa2t1tcnvoTy6cuYDqqImRYjp1KnMKlKQBnQ1NjS2TsRGm+F0FbreVCECgYEA4IDJlm8q/hVyNcPe4OzIcL1rsdYN3bNm2Y2O/YtRPIkQ446ItyxD06d9VuXsQpFp9jNACAPfCMSyHpPApqlxdc8z/xATlgHkcGezEOd1r4E7NdTpGg8y6Rj9b8kVlED6v4grbRhKcU6moyKUQT3+1B6ENZTOKyxuyDEgTwZHtFECgYEA0fqdv9h9s77d6eWmIioP7FSymq93pC4umxf6TVicpjpMErdD2ZfJGulN37dq8FOsOFnSmFYJdICj/PbJm6p1i8O21lsFCltEqVoVabJ7/0alPfdG2U76OeBqI8ZubL4BMnWXAB/VVEYbyWCNpQSDTjHQYs54qa2I0dJB7OgJt1sCgYEArctFQ02/7H5Rscl1yo3DBXO94SeiCFSPdC8f2Kt3MfOxvVdkAtkjkMACSbkoUsgbTVqTYSEOEc2jTgR3iQ13JgpHaFbbsq64V0QP3TAxbLIQUjYGVgQaF1UfLOBv8hrzgj45z/ST/G80lOl595+0nCUbmBcgG1AEWrmdF0/3RmECgYAKvIzKXXB3+19vcT2ga5Qq2l3TiPtOGsppRb2XrNs9qKdxIYvHmXo/9QP1V3SRW0XoD7ez8FpFabp42cmPOxUNk3FK3paQZABLxH5pzCWI9PzIAVfPDrm+sdnbgG7vAnwfL2IMMJSA3aDYGCbF9EgefG+STcpfqq7fQ6f5TBgLFwKBgCd7gn1xYL696SaKVSm7VngpXlczHVEpz3kStWR5gfzriPBxXgMVcWmcbajRser7ARpCEfbxM1UJyv6oAYZWVSNErNzNVb4POqLYcCNySuC6xKhs9FrEQnyKjyk8wI4VnrEMGrQ8e+qYSwYk9Gh6dKGoRMAPYVXQAO0fIsHF/T0a\n';
61+
const key = Buffer.from(pemFileData, 'base64');
62+
const output = Buffer.alloc(256);
63+
const expectedOutput = Buffer.from(
64+
'VocBRhpMmQ2XCzVehWSqheQLnU889gf3dhU4AnVnQTJjsKx/CM23qKDPkZDd2A/BnQsp99SN7ksIX5Raj0TPwyN5OCN/YrNFNGoOFlTsGhgP/hyE8X3Duiq6sNO0SMvRYNPFFGlJFsp1Fw3Z94eYMg4/Wpw5s4+Jo5Zm/qY7aTJIqDKDQ3CNHLeJgcMUOc9sz01/GzoUYKDVODHSxrYEk5ireFJFz9vP8P7Ha+VDUZuQIQdXer9NBbGFtYmWprY3nn4D3Dw93Sn0V0dIqYeIo91oKyslvMebmUM95S2PyIJdEpPb2DJDxjvX/0LLwSWlSXRWy9gapWoBkb4ynqZBsg==',
65+
'base64'
66+
);
67+
68+
const { signRsaSha256Hook } = cryptoCallbacks;
69+
const err = signRsaSha256Hook(key, input, output);
70+
if (err instanceof Error) {
71+
expect(err).to.not.exist;
72+
}
73+
74+
expect(output).to.deep.equal(expectedOutput);
75+
});
76+
77+
it('should invoke crypto callbacks when doing encryption', async function () {
78+
function assertCertainHooksCalled(expectedSet?) {
79+
expectedSet = expectedSet || new Set([]);
80+
for (const name of hookNames) {
81+
const hook = cryptoCallbacks[name];
82+
if (expectedSet.has(name)) {
83+
expect(hook).to.have.been.called;
84+
} else {
85+
expect(hook).to.not.have.been.called;
86+
}
87+
88+
hook.resetHistory();
89+
}
90+
}
91+
92+
const encryption = new ClientEncryption(client, {
93+
keyVaultNamespace: 'test.encryption',
94+
kmsProviders
95+
});
96+
97+
assertCertainHooksCalled();
98+
99+
const dataKeyId = await encryption.createDataKey('aws', dataKeyOptions);
100+
assertCertainHooksCalled(new Set(['hmacSha256Hook', 'sha256Hook', 'randomHook']));
101+
102+
const encryptOptions = {
103+
keyId: dataKeyId,
104+
algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'
105+
};
106+
107+
const encryptedValue = await encryption.encrypt('hello', encryptOptions);
108+
assertCertainHooksCalled(
109+
new Set(['aes256CbcEncryptHook', 'hmacSha512Hook', 'hmacSha256Hook', 'sha256Hook'])
110+
);
111+
112+
await encryption.decrypt(encryptedValue);
113+
assertCertainHooksCalled(new Set(['aes256CbcDecryptHook', 'hmacSha512Hook']));
114+
});
115+
116+
describe('error testing', function () {
117+
beforeEach(async function () {
118+
sandbox?.restore();
119+
});
120+
121+
for (const hookName of ['aes256CbcEncryptHook', 'aes256CbcDecryptHook', 'hmacSha512Hook']) {
122+
it(`should properly propagate an error when ${hookName} fails`, async function () {
123+
const error = new Error('some random error text');
124+
sandbox.stub(cryptoCallbacks, hookName).returns(error);
125+
126+
const encryption = new ClientEncryption(client, {
127+
keyVaultNamespace: 'test.encryption',
128+
kmsProviders
129+
});
130+
131+
const result = await (async () => {
132+
const dataKeyId = await encryption.createDataKey('aws', dataKeyOptions);
133+
const encryptOptions = {
134+
keyId: dataKeyId,
135+
algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'
136+
};
137+
138+
const encryptedValue = await encryption.encrypt('hello', encryptOptions);
139+
await encryption.decrypt(encryptedValue);
140+
})().then(
141+
() => null,
142+
error => error
143+
);
144+
145+
expect(result).to.be.instanceOf(Error);
146+
});
147+
}
148+
149+
// These ones will fail with an error, but that error will get overridden
150+
// with "failed to create KMS message" in mongocrypt-kms-ctx.c
151+
for (const hookName of ['hmacSha256Hook', 'sha256Hook']) {
152+
it(`should error with a specific kms error when ${hookName} fails`, async function () {
153+
const error = new Error('some random error text');
154+
sandbox.stub(cryptoCallbacks, hookName).returns(error);
155+
156+
const encryption = new ClientEncryption(client, {
157+
keyVaultNamespace: 'test.encryption',
158+
kmsProviders
159+
});
160+
161+
const result = await encryption.createDataKey('aws', dataKeyOptions).catch(error => error);
162+
expect(result).to.match(/failed to create KMS message/);
163+
});
164+
}
165+
166+
it('should error asynchronously with error when randomHook fails', async function () {
167+
const error = new Error('some random error text');
168+
sandbox.stub(cryptoCallbacks, 'randomHook').returns(error);
169+
170+
const encryption = new ClientEncryption(client, {
171+
keyVaultNamespace: 'test.encryption',
172+
kmsProviders
173+
});
174+
175+
const result = await encryption.createDataKey('aws', dataKeyOptions).catch(error => error);
176+
expect(result).to.have.property('message', 'some random error text');
177+
});
178+
});
179+
});

0 commit comments

Comments
 (0)