@naturalcycles/nodejs-lib 12.67.1 → 12.68.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.
- package/dist/secret/secrets-decrypt.util.js +1 -4
- package/dist/secret/secrets-encrypt.util.js +1 -4
- package/dist/security/crypto.util.d.ts +7 -0
- package/dist/security/crypto.util.js +36 -16
- package/dist/security/secret.util.js +2 -4
- package/package.json +1 -1
- package/src/secret/secrets-decrypt.util.ts +3 -6
- package/src/secret/secrets-encrypt.util.ts +3 -7
- package/src/security/crypto.util.ts +38 -18
- package/src/security/secret.util.ts +4 -6
|
@@ -24,10 +24,7 @@ function secretsDecrypt(dir, file, encKey, del = false, jsonMode = false) {
|
|
|
24
24
|
(0, js_lib_1._assert)(filename.endsWith('.json'), `${path.basename(filename)} MUST end with '.json'`);
|
|
25
25
|
(0, js_lib_1._assert)(!filename.endsWith('.plain.json'), `${path.basename(filename)} MUST NOT end with '.plain.json'`);
|
|
26
26
|
plainFilename = filename.replace('.json', '.plain.json');
|
|
27
|
-
const json = JSON.parse(fs.readFileSync(filename, 'utf8'));
|
|
28
|
-
(0, js_lib_1._stringMapEntries)(json).forEach(([k, v]) => {
|
|
29
|
-
json[k] = (0, crypto_util_1.decryptString)(v, encKey);
|
|
30
|
-
});
|
|
27
|
+
const json = (0, crypto_util_1.decryptObject)(JSON.parse(fs.readFileSync(filename, 'utf8')), encKey);
|
|
31
28
|
fs.writeFileSync(plainFilename, JSON.stringify(json, null, 2));
|
|
32
29
|
}
|
|
33
30
|
else {
|
|
@@ -24,10 +24,7 @@ function secretsEncrypt(pattern, file, encKey, del = false, jsonMode = false) {
|
|
|
24
24
|
if (jsonMode) {
|
|
25
25
|
(0, js_lib_1._assert)(filename.endsWith('.plain.json'), `${path.basename(filename)} MUST end with '.plain.json'`);
|
|
26
26
|
encFilename = filename.replace('.plain', '');
|
|
27
|
-
const json = JSON.parse(fs.readFileSync(filename, 'utf8'));
|
|
28
|
-
(0, js_lib_1._stringMapEntries)(json).forEach(([k, plain]) => {
|
|
29
|
-
json[k] = (0, crypto_util_1.encryptString)(plain, encKey);
|
|
30
|
-
});
|
|
27
|
+
const json = (0, crypto_util_1.encryptObject)(JSON.parse(fs.readFileSync(filename, 'utf8')), encKey);
|
|
31
28
|
fs.writeFileSync(encFilename, JSON.stringify(json, null, 2));
|
|
32
29
|
}
|
|
33
30
|
else {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
import { StringMap } from '@naturalcycles/js-lib';
|
|
2
3
|
/**
|
|
3
4
|
* Using aes-256-cbc
|
|
4
5
|
*/
|
|
@@ -7,6 +8,12 @@ export declare function encryptRandomIVBuffer(input: Buffer, secretKeyBase64: st
|
|
|
7
8
|
* Using aes-256-cbc
|
|
8
9
|
*/
|
|
9
10
|
export declare function decryptRandomIVBuffer(input: Buffer, secretKeyBase64: string): Buffer;
|
|
11
|
+
/**
|
|
12
|
+
* Decrypts all object values.
|
|
13
|
+
* Returns object with decrypted values.
|
|
14
|
+
*/
|
|
15
|
+
export declare function decryptObject(obj: StringMap, secretKey: string): StringMap;
|
|
16
|
+
export declare function encryptObject(obj: StringMap, secretKey: string): StringMap;
|
|
10
17
|
/**
|
|
11
18
|
* Using aes-256-cbc
|
|
12
19
|
*/
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.encryptString = exports.decryptString = exports.decryptRandomIVBuffer = exports.encryptRandomIVBuffer = void 0;
|
|
3
|
+
exports.encryptString = exports.decryptString = exports.encryptObject = exports.decryptObject = exports.decryptRandomIVBuffer = exports.encryptRandomIVBuffer = void 0;
|
|
4
4
|
const crypto = require("crypto");
|
|
5
|
+
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
6
|
const hash_util_1 = require("./hash.util");
|
|
6
7
|
const algorithm = 'aes-256-cbc';
|
|
7
8
|
/**
|
|
8
9
|
* Using aes-256-cbc
|
|
9
10
|
*/
|
|
10
11
|
function encryptRandomIVBuffer(input, secretKeyBase64) {
|
|
11
|
-
|
|
12
|
+
// md5 to match aes-256 key length of 32 bytes
|
|
13
|
+
const key = (0, hash_util_1.md5)(Buffer.from(secretKeyBase64, 'base64'));
|
|
12
14
|
// Random iv to achieve non-deterministic encryption (but deterministic decryption)
|
|
13
|
-
|
|
14
|
-
const iv = crypto.randomBytes(16); // use sync method here for speed
|
|
15
|
+
const iv = crypto.randomBytes(16);
|
|
15
16
|
const cipher = crypto.createCipheriv(algorithm, key, iv);
|
|
16
17
|
return Buffer.concat([iv, cipher.update(input), cipher.final()]);
|
|
17
18
|
}
|
|
@@ -20,7 +21,8 @@ exports.encryptRandomIVBuffer = encryptRandomIVBuffer;
|
|
|
20
21
|
* Using aes-256-cbc
|
|
21
22
|
*/
|
|
22
23
|
function decryptRandomIVBuffer(input, secretKeyBase64) {
|
|
23
|
-
|
|
24
|
+
// md5 to match aes-256 key length of 32 bytes
|
|
25
|
+
const key = (0, hash_util_1.md5)(Buffer.from(secretKeyBase64, 'base64'));
|
|
24
26
|
// iv is first 16 bytes of encrypted buffer, the rest is payload
|
|
25
27
|
const iv = input.slice(0, 16);
|
|
26
28
|
const payload = input.slice(16);
|
|
@@ -28,32 +30,50 @@ function decryptRandomIVBuffer(input, secretKeyBase64) {
|
|
|
28
30
|
return Buffer.concat([decipher.update(payload), decipher.final()]);
|
|
29
31
|
}
|
|
30
32
|
exports.decryptRandomIVBuffer = decryptRandomIVBuffer;
|
|
33
|
+
/**
|
|
34
|
+
* Decrypts all object values.
|
|
35
|
+
* Returns object with decrypted values.
|
|
36
|
+
*/
|
|
37
|
+
function decryptObject(obj, secretKey) {
|
|
38
|
+
const { key, iv } = getCryptoParams(secretKey);
|
|
39
|
+
const r = {};
|
|
40
|
+
(0, js_lib_1._stringMapEntries)(obj).forEach(([k, v]) => {
|
|
41
|
+
const decipher = crypto.createDecipheriv(algorithm, key, iv);
|
|
42
|
+
r[k] = decipher.update(v, 'base64', 'utf8') + decipher.final('utf8');
|
|
43
|
+
});
|
|
44
|
+
return r;
|
|
45
|
+
}
|
|
46
|
+
exports.decryptObject = decryptObject;
|
|
47
|
+
function encryptObject(obj, secretKey) {
|
|
48
|
+
const { key, iv } = getCryptoParams(secretKey);
|
|
49
|
+
const r = {};
|
|
50
|
+
(0, js_lib_1._stringMapEntries)(obj).forEach(([k, v]) => {
|
|
51
|
+
const cipher = crypto.createCipheriv(algorithm, key, iv);
|
|
52
|
+
r[k] = cipher.update(v, 'utf8', 'base64') + cipher.final('base64');
|
|
53
|
+
});
|
|
54
|
+
return r;
|
|
55
|
+
}
|
|
56
|
+
exports.encryptObject = encryptObject;
|
|
31
57
|
/**
|
|
32
58
|
* Using aes-256-cbc
|
|
33
59
|
*/
|
|
34
60
|
function decryptString(str, secretKey) {
|
|
35
|
-
const {
|
|
61
|
+
const { key, iv } = getCryptoParams(secretKey);
|
|
36
62
|
const decipher = crypto.createDecipheriv(algorithm, key, iv);
|
|
37
|
-
|
|
38
|
-
return (decrypted += decipher.final('utf8'));
|
|
63
|
+
return decipher.update(str, 'base64', 'utf8') + decipher.final('utf8');
|
|
39
64
|
}
|
|
40
65
|
exports.decryptString = decryptString;
|
|
41
66
|
/**
|
|
42
67
|
* Using aes-256-cbc
|
|
43
68
|
*/
|
|
44
69
|
function encryptString(str, secretKey) {
|
|
45
|
-
const {
|
|
70
|
+
const { key, iv } = getCryptoParams(secretKey);
|
|
46
71
|
const cipher = crypto.createCipheriv(algorithm, key, iv);
|
|
47
|
-
|
|
48
|
-
return (encrypted += cipher.final('base64'));
|
|
72
|
+
return cipher.update(str, 'utf8', 'base64') + cipher.final('base64');
|
|
49
73
|
}
|
|
50
74
|
exports.encryptString = encryptString;
|
|
51
75
|
function getCryptoParams(secretKey) {
|
|
52
76
|
const key = (0, hash_util_1.md5)(secretKey);
|
|
53
77
|
const iv = (0, hash_util_1.md5)(secretKey + key).slice(0, 16);
|
|
54
|
-
return {
|
|
55
|
-
}
|
|
56
|
-
function aes256Key(secretKeyBase64) {
|
|
57
|
-
// md5 to match aes-256 key length of 32 bytes
|
|
58
|
-
return (0, hash_util_1.md5)(Buffer.from(secretKeyBase64, 'base64'));
|
|
78
|
+
return { key, iv };
|
|
59
79
|
}
|
|
@@ -69,11 +69,9 @@ exports.loadSecretsFromEncryptedJsonFile = loadSecretsFromEncryptedJsonFile;
|
|
|
69
69
|
*/
|
|
70
70
|
function loadSecretsFromEncryptedJsonFileValues(filePath, secretEncryptionKey) {
|
|
71
71
|
(0, js_lib_1._assert)(fs.existsSync(filePath), `loadSecretsFromEncryptedJsonFileValues() cannot load from path: ${filePath}`);
|
|
72
|
-
|
|
72
|
+
let secrets = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
73
73
|
if (secretEncryptionKey) {
|
|
74
|
-
(0,
|
|
75
|
-
secrets[k] = (0, crypto_util_1.decryptString)(enc, secretEncryptionKey);
|
|
76
|
-
});
|
|
74
|
+
secrets = (0, crypto_util_1.decryptObject)(secrets, secretEncryptionKey);
|
|
77
75
|
}
|
|
78
76
|
Object.entries(secrets).forEach(([k, v]) => (secretMap[k.toUpperCase()] = v));
|
|
79
77
|
loaded = true;
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as path from 'path'
|
|
2
|
-
import { _assert
|
|
2
|
+
import { _assert } from '@naturalcycles/js-lib'
|
|
3
3
|
import * as fs from 'fs-extra'
|
|
4
4
|
import globby = require('globby')
|
|
5
5
|
import { dimGrey, yellow } from '../colors'
|
|
6
|
-
import {
|
|
6
|
+
import { decryptObject, decryptRandomIVBuffer } from '../security/crypto.util'
|
|
7
7
|
|
|
8
8
|
export interface DecryptCLIOptions {
|
|
9
9
|
dir: string[]
|
|
@@ -44,10 +44,7 @@ export function secretsDecrypt(
|
|
|
44
44
|
)
|
|
45
45
|
plainFilename = filename.replace('.json', '.plain.json')
|
|
46
46
|
|
|
47
|
-
const json
|
|
48
|
-
_stringMapEntries(json).forEach(([k, v]) => {
|
|
49
|
-
json[k] = decryptString(v, encKey)
|
|
50
|
-
})
|
|
47
|
+
const json = decryptObject(JSON.parse(fs.readFileSync(filename, 'utf8')), encKey)
|
|
51
48
|
|
|
52
49
|
fs.writeFileSync(plainFilename, JSON.stringify(json, null, 2))
|
|
53
50
|
} else {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as path from 'path'
|
|
2
|
-
import { _assert
|
|
2
|
+
import { _assert } from '@naturalcycles/js-lib'
|
|
3
3
|
import * as fs from 'fs-extra'
|
|
4
4
|
import globby = require('globby')
|
|
5
5
|
import { dimGrey, yellow } from '../colors'
|
|
6
|
-
import {
|
|
6
|
+
import { encryptObject, encryptRandomIVBuffer } from '../security/crypto.util'
|
|
7
7
|
|
|
8
8
|
export interface EncryptCLIOptions {
|
|
9
9
|
pattern: string[]
|
|
@@ -41,11 +41,7 @@ export function secretsEncrypt(
|
|
|
41
41
|
)
|
|
42
42
|
encFilename = filename.replace('.plain', '')
|
|
43
43
|
|
|
44
|
-
const json
|
|
45
|
-
|
|
46
|
-
_stringMapEntries(json).forEach(([k, plain]) => {
|
|
47
|
-
json[k] = encryptString(plain, encKey)
|
|
48
|
-
})
|
|
44
|
+
const json = encryptObject(JSON.parse(fs.readFileSync(filename, 'utf8')), encKey)
|
|
49
45
|
|
|
50
46
|
fs.writeFileSync(encFilename, JSON.stringify(json, null, 2))
|
|
51
47
|
} else {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as crypto from 'crypto'
|
|
2
|
+
import { _stringMapEntries, StringMap } from '@naturalcycles/js-lib'
|
|
2
3
|
import { md5 } from './hash.util'
|
|
3
4
|
|
|
4
5
|
const algorithm = 'aes-256-cbc'
|
|
@@ -7,12 +8,11 @@ const algorithm = 'aes-256-cbc'
|
|
|
7
8
|
* Using aes-256-cbc
|
|
8
9
|
*/
|
|
9
10
|
export function encryptRandomIVBuffer(input: Buffer, secretKeyBase64: string): Buffer {
|
|
10
|
-
|
|
11
|
+
// md5 to match aes-256 key length of 32 bytes
|
|
12
|
+
const key = md5(Buffer.from(secretKeyBase64, 'base64'))
|
|
11
13
|
|
|
12
14
|
// Random iv to achieve non-deterministic encryption (but deterministic decryption)
|
|
13
|
-
|
|
14
|
-
const iv = crypto.randomBytes(16) // use sync method here for speed
|
|
15
|
-
|
|
15
|
+
const iv = crypto.randomBytes(16)
|
|
16
16
|
const cipher = crypto.createCipheriv(algorithm, key, iv)
|
|
17
17
|
|
|
18
18
|
return Buffer.concat([iv, cipher.update(input), cipher.final()])
|
|
@@ -22,7 +22,8 @@ export function encryptRandomIVBuffer(input: Buffer, secretKeyBase64: string): B
|
|
|
22
22
|
* Using aes-256-cbc
|
|
23
23
|
*/
|
|
24
24
|
export function decryptRandomIVBuffer(input: Buffer, secretKeyBase64: string): Buffer {
|
|
25
|
-
|
|
25
|
+
// md5 to match aes-256 key length of 32 bytes
|
|
26
|
+
const key = md5(Buffer.from(secretKeyBase64, 'base64'))
|
|
26
27
|
|
|
27
28
|
// iv is first 16 bytes of encrypted buffer, the rest is payload
|
|
28
29
|
const iv = input.slice(0, 16)
|
|
@@ -33,33 +34,52 @@ export function decryptRandomIVBuffer(input: Buffer, secretKeyBase64: string): B
|
|
|
33
34
|
return Buffer.concat([decipher.update(payload), decipher.final()])
|
|
34
35
|
}
|
|
35
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Decrypts all object values.
|
|
39
|
+
* Returns object with decrypted values.
|
|
40
|
+
*/
|
|
41
|
+
export function decryptObject(obj: StringMap, secretKey: string): StringMap {
|
|
42
|
+
const { key, iv } = getCryptoParams(secretKey)
|
|
43
|
+
|
|
44
|
+
const r: StringMap = {}
|
|
45
|
+
_stringMapEntries(obj).forEach(([k, v]) => {
|
|
46
|
+
const decipher = crypto.createDecipheriv(algorithm, key, iv)
|
|
47
|
+
r[k] = decipher.update(v, 'base64', 'utf8') + decipher.final('utf8')
|
|
48
|
+
})
|
|
49
|
+
return r
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function encryptObject(obj: StringMap, secretKey: string): StringMap {
|
|
53
|
+
const { key, iv } = getCryptoParams(secretKey)
|
|
54
|
+
|
|
55
|
+
const r: StringMap = {}
|
|
56
|
+
_stringMapEntries(obj).forEach(([k, v]) => {
|
|
57
|
+
const cipher = crypto.createCipheriv(algorithm, key, iv)
|
|
58
|
+
r[k] = cipher.update(v, 'utf8', 'base64') + cipher.final('base64')
|
|
59
|
+
})
|
|
60
|
+
return r
|
|
61
|
+
}
|
|
62
|
+
|
|
36
63
|
/**
|
|
37
64
|
* Using aes-256-cbc
|
|
38
65
|
*/
|
|
39
66
|
export function decryptString(str: string, secretKey: string): string {
|
|
40
|
-
const {
|
|
67
|
+
const { key, iv } = getCryptoParams(secretKey)
|
|
41
68
|
const decipher = crypto.createDecipheriv(algorithm, key, iv)
|
|
42
|
-
|
|
43
|
-
return (decrypted += decipher.final('utf8'))
|
|
69
|
+
return decipher.update(str, 'base64', 'utf8') + decipher.final('utf8')
|
|
44
70
|
}
|
|
45
71
|
|
|
46
72
|
/**
|
|
47
73
|
* Using aes-256-cbc
|
|
48
74
|
*/
|
|
49
75
|
export function encryptString(str: string, secretKey: string): string {
|
|
50
|
-
const {
|
|
76
|
+
const { key, iv } = getCryptoParams(secretKey)
|
|
51
77
|
const cipher = crypto.createCipheriv(algorithm, key, iv)
|
|
52
|
-
|
|
53
|
-
return (encrypted += cipher.final('base64'))
|
|
78
|
+
return cipher.update(str, 'utf8', 'base64') + cipher.final('base64')
|
|
54
79
|
}
|
|
55
80
|
|
|
56
|
-
function getCryptoParams(secretKey: string): {
|
|
81
|
+
function getCryptoParams(secretKey: string): { key: string; iv: string } {
|
|
57
82
|
const key = md5(secretKey)
|
|
58
83
|
const iv = md5(secretKey + key).slice(0, 16)
|
|
59
|
-
return {
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function aes256Key(secretKeyBase64: string): string {
|
|
63
|
-
// md5 to match aes-256 key length of 32 bytes
|
|
64
|
-
return md5(Buffer.from(secretKeyBase64, 'base64'))
|
|
84
|
+
return { key, iv }
|
|
65
85
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from 'fs'
|
|
2
|
-
import { _assert,
|
|
2
|
+
import { _assert, StringMap } from '@naturalcycles/js-lib'
|
|
3
3
|
import { base64ToString } from '..'
|
|
4
|
-
import {
|
|
4
|
+
import { decryptObject, decryptRandomIVBuffer } from './crypto.util'
|
|
5
5
|
|
|
6
6
|
let loaded = false
|
|
7
7
|
|
|
@@ -93,12 +93,10 @@ export function loadSecretsFromEncryptedJsonFileValues(
|
|
|
93
93
|
`loadSecretsFromEncryptedJsonFileValues() cannot load from path: ${filePath}`,
|
|
94
94
|
)
|
|
95
95
|
|
|
96
|
-
|
|
96
|
+
let secrets: StringMap = JSON.parse(fs.readFileSync(filePath, 'utf8'))
|
|
97
97
|
|
|
98
98
|
if (secretEncryptionKey) {
|
|
99
|
-
|
|
100
|
-
secrets[k] = decryptString(enc, secretEncryptionKey)
|
|
101
|
-
})
|
|
99
|
+
secrets = decryptObject(secrets, secretEncryptionKey)
|
|
102
100
|
}
|
|
103
101
|
|
|
104
102
|
Object.entries(secrets).forEach(([k, v]) => (secretMap[k.toUpperCase()] = v))
|