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