1 | ;
|
2 | /*
|
3 | * Copyright (c) 2018, salesforce.com, inc.
|
4 | * All rights reserved.
|
5 | * SPDX-License-Identifier: BSD-3-Clause
|
6 | * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
7 | */
|
8 | Object.defineProperty(exports, "__esModule", { value: true });
|
9 | const ts_types_1 = require("@salesforce/ts-types");
|
10 | const crypto = require("crypto");
|
11 | const cipherName = 'aes256';
|
12 | const cipherSize = 32;
|
13 | /**
|
14 | * Used to store and retrieve a sensitive information in memory. This is not meant for at rest encryption.
|
15 | *
|
16 | * ```
|
17 | * const sString: SecureBuffer<string> = new SecureBuffer();
|
18 | * sString.consume(secretTextBuffer);
|
19 | * const value: string = sString.value((buffer: Buffer): string => {
|
20 | * const password: string = buffer.toString('utf8');
|
21 | * // doSomething with the password
|
22 | * // returns something of type <T>
|
23 | * return testReturnValue;
|
24 | * });
|
25 | * ```
|
26 | */
|
27 | class SecureBuffer {
|
28 | constructor() {
|
29 | this.key = crypto.randomBytes(cipherSize);
|
30 | this.iv = crypto.randomBytes(16);
|
31 | }
|
32 | /**
|
33 | * Invokes a callback with a decrypted version of the buffer.
|
34 | * @param cb The callback containing the decrypted buffer parameter that returns a desired.
|
35 | * typed object. It's important to understand that once the callback goes out of scope the buffer parameters is
|
36 | * overwritten with random data. Do not make a copy of this buffer and persist it!
|
37 | */
|
38 | value(cb) {
|
39 | if (cb) {
|
40 | const cipher = crypto.createDecipheriv(cipherName, this.key, this.iv);
|
41 | const a = cipher.update(ts_types_1.ensure(this.secret));
|
42 | const b = cipher.final();
|
43 | const c = Buffer.concat([a, b]);
|
44 | try {
|
45 | return cb(c);
|
46 | }
|
47 | finally {
|
48 | crypto.randomFillSync(a);
|
49 | crypto.randomFillSync(b);
|
50 | crypto.randomFillSync(c);
|
51 | }
|
52 | }
|
53 | }
|
54 | /**
|
55 | * Overwrites the value of the encrypted secret with random data.
|
56 | */
|
57 | clear() {
|
58 | if (this.secret) {
|
59 | crypto.randomFillSync(this.secret);
|
60 | }
|
61 | const cipher = crypto.createCipheriv(cipherName, this.key, this.iv);
|
62 | this.secret = Buffer.concat([cipher.update(Buffer.from('')), cipher.final()]);
|
63 | }
|
64 | /**
|
65 | * Consumes a buffer of data that's intended to be secret.
|
66 | * @param buffer Data to encrypt. The input buffer is overwritten with random data after it's encrypted
|
67 | * and assigned internally.
|
68 | */
|
69 | consume(buffer) {
|
70 | let targetBuffer = buffer;
|
71 | if (!targetBuffer) {
|
72 | targetBuffer = Buffer.from('');
|
73 | }
|
74 | const cipher = crypto.createCipheriv(cipherName, this.key, this.iv);
|
75 | this.secret = Buffer.concat([cipher.update(targetBuffer), cipher.final()]);
|
76 | crypto.randomFillSync(targetBuffer);
|
77 | }
|
78 | }
|
79 | exports.SecureBuffer = SecureBuffer;
|
80 | //# sourceMappingURL=secureBuffer.js.map |
\ | No newline at end of file |