k9crypt 1.1.1 → 1.1.2
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/README.md +2 -2
- package/package.json +7 -5
- package/src/constants.js +4 -4
- package/src/index.js +16 -38
- package/src/utils/compression.js +16 -25
- package/src/utils/encryption.js +14 -14
- package/src/utils/hashing.js +5 -6
- package/src/utils/keyDerivation.js +9 -16
- package/src/utils/math.js +4 -7
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "k9crypt",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "A special encryption algorithm created for K9Crypt.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -18,10 +18,12 @@
|
|
|
18
18
|
"author": "K9Crypt Team",
|
|
19
19
|
"license": "MIT",
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"bcrypt": "
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
21
|
+
"bcrypt": "^6.0.0",
|
|
22
|
+
"crypto-js": "^4.2.0",
|
|
23
|
+
"lz4": "^0.6.5",
|
|
24
|
+
"lzma-native": "^8.0.6",
|
|
25
|
+
"node-forge": "^1.3.1",
|
|
26
|
+
"xxhash": "^0.3.0"
|
|
25
27
|
},
|
|
26
28
|
"repository": {
|
|
27
29
|
"type": "git",
|
package/src/constants.js
CHANGED
|
@@ -4,7 +4,7 @@ module.exports = {
|
|
|
4
4
|
KEY_SIZE: 32,
|
|
5
5
|
TAG_SIZE: 16,
|
|
6
6
|
PBKDF2_ITERATIONS: 310000,
|
|
7
|
-
HASH_SEED:
|
|
8
|
-
PEPPER:
|
|
9
|
-
HMAC_KEY:
|
|
10
|
-
};
|
|
7
|
+
HASH_SEED: 0xCAFEBABE,
|
|
8
|
+
PEPPER: 'veryLongAndComplexPepperValue123!@#$%^&*()_+[]{}|;:,.<>?',
|
|
9
|
+
HMAC_KEY: 'veryLongAndComplexHMACKeyValue456!@#$%^&*()_+[]{}|;:,.<>?',
|
|
10
|
+
};
|
package/src/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
const crypto = require(
|
|
2
|
-
const { compress, decompress } = require(
|
|
3
|
-
const { deriveKey } = require(
|
|
4
|
-
const { encrypt, decrypt } = require(
|
|
5
|
-
const { hash, verifyHash } = require(
|
|
6
|
-
const { SALT_SIZE, IV_SIZE, TAG_SIZE } = require(
|
|
1
|
+
const crypto = require('crypto');
|
|
2
|
+
const { compress, decompress } = require('./utils/compression');
|
|
3
|
+
const { deriveKey } = require('./utils/keyDerivation');
|
|
4
|
+
const { encrypt, decrypt } = require('./utils/encryption');
|
|
5
|
+
const { hash, verifyHash } = require('./utils/hashing');
|
|
6
|
+
const { SALT_SIZE, IV_SIZE, TAG_SIZE } = require('./constants');
|
|
7
7
|
|
|
8
8
|
class K9crypt {
|
|
9
9
|
constructor(secretKey) {
|
|
@@ -15,41 +15,19 @@ class K9crypt {
|
|
|
15
15
|
const compressed = await compress(plaintext);
|
|
16
16
|
const salt = crypto.randomBytes(SALT_SIZE);
|
|
17
17
|
const key = await deriveKey(this.secretKey, salt);
|
|
18
|
-
const { iv1, iv2, iv3, iv4, iv5, encrypted, tag1 } = encrypt(
|
|
19
|
-
|
|
20
|
-
key,
|
|
21
|
-
);
|
|
22
|
-
const dataToHash = Buffer.concat([
|
|
23
|
-
salt,
|
|
24
|
-
iv1,
|
|
25
|
-
iv2,
|
|
26
|
-
iv3,
|
|
27
|
-
iv4,
|
|
28
|
-
iv5,
|
|
29
|
-
encrypted,
|
|
30
|
-
tag1,
|
|
31
|
-
]);
|
|
18
|
+
const { iv1, iv2, iv3, iv4, iv5, encrypted, tag1 } = encrypt(compressed, key);
|
|
19
|
+
const dataToHash = Buffer.concat([salt, iv1, iv2, iv3, iv4, iv5, encrypted, tag1]);
|
|
32
20
|
const dataHash = hash(dataToHash);
|
|
33
|
-
const result = Buffer.concat([
|
|
34
|
-
|
|
35
|
-
iv1,
|
|
36
|
-
iv2,
|
|
37
|
-
iv3,
|
|
38
|
-
iv4,
|
|
39
|
-
iv5,
|
|
40
|
-
encrypted,
|
|
41
|
-
tag1,
|
|
42
|
-
dataHash,
|
|
43
|
-
]);
|
|
44
|
-
return result.toString("base64");
|
|
21
|
+
const result = Buffer.concat([salt, iv1, iv2, iv3, iv4, iv5, encrypted, tag1, dataHash]);
|
|
22
|
+
return result.toString('base64');
|
|
45
23
|
} catch (error) {
|
|
46
|
-
console.log(
|
|
24
|
+
console.log('Encryption failed');
|
|
47
25
|
}
|
|
48
26
|
}
|
|
49
27
|
|
|
50
28
|
async decrypt(ciphertext) {
|
|
51
29
|
try {
|
|
52
|
-
const data = Buffer.from(ciphertext,
|
|
30
|
+
const data = Buffer.from(ciphertext, 'base64');
|
|
53
31
|
const salt = data.slice(0, SALT_SIZE);
|
|
54
32
|
const iv1 = data.slice(SALT_SIZE, SALT_SIZE + IV_SIZE);
|
|
55
33
|
const iv2 = data.slice(SALT_SIZE + IV_SIZE, SALT_SIZE + 2 * IV_SIZE);
|
|
@@ -62,17 +40,17 @@ class K9crypt {
|
|
|
62
40
|
|
|
63
41
|
const dataToVerify = data.slice(0, -64);
|
|
64
42
|
if (!verifyHash(dataToVerify, dataHash)) {
|
|
65
|
-
console.log(
|
|
43
|
+
console.log('Data integrity check failed');
|
|
66
44
|
}
|
|
67
45
|
|
|
68
46
|
const key = await deriveKey(this.secretKey, salt);
|
|
69
47
|
const decrypted = decrypt(encrypted, key, iv1, iv2, iv3, iv4, iv5, tag1);
|
|
70
48
|
const decompressed = await decompress(decrypted);
|
|
71
|
-
return decompressed.toString(
|
|
49
|
+
return decompressed.toString('utf8');
|
|
72
50
|
} catch (error) {
|
|
73
|
-
console.log(
|
|
51
|
+
console.log('Decryption failed');
|
|
74
52
|
}
|
|
75
53
|
}
|
|
76
54
|
}
|
|
77
55
|
|
|
78
|
-
module.exports = K9crypt;
|
|
56
|
+
module.exports = K9crypt;
|
package/src/utils/compression.js
CHANGED
|
@@ -1,35 +1,26 @@
|
|
|
1
|
-
const zlib = require(
|
|
2
|
-
const
|
|
1
|
+
const zlib = require('zlib');
|
|
2
|
+
const lzma = require('lzma-native');
|
|
3
3
|
|
|
4
4
|
exports.compress = async (data) => {
|
|
5
5
|
try {
|
|
6
6
|
const brotliParams = {
|
|
7
7
|
params: {
|
|
8
8
|
[zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT,
|
|
9
|
-
[zlib.constants.BROTLI_PARAM_QUALITY]:
|
|
10
|
-
|
|
11
|
-
[zlib.constants.
|
|
12
|
-
|
|
13
|
-
"utf8",
|
|
14
|
-
),
|
|
15
|
-
[zlib.constants.BROTLI_PARAM_LGWIN]: 24,
|
|
16
|
-
},
|
|
9
|
+
[zlib.constants.BROTLI_PARAM_QUALITY]: zlib.constants.BROTLI_MAX_QUALITY,
|
|
10
|
+
[zlib.constants.BROTLI_PARAM_SIZE_HINT]: Buffer.byteLength(data, 'utf8'),
|
|
11
|
+
[zlib.constants.BROTLI_PARAM_LGWIN]: 24
|
|
12
|
+
}
|
|
17
13
|
};
|
|
18
14
|
|
|
19
15
|
const brotliCompressed = await new Promise((resolve, reject) => {
|
|
20
|
-
zlib.brotliCompress(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (err) reject(err);
|
|
25
|
-
else resolve(compressed);
|
|
26
|
-
},
|
|
27
|
-
);
|
|
16
|
+
zlib.brotliCompress(Buffer.from(data, 'utf8'), brotliParams, (err, compressed) => {
|
|
17
|
+
if (err) reject(err);
|
|
18
|
+
else resolve(compressed);
|
|
19
|
+
});
|
|
28
20
|
});
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return pakoCompressed;
|
|
21
|
+
|
|
22
|
+
const lzmaCompressed = await lzma.compress(brotliCompressed, 9);
|
|
23
|
+
return lzmaCompressed;
|
|
33
24
|
} catch (error) {
|
|
34
25
|
throw new Error(`Compression error: ${error.message}`);
|
|
35
26
|
}
|
|
@@ -37,10 +28,10 @@ exports.compress = async (data) => {
|
|
|
37
28
|
|
|
38
29
|
exports.decompress = async (data) => {
|
|
39
30
|
try {
|
|
40
|
-
const
|
|
31
|
+
const lzmaDecompressed = await lzma.decompress(data);
|
|
41
32
|
|
|
42
33
|
const brotliDecompressed = await new Promise((resolve, reject) => {
|
|
43
|
-
zlib.brotliDecompress(
|
|
34
|
+
zlib.brotliDecompress(lzmaDecompressed, (err, decompressed) => {
|
|
44
35
|
if (err) reject(err);
|
|
45
36
|
else resolve(decompressed);
|
|
46
37
|
});
|
|
@@ -50,4 +41,4 @@ exports.decompress = async (data) => {
|
|
|
50
41
|
} catch (error) {
|
|
51
42
|
throw new Error(`Decompression error: ${error.message}`);
|
|
52
43
|
}
|
|
53
|
-
};
|
|
44
|
+
};
|
package/src/utils/encryption.js
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
const crypto = require(
|
|
2
|
-
const { IV_SIZE } = require(
|
|
3
|
-
const { reverseBuffer } = require(
|
|
1
|
+
const crypto = require('crypto');
|
|
2
|
+
const { IV_SIZE } = require('../constants');
|
|
3
|
+
const { reverseBuffer } = require('./math');
|
|
4
4
|
|
|
5
5
|
exports.encrypt = (data, key) => {
|
|
6
6
|
const iv1 = crypto.randomBytes(IV_SIZE);
|
|
7
|
-
const cipher1 = crypto.createCipheriv(
|
|
7
|
+
const cipher1 = crypto.createCipheriv('aes-256-gcm', key, iv1);
|
|
8
8
|
let encrypted1 = cipher1.update(data);
|
|
9
9
|
encrypted1 = Buffer.concat([encrypted1, cipher1.final()]);
|
|
10
10
|
const tag1 = cipher1.getAuthTag();
|
|
11
11
|
const iv2 = crypto.randomBytes(IV_SIZE);
|
|
12
|
-
const cipher2 = crypto.createCipheriv(
|
|
12
|
+
const cipher2 = crypto.createCipheriv('aes-256-cbc', key, iv2);
|
|
13
13
|
let encrypted2 = cipher2.update(encrypted1);
|
|
14
14
|
encrypted2 = Buffer.concat([encrypted2, cipher2.final()]);
|
|
15
15
|
const iv3 = crypto.randomBytes(IV_SIZE);
|
|
16
|
-
const cipher3 = crypto.createCipheriv(
|
|
16
|
+
const cipher3 = crypto.createCipheriv('aes-256-cfb', key, iv3);
|
|
17
17
|
let encrypted3 = cipher3.update(encrypted2);
|
|
18
18
|
encrypted3 = Buffer.concat([encrypted3, cipher3.final()]);
|
|
19
19
|
const iv4 = crypto.randomBytes(IV_SIZE);
|
|
20
|
-
const cipher4 = crypto.createCipheriv(
|
|
20
|
+
const cipher4 = crypto.createCipheriv('aes-256-ofb', key, iv4);
|
|
21
21
|
let encrypted4 = cipher4.update(encrypted3);
|
|
22
22
|
encrypted4 = Buffer.concat([encrypted4, cipher4.final()]);
|
|
23
23
|
const iv5 = crypto.randomBytes(IV_SIZE);
|
|
24
|
-
const cipher5 = crypto.createCipheriv(
|
|
24
|
+
const cipher5 = crypto.createCipheriv('aes-256-ctr', key, iv5);
|
|
25
25
|
let encrypted5 = cipher5.update(encrypted4);
|
|
26
26
|
encrypted5 = Buffer.concat([encrypted5, cipher5.final()]);
|
|
27
27
|
const permutedEncrypted = reverseBuffer(encrypted5);
|
|
@@ -31,22 +31,22 @@ exports.encrypt = (data, key) => {
|
|
|
31
31
|
|
|
32
32
|
exports.decrypt = (encrypted, key, iv1, iv2, iv3, iv4, iv5, tag1) => {
|
|
33
33
|
const originalEncrypted = reverseBuffer(encrypted, true);
|
|
34
|
-
const decipher5 = crypto.createDecipheriv(
|
|
34
|
+
const decipher5 = crypto.createDecipheriv('aes-256-ctr', key, iv5);
|
|
35
35
|
let decrypted5 = decipher5.update(originalEncrypted);
|
|
36
36
|
decrypted5 = Buffer.concat([decrypted5, decipher5.final()]);
|
|
37
|
-
const decipher4 = crypto.createDecipheriv(
|
|
37
|
+
const decipher4 = crypto.createDecipheriv('aes-256-ofb', key, iv4);
|
|
38
38
|
let decrypted4 = decipher4.update(decrypted5);
|
|
39
39
|
decrypted4 = Buffer.concat([decrypted4, decipher4.final()]);
|
|
40
|
-
const decipher3 = crypto.createDecipheriv(
|
|
40
|
+
const decipher3 = crypto.createDecipheriv('aes-256-cfb', key, iv3);
|
|
41
41
|
let decrypted3 = decipher3.update(decrypted4);
|
|
42
42
|
decrypted3 = Buffer.concat([decrypted3, decipher3.final()]);
|
|
43
|
-
const decipher2 = crypto.createDecipheriv(
|
|
43
|
+
const decipher2 = crypto.createDecipheriv('aes-256-cbc', key, iv2);
|
|
44
44
|
let decrypted2 = decipher2.update(decrypted3);
|
|
45
45
|
decrypted2 = Buffer.concat([decrypted2, decipher2.final()]);
|
|
46
|
-
const decipher1 = crypto.createDecipheriv(
|
|
46
|
+
const decipher1 = crypto.createDecipheriv('aes-256-gcm', key, iv1);
|
|
47
47
|
decipher1.setAuthTag(tag1);
|
|
48
48
|
let decrypted1 = decipher1.update(decrypted2);
|
|
49
49
|
decrypted1 = Buffer.concat([decrypted1, decipher1.final()]);
|
|
50
50
|
|
|
51
51
|
return decrypted1;
|
|
52
|
-
};
|
|
52
|
+
};
|
package/src/utils/hashing.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
const crypto = require(
|
|
2
|
-
const { HMAC_KEY } = require(
|
|
3
|
-
const { reverseHash } = require(
|
|
1
|
+
const crypto = require('crypto');
|
|
2
|
+
const { HMAC_KEY } = require('../constants');
|
|
3
|
+
const { reverseHash } = require('./math');
|
|
4
4
|
|
|
5
5
|
exports.hash = (data) => {
|
|
6
|
-
const hmac = crypto.createHmac(
|
|
6
|
+
const hmac = crypto.createHmac('sha512', HMAC_KEY);
|
|
7
7
|
hmac.update(data);
|
|
8
8
|
const digest = hmac.digest();
|
|
9
9
|
|
|
10
10
|
return reverseHash(digest);
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
-
exports.verifyHash = (data, hash) =>
|
|
14
|
-
crypto.timingSafeEqual(exports.hash(data), hash);
|
|
13
|
+
exports.verifyHash = (data, hash) => crypto.timingSafeEqual(exports.hash(data), hash);
|
|
@@ -1,23 +1,16 @@
|
|
|
1
|
-
const crypto = require(
|
|
2
|
-
const { PBKDF2_ITERATIONS, KEY_SIZE, PEPPER } = require(
|
|
3
|
-
const { enhanceKey } = require(
|
|
1
|
+
const crypto = require('crypto');
|
|
2
|
+
const { PBKDF2_ITERATIONS, KEY_SIZE, PEPPER } = require('../constants');
|
|
3
|
+
const { enhanceKey } = require('./math');
|
|
4
4
|
|
|
5
5
|
exports.deriveKey = (password, salt) => {
|
|
6
6
|
return new Promise((resolve, reject) => {
|
|
7
7
|
const pepperedPassword = password + PEPPER;
|
|
8
|
-
crypto.pbkdf2(
|
|
9
|
-
|
|
10
|
-
salt,
|
|
11
|
-
PBKDF2_ITERATIONS,
|
|
12
|
-
KEY_SIZE,
|
|
13
|
-
"sha512",
|
|
14
|
-
(err, key) => {
|
|
15
|
-
if (err) reject(err);
|
|
8
|
+
crypto.pbkdf2(pepperedPassword, salt, PBKDF2_ITERATIONS, KEY_SIZE, 'sha512', (err, key) => {
|
|
9
|
+
if (err) reject(err);
|
|
16
10
|
|
|
17
|
-
|
|
11
|
+
const enhancedKey = enhanceKey(key);
|
|
18
12
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
);
|
|
13
|
+
resolve(enhancedKey);
|
|
14
|
+
});
|
|
22
15
|
});
|
|
23
|
-
};
|
|
16
|
+
};
|
package/src/utils/math.js
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
exports.reverseBuffer = (data, reverse = false) => {
|
|
2
2
|
if (reverse) {
|
|
3
|
-
return Buffer.from(
|
|
4
|
-
data.toString("hex").split("").reverse().join(""),
|
|
5
|
-
"hex",
|
|
6
|
-
);
|
|
3
|
+
return Buffer.from(data.toString('hex').split('').reverse().join(''), 'hex');
|
|
7
4
|
}
|
|
8
|
-
return Buffer.from(data.toString(
|
|
5
|
+
return Buffer.from(data.toString('hex').split('').reverse().join(''), 'hex');
|
|
9
6
|
};
|
|
10
7
|
|
|
11
8
|
exports.reverseHash = (hash) => {
|
|
12
|
-
return Buffer.from(hash.toString(
|
|
9
|
+
return Buffer.from(hash.toString('hex').split('').reverse().join(''), 'hex');
|
|
13
10
|
};
|
|
14
11
|
|
|
15
12
|
exports.enhanceKey = (key) => {
|
|
16
|
-
return Buffer.from(key.toString(
|
|
13
|
+
return Buffer.from(key.toString('hex').split('').reverse().join(''), 'hex');
|
|
17
14
|
};
|