From 72d763369f651f59fe5c53f768c47936df55ba72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lteri=C5=9F=20Ero=C4=9Flu?= Date: Tue, 4 Jul 2017 02:46:09 +0300 Subject: [PATCH 01/15] little typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c39df8c..23afd9c 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Usage without downloading from NPM Gather basic256.js first, copy all files inside to your project folder/direcory. -And do this on your terminalif you are not root: +And do this on your terminal if you are not root: npm install From f2144406c0dccf6482bf821b22b1ce3bd3d01dc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lteri=C5=9F=20Ero=C4=9Flu?= Date: Wed, 23 Aug 2017 02:25:50 +0300 Subject: [PATCH 02/15] Update basic256.js --- basic256.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basic256.js b/basic256.js index 304b2f4..da5e0e0 100644 --- a/basic256.js +++ b/basic256.js @@ -78,7 +78,7 @@ module.exports = { chmac.update(IV.toString('hex')); if (!constant_time_compare(chmac.digest('hex'), hmac)) { - console.log("Encrypted Blob has been tampered with..."); + throw new Error("Encrypted Blob has been tampered with..."); return null; } From f83c9fe2545518076b6254fe85d3ba7e5796625f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lteri=C5=9F=20Ero=C4=9Flu?= Date: Wed, 23 Aug 2017 03:35:03 +0300 Subject: [PATCH 03/15] Update basic256.js --- basic256.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basic256.js b/basic256.js index da5e0e0..b5b3af7 100644 --- a/basic256.js +++ b/basic256.js @@ -78,7 +78,7 @@ module.exports = { chmac.update(IV.toString('hex')); if (!constant_time_compare(chmac.digest('hex'), hmac)) { - throw new Error("Encrypted Blob has been tampered with..."); + Promise.reject("Encrypted Blob has been tampered with..."); return null; } From 8419ea74a50cf338723dff2e34b99c384e3acafc Mon Sep 17 00:00:00 2001 From: linuxgemini Date: Wed, 23 Aug 2017 03:38:17 +0300 Subject: [PATCH 04/15] test in progress --- README.md | 4 +-- basic256.js | 76 ++++++++++++++++++++++++---------------------------- package.json | 3 ++- test.js | 10 +++---- 4 files changed, 44 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 23afd9c..09b2190 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ Then make your script connected. Example: var crypter = require("./basic256.js"); - var blob = crypter.enc.run("FOO"); // This encrypts the string "FOO". + var blob = crypter.encrypt("FOO").catch(console.error); // This encrypts the string "FOO". console.log(blob); // This will show the encrypted string. - var unblob = crypter.dec.run(blob); // This decrypts the encrypted string. + var unblob = crypter.decrypt(blob).catch(console.error); // This decrypts the encrypted string. console.log(unblob); // This will show the decrypted string. (Which in this case, it is "FOO") diff --git a/basic256.js b/basic256.js index b5b3af7..2618007 100644 --- a/basic256.js +++ b/basic256.js @@ -2,15 +2,10 @@ let crypto = require('crypto'); -function UserException(message) { - this.message = message; - this.name = 'UserException'; -} - try { var savedKeys = require("./config.js").k; } catch (e) { - throw new UserException('No Configuration Exists'); + Promise.reject('No Configuration Exists!'); } var ALGORITHM, KEY, HMAC_ALGORITHM, HMAC_KEY; @@ -43,48 +38,47 @@ var constant_time_compare = function (val1, val2) { module.exports = { - "enc": { - run : function (plain_text) { + "encrypt": function (plain_text) { + if (!plain_text || typeof(plain_text) !== "string") Promise.reject("Plain text not found."); - var IV = Buffer.from(randomValueHex(16)); // ensure that the IV (initialization vector) is random - var encryptor, cipher_text, hmac; + var IV = Buffer.from(randomValueHex(16)); // ensure that the IV (initialization vector) is random + var encryptor, cipher_text, hmac; - encryptor = crypto.createCipheriv(ALGORITHM, KEY, IV); - encryptor.setEncoding('hex'); - encryptor.write(plain_text); - encryptor.end(); + encryptor = crypto.createCipheriv(ALGORITHM, KEY, IV); + encryptor.setEncoding('hex'); + encryptor.write(plain_text); + encryptor.end(); - cipher_text = encryptor.read(); + cipher_text = encryptor.read(); - hmac = crypto.createHmac(HMAC_ALGORITHM, HMAC_KEY); - hmac.update(cipher_text); - hmac.update(IV.toString('hex')); // ensure that both the IV and the cipher-text is protected by the HMAC + hmac = crypto.createHmac(HMAC_ALGORITHM, HMAC_KEY); + hmac.update(cipher_text); + hmac.update(IV.toString('hex')); // ensure that both the IV and the cipher-text is protected by the HMAC - // The IV isn't a secret so it can be stored along side everything else - return cipher_text + "$" + IV.toString('hex') + "$" + hmac.digest('hex') - } + // The IV isn't a secret so it can be stored along side everything else + return cipher_text + "$" + IV.toString('hex') + "$" + hmac.digest('hex') }, - "dec": { - run : function (cipher_text) { - var cipher_blob = cipher_text.split("$"); - var ct = cipher_blob[0]; - var IV = Buffer.from(cipher_blob[1], 'hex'); - var hmac = cipher_blob[2]; - var chmac, decryptor; - - chmac = crypto.createHmac(HMAC_ALGORITHM, HMAC_KEY); - chmac.update(ct); - chmac.update(IV.toString('hex')); - - if (!constant_time_compare(chmac.digest('hex'), hmac)) { - Promise.reject("Encrypted Blob has been tampered with..."); - return null; - } - - decryptor = crypto.createDecipheriv(ALGORITHM, KEY, IV); - var decryptedText = decryptor.update(ct, 'hex', 'utf-8'); - return decryptedText + decryptor.final('utf-8'); + "decrypt": function (cipher_text) { + if (!cipher_text || typeof(cipher_text) !== "string" || !cipher_text.match("$")) Promise.reject("A valid cipher text not found."); + + var cipher_blob = cipher_text.split("$"); + var ct = cipher_blob[0]; + var IV = Buffer.from(cipher_blob[1], 'hex'); + var hmac = cipher_blob[2]; + var chmac, decryptor; + + chmac = crypto.createHmac(HMAC_ALGORITHM, HMAC_KEY); + chmac.update(ct); + chmac.update(IV.toString('hex')); + + if (!constant_time_compare(chmac.digest('hex'), hmac)) { + Promise.reject("Encrypted Blob has been tampered with."); } + + decryptor = crypto.createDecipheriv(ALGORITHM, KEY, IV); + var decryptedText = decryptor.update(ct, 'hex', 'utf-8'); + return decryptedText + decryptor.final('utf-8'); } + } diff --git a/package.json b/package.json index 12c0918..bd03e84 100644 --- a/package.json +++ b/package.json @@ -15,5 +15,6 @@ "scripts": { "install": "node ./DontRunMe.js", "test": "node ./test.js" - } + }, + "main": "./basic256" } diff --git a/test.js b/test.js index 0e51652..362b381 100644 --- a/test.js +++ b/test.js @@ -3,15 +3,15 @@ var m = require("./basic256"); console.log("Encrypting string \"foo\"..."); -var encStr = m.enc.run("foo"); +var encStr = m.encrypt("foo"); console.log("\nDecrypting the string below...\n" + encStr); -var decStr = m.dec.run(encStr); -console.log("\n\nResult: " + decStr); +var decStr = m.decrypt(encStr); +console.log("\nResult: " + decStr); if (decStr === "foo") { console.log("\nSUCCESS!"); - setTimeout(function(){process.exit(0);},853); + setTimeout(() => {process.exit(0);},853); } else { console.error("\nFAILURE!"); - setTimeout(function(){process.exit(1);},853); + setTimeout(() => {process.exit(1);},853); } From 1eb24a5b6f2d860689bd718a92fac8d2be4f597f Mon Sep 17 00:00:00 2001 From: linuxgemini Date: Wed, 23 Aug 2017 03:40:53 +0300 Subject: [PATCH 05/15] fix in promise rejection --- basic256.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/basic256.js b/basic256.js index 2618007..9c7eb2f 100644 --- a/basic256.js +++ b/basic256.js @@ -5,7 +5,7 @@ let crypto = require('crypto'); try { var savedKeys = require("./config.js").k; } catch (e) { - Promise.reject('No Configuration Exists!'); + return Promise.reject('No Configuration Exists!'); } var ALGORITHM, KEY, HMAC_ALGORITHM, HMAC_KEY; @@ -39,7 +39,7 @@ var constant_time_compare = function (val1, val2) { module.exports = { "encrypt": function (plain_text) { - if (!plain_text || typeof(plain_text) !== "string") Promise.reject("Plain text not found."); + if (!plain_text || typeof(plain_text) !== "string") return Promise.reject("Plain text not found."); var IV = Buffer.from(randomValueHex(16)); // ensure that the IV (initialization vector) is random var encryptor, cipher_text, hmac; @@ -60,7 +60,7 @@ module.exports = { }, "decrypt": function (cipher_text) { - if (!cipher_text || typeof(cipher_text) !== "string" || !cipher_text.match("$")) Promise.reject("A valid cipher text not found."); + if (!cipher_text || typeof(cipher_text) !== "string" || !cipher_text.match("$")) return Promise.reject("A valid cipher text not found."); var cipher_blob = cipher_text.split("$"); var ct = cipher_blob[0]; @@ -73,7 +73,7 @@ module.exports = { chmac.update(IV.toString('hex')); if (!constant_time_compare(chmac.digest('hex'), hmac)) { - Promise.reject("Encrypted Blob has been tampered with."); + return Promise.reject("Encrypted Blob has been tampered with."); } decryptor = crypto.createDecipheriv(ALGORITHM, KEY, IV); From cfb9bb40ef1c8c11501ec172427eba57f10c1c5c Mon Sep 17 00:00:00 2001 From: linuxgemini Date: Wed, 23 Aug 2017 03:45:43 +0300 Subject: [PATCH 06/15] fixes and stuff --- basic256.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/basic256.js b/basic256.js index 9c7eb2f..ebc950c 100644 --- a/basic256.js +++ b/basic256.js @@ -39,7 +39,7 @@ var constant_time_compare = function (val1, val2) { module.exports = { "encrypt": function (plain_text) { - if (!plain_text || typeof(plain_text) !== "string") return Promise.reject("Plain text not found."); + if (!plain_text || typeof(plain_text) !== "string") return Promise.reject("Plain text was not found."); var IV = Buffer.from(randomValueHex(16)); // ensure that the IV (initialization vector) is random var encryptor, cipher_text, hmac; @@ -60,7 +60,7 @@ module.exports = { }, "decrypt": function (cipher_text) { - if (!cipher_text || typeof(cipher_text) !== "string" || !cipher_text.match("$")) return Promise.reject("A valid cipher text not found."); + if (!cipher_text || typeof(cipher_text) !== "string" || !cipher_text.match(/\$/g)) return Promise.reject("A valid cipher text was not found."); var cipher_blob = cipher_text.split("$"); var ct = cipher_blob[0]; From 8e52a7d7b42e9ef1a8ac6f7baefa1cfd3a1539aa Mon Sep 17 00:00:00 2001 From: linuxgemini Date: Wed, 23 Aug 2017 04:01:25 +0300 Subject: [PATCH 07/15] new rel --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bd03e84..ea7f5bf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "basic256.js", - "version": "0.0.1", + "version": "1.0.0", "description": "A basic encryption/decryption script/API for resting data for Node.js users.", "readme": "README.md", "maintainers": [ From 81bc2e51b263a14bf75bf7b721ddd890a5449bb9 Mon Sep 17 00:00:00 2001 From: linuxgemini Date: Wed, 23 Aug 2017 04:13:06 +0300 Subject: [PATCH 08/15] fixes --- README.md | 42 +++++++++++++++++++++++++++++++++--------- package.json | 6 +++--- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 09b2190..5b4969c 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,30 @@ A basic encryption/decryption script/API for resting data for Node.js users. *Slightly* modified the work of [Levi Gross](http://www.levigross.com/2014/03/30/how-to-write-an-encrypt-and-decrypt-api-for-data-at-rest-in-nodejs/). +Usage with downloading from NPM +----- + +Open a terminal in your project folder and make sure that you have a package.json file. + +And do this on your terminal if you are not root: + + npm install --save basic256.js + +If you are running as root, do this: + + npm install --unsafe-perm --save basic256.js + +Then make your script connected. Example: + + var crypter = require("basic256.js"); + + var blob = crypter.encrypt("FOO").catch(console.error); // This encrypts the string "FOO". + console.log(blob); // This will show the encrypted string. + + var unblob = crypter.decrypt(blob).catch(console.error); // This decrypts the encrypted string. + console.log(unblob); // This will show the decrypted string. (Which in this case, it is "FOO") + + Usage without downloading from NPM ----- @@ -14,18 +38,18 @@ Gather basic256.js first, copy all files inside to your project folder/direcory. And do this on your terminal if you are not root: - npm install + npm install If you are running as root, do this: - npm install --unsafe-perm + npm install --unsafe-perm Then make your script connected. Example: - var crypter = require("./basic256.js"); - - var blob = crypter.encrypt("FOO").catch(console.error); // This encrypts the string "FOO". - console.log(blob); // This will show the encrypted string. - - var unblob = crypter.decrypt(blob).catch(console.error); // This decrypts the encrypted string. - console.log(unblob); // This will show the decrypted string. (Which in this case, it is "FOO") + var crypter = require("./basic256.js"); + + var blob = crypter.encrypt("FOO").catch(console.error); // This encrypts the string "FOO". + console.log(blob); // This will show the encrypted string. + + var unblob = crypter.decrypt(blob).catch(console.error); // This decrypts the encrypted string. + console.log(unblob); // This will show the decrypted string. (Which in this case, it is "FOO") diff --git a/package.json b/package.json index ea7f5bf..1e66674 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "basic256.js", - "version": "1.0.0", + "version": "1.0.1", "description": "A basic encryption/decryption script/API for resting data for Node.js users.", "readme": "README.md", "maintainers": [ @@ -13,8 +13,8 @@ }, "license": "Apache-2.0", "scripts": { - "install": "node ./DontRunMe.js", - "test": "node ./test.js" + "install": "node DontRunMe.js", + "test": "node test.js" }, "main": "./basic256" } From 2f3ca6ea072dc9cab8ee01e826552f5c46dd0fc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lteri=C5=9F=20Ero=C4=9Flu?= Date: Sat, 3 Mar 2018 16:47:42 +0300 Subject: [PATCH 09/15] Rewrite Update... * Rewritten key generation script * Rewritten class * Cleaned up code * Cleaned up readme --- .eslintrc.json | 38 +++++++++++++++ .gitignore | 2 + .travis.yml | 5 +- DontRunMe.js | 70 +++++++++++++++++++-------- LICENSE | 2 +- README.md | 52 ++++++++------------ basic256.js | 121 +++++++++++++++++++++++++--------------------- package-lock.json | 13 +++++ package.json | 5 +- test.js | 69 ++++++++++++++++++++------ 10 files changed, 249 insertions(+), 128 deletions(-) create mode 100644 .eslintrc.json create mode 100644 .gitignore create mode 100644 package-lock.json diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..30cb1a0 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,38 @@ +{ + "env": { + "es6": true, + "node": true + }, + "extends": "eslint:recommended", + "parserOptions": { + "ecmaVersion": 2017, + "sourceType": "module", + "impliedStrict": true, + "ecmaFeatures": { + "experimentalObjectRestSpread": true + } + }, + "rules": { + "indent": [ + "error", + 4, + { + "SwitchCase": 1 + } + ], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + "error", + "double" + ], + "semi": [ + "error", + "always" + ], + "no-console": 0, + "no-unused-vars": "warn" + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8fb1670 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +.basic256rc.js diff --git a/.travis.yml b/.travis.yml index 34a663e..ffdc18a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,10 +3,7 @@ sudo: enabled group: edge node_js: - "node" - - "7" - - "6" - - "5" - - "4" + - "8" install: - npm install script: diff --git a/DontRunMe.js b/DontRunMe.js index 8eaf6f2..89f3b9e 100644 --- a/DontRunMe.js +++ b/DontRunMe.js @@ -1,28 +1,60 @@ -'use strict'; +"use strict"; -let crypto = require('crypto'); // define crypto -let fs = require('fs'); // define filesys +const detectNewline = require("detect-newline"); +const crypto = require("crypto"); // define crypto +const fs = require("fs"); // define filesys +let projectRoot = require("path").dirname(require.main.filename); +let fetchedKey, fetchedHMAC, convertedConfig = false; -function randomValueHex (len) { +const exit = (msg) => { + console.log(msg); + return setTimeout(() => { + process.exit(0); + }, 2000); +}; + +const randomValueHex = (len) => { return crypto.randomBytes(Math.ceil(len/2)) - .toString('hex') // convert to hexadecimal format + .toString("hex") // convert to hexadecimal format .slice(0,len); // return required number of characters }; -if (fs.existsSync("./config.js")) { - return setTimeout(function(){ - process.exit(0); // exit script if config already exists - }, 833); -} +const main = () => { + if (fs.existsSync(`${projectRoot}/.gitignore`)) { + var file = fs.readFileSync(`${projectRoot}/.gitignore`).toString(); + var newlineChar = detectNewline(file); + if (!file.includes(".basic256rc.js")) fs.appendFileSync(`${projectRoot}/.gitignore`, `${newlineChar}.basic256rc.js${newlineChar}`); + } + + if (fs.existsSync(`${projectRoot}/.basic256rc.js`)) { + return exit("\n.basic256rc.js already exists, stopping setup.\n"); + } + + if (fs.existsSync("./config.js")) { + try { + var c = require("./config.js").k; + if (c.key) fetchedKey = c.key; + if (c.hmac_key) fetchedHMAC = c.hmac_key; + convertedConfig = true; + } catch (e) { + fetchedKey = null, + fetchedHMAC = null; + console.warn(`\nThere is an old config.js file in package.\nHowever, reading of the keys have failed:\n\n${e.stack}\n`); + } + } -let key = randomValueHex(32); // create random hex val for enc key -let hmac = randomValueHex(32); // create random hex val for hmac key -let randFold = "./" + randomValueHex(32) + "/"; // create random hex val with filesys encoding for folder -let randFile = randomValueHex(32) + ".json"; // create random hex val with .json ending for file -let resSysop = randFold + randFile; // merge foldername and filename + const enduserconfig = { + key: fetchedKey || randomValueHex(32), // create random hex val for enc key + hmac_key: fetchedHMAC || randomValueHex(32) // create random hex val for hmac key + }; -fs.mkdirSync(randFold); // create folder -fs.appendFileSync(resSysop, "{\n \"key\": \"" + key + "\",\n \"hmac_key\": \"" + hmac + "\"\n}\n"); // create file with keys necessary -fs.appendFileSync("./config.js", "\'use strict\';\n\nvar k = require(\"" + resSysop + "\");\n\nmodule.exports = {\n k\n};\n\n"); // generate config file with necessary info + fs.appendFileSync(`${projectRoot}/.basic256rc.js`, `"use strict"; + +module.exports = ${JSON.stringify(enduserconfig, null, 4)} +`); // generate config file with necessary info + + if (convertedConfig) return exit("\nYour old configuration is saved to a file named .basic256rc.js has been created on the project root.\nDON'T FORGET TO BACK THIS UP.\n"); + return exit("\nA file named .basic256rc.js has been created on the project root. DON'T FORGET TO BACK THIS UP.\n"); +}; -setTimeout(function(){process.exit(0);}, 2000); // exit script +main(); diff --git a/LICENSE b/LICENSE index 2ccfd4d..3d847b3 100644 --- a/LICENSE +++ b/LICENSE @@ -176,7 +176,7 @@ END OF TERMS AND CONDITIONS Copyright 2014 Levi Gross - Copyright 2016 linuxgemini. All Rights Reserved. + Copyright 2018 linuxgemini. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index 5b4969c..ab9dc0e 100644 --- a/README.md +++ b/README.md @@ -1,55 +1,45 @@ basic256.js ========================= +WARNING +------- + +**THIS PACKAGE SAVES IMPORTANT KEYS ON YOUR PROJECT, DON'T LOSE IT.** + [![Build Status](https://travis-ci.org/linuxgemini/basic256.js.svg?branch=master)](https://travis-ci.org/linuxgemini/basic256.js) A basic encryption/decryption script/API for resting data for Node.js users. *Slightly* modified the work of [Levi Gross](http://www.levigross.com/2014/03/30/how-to-write-an-encrypt-and-decrypt-api-for-data-at-rest-in-nodejs/). -Usage with downloading from NPM +Usage ----- Open a terminal in your project folder and make sure that you have a package.json file. And do this on your terminal if you are not root: - npm install --save basic256.js +` +$ npm install --save basic256.js +` If you are running as root, do this: - npm install --unsafe-perm --save basic256.js +` +$ npm install --unsafe-perm --save basic256.js +` Then make your script connected. Example: - var crypter = require("basic256.js"); - - var blob = crypter.encrypt("FOO").catch(console.error); // This encrypts the string "FOO". - console.log(blob); // This will show the encrypted string. - - var unblob = crypter.decrypt(blob).catch(console.error); // This decrypts the encrypted string. - console.log(unblob); // This will show the decrypted string. (Which in this case, it is "FOO") - - -Usage without downloading from NPM ------ - -Gather basic256.js first, copy all files inside to your project folder/direcory. +```js +const b256 = require("basic256.js"); +const basic256 = new b256(); -And do this on your terminal if you are not root: - - npm install - -If you are running as root, do this: - - npm install --unsafe-perm +var blob = basic256.encrypt("FOO"); // This encrypts the string "FOO". +console.log(blob); // This will show the encrypted string. -Then make your script connected. Example: +var unblob = basic256.decrypt(blob); // This decrypts the encrypted string. +console.log(unblob); // This will show the decrypted string. (Which in this case, it is "FOO") +``` - var crypter = require("./basic256.js"); - - var blob = crypter.encrypt("FOO").catch(console.error); // This encrypts the string "FOO". - console.log(blob); // This will show the encrypted string. - - var unblob = crypter.decrypt(blob).catch(console.error); // This decrypts the encrypted string. - console.log(unblob); // This will show the decrypted string. (Which in this case, it is "FOO") +**Don't forget to back your .basic256rc.js file as it contains your keys to encrypt and decrypt strings.** diff --git a/basic256.js b/basic256.js index ebc950c..af52860 100644 --- a/basic256.js +++ b/basic256.js @@ -1,84 +1,93 @@ -'use strict'; - -let crypto = require('crypto'); - -try { - var savedKeys = require("./config.js").k; -} catch (e) { - return Promise.reject('No Configuration Exists!'); -} - -var ALGORITHM, KEY, HMAC_ALGORITHM, HMAC_KEY; - -ALGORITHM = 'AES-256-CBC'; // CBC because CTR isn't possible with the current version of the Node.JS crypto library -HMAC_ALGORITHM = 'SHA256'; -KEY = savedKeys.key; // Use the automated script. -HMAC_KEY = savedKeys.hmac_key; // Use the automated script. - -function randomValueHex (len) { - return crypto.randomBytes(Math.ceil(len/2)) - .toString('hex') // convert to hexadecimal format - .slice(0,len); // return required number of characters -}; - -var constant_time_compare = function (val1, val2) { - var sentinel; - - if (val1.length !== val2.length) { - return false; - } - +"use strict"; + +let crypto = require("crypto"); +let projectRoot = require("path").dirname(require.main.filename); + +/** + * A basic encryption/decryption script/API for resting data for Node.js users. + * @class + */ +class basic256 { + constructor() { + try { + var savedKeys = require(`${projectRoot}/.basic256rc.js`); + } catch (e) { + throw new Error("An error happened while loading the key"); + } - for (var i = 0; i <= (val1.length - 1); i++) { - sentinel |= val1.charCodeAt(i) ^ val2.charCodeAt(i); + this.ALGORITHM = "AES-256-CBC"; + this.HMAC_ALGORITHM = "SHA256"; + this.KEY = savedKeys.key; // Use the automated script. + this.HMAC_KEY = savedKeys.hmac_key; // Use the automated script. } - return sentinel === 0 -}; - -module.exports = { - - "encrypt": function (plain_text) { - if (!plain_text || typeof(plain_text) !== "string") return Promise.reject("Plain text was not found."); + encrypt(plain_text) { + if (!plain_text || typeof (plain_text) !== "string") throw new Error("Plain text was not found."); - var IV = Buffer.from(randomValueHex(16)); // ensure that the IV (initialization vector) is random + var IV = Buffer.from(tools.randomValueHex(16)); // ensure that the IV (initialization vector) is random var encryptor, cipher_text, hmac; - encryptor = crypto.createCipheriv(ALGORITHM, KEY, IV); - encryptor.setEncoding('hex'); + encryptor = crypto.createCipheriv(this.ALGORITHM, this.KEY, IV); + encryptor.setEncoding("hex"); encryptor.write(plain_text); encryptor.end(); cipher_text = encryptor.read(); - hmac = crypto.createHmac(HMAC_ALGORITHM, HMAC_KEY); + hmac = crypto.createHmac(this.HMAC_ALGORITHM, this.HMAC_KEY); hmac.update(cipher_text); - hmac.update(IV.toString('hex')); // ensure that both the IV and the cipher-text is protected by the HMAC + hmac.update(IV.toString("hex")); // ensure that both the IV and the cipher-text is protected by the HMAC // The IV isn't a secret so it can be stored along side everything else - return cipher_text + "$" + IV.toString('hex') + "$" + hmac.digest('hex') - }, + return cipher_text + "$" + IV.toString("hex") + "$" + hmac.digest("hex"); + } - "decrypt": function (cipher_text) { - if (!cipher_text || typeof(cipher_text) !== "string" || !cipher_text.match(/\$/g)) return Promise.reject("A valid cipher text was not found."); + decrypt(cipher_text) { + if (!cipher_text || typeof (cipher_text) !== "string" || !cipher_text.match(/\$/g)) throw new Error("A valid cipher text was not found."); var cipher_blob = cipher_text.split("$"); + + if (cipher_blob.length !== 3) throw new Error("Cipher text is broken."); + var ct = cipher_blob[0]; - var IV = Buffer.from(cipher_blob[1], 'hex'); + var IV = Buffer.from(cipher_blob[1], "hex"); var hmac = cipher_blob[2]; var chmac, decryptor; - chmac = crypto.createHmac(HMAC_ALGORITHM, HMAC_KEY); + chmac = crypto.createHmac(this.HMAC_ALGORITHM, this.HMAC_KEY); chmac.update(ct); - chmac.update(IV.toString('hex')); + chmac.update(IV.toString("hex")); - if (!constant_time_compare(chmac.digest('hex'), hmac)) { - return Promise.reject("Encrypted Blob has been tampered with."); + if (!tools.constant_time_compare(chmac.digest("hex"), hmac)) { + throw new Error("Encrypted Blob has been tampered with."); } - decryptor = crypto.createDecipheriv(ALGORITHM, KEY, IV); - var decryptedText = decryptor.update(ct, 'hex', 'utf-8'); - return decryptedText + decryptor.final('utf-8'); + decryptor = crypto.createDecipheriv(this.ALGORITHM, this.KEY, IV); + var decryptedText = decryptor.update(ct, "hex", "utf-8"); + return decryptedText + decryptor.final("utf-8"); } } + +class tools { + static constant_time_compare(val1, val2) { + var sentinel; + + if (val1.length !== val2.length) { + return false; + } + + for (var i = 0; i <= (val1.length - 1); i++) { + sentinel |= val1.charCodeAt(i) ^ val2.charCodeAt(i); + } + + return sentinel === 0; + } + static randomValueHex(len) { + return crypto.randomBytes(Math.ceil(len / 2)) + .toString("hex") // convert to hexadecimal format + .slice(0, len); // return required number of characters + } +} + +module.exports = basic256; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..6692f90 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,13 @@ +{ + "name": "basic256.js", + "version": "1.2.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=" + } + } +} diff --git a/package.json b/package.json index 1e66674..f14886f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "basic256.js", - "version": "1.0.1", + "version": "1.2.0", "description": "A basic encryption/decryption script/API for resting data for Node.js users.", "readme": "README.md", "maintainers": [ @@ -16,5 +16,8 @@ "install": "node DontRunMe.js", "test": "node test.js" }, + "dependencies": { + "detect-newline": "^2.1.0" + }, "main": "./basic256" } diff --git a/test.js b/test.js index 362b381..2e3ea07 100644 --- a/test.js +++ b/test.js @@ -1,17 +1,54 @@ -'use strict'; - -var m = require("./basic256"); - -console.log("Encrypting string \"foo\"..."); -var encStr = m.encrypt("foo"); -console.log("\nDecrypting the string below...\n" + encStr); -var decStr = m.decrypt(encStr); -console.log("\nResult: " + decStr); - -if (decStr === "foo") { - console.log("\nSUCCESS!"); - setTimeout(() => {process.exit(0);},853); -} else { - console.error("\nFAILURE!"); - setTimeout(() => {process.exit(1);},853); +"use strict"; + +try { + var base = require("./basic256"); +} catch (error) { + setTimeout(() => { + console.error(`Huge error in library\n${error.stack}`); + process.exit(1); + }, 1000); +} + +const basic256 = new base(); + +const testText = "Lorem ipsum dolor sit amet."; +let errCount = 0; +let successCount = 0; + +var ciphertext, returningtext; + +try { + ciphertext = basic256.encrypt(testText); + returningtext = basic256.decrypt(ciphertext); + if (returningtext === testText) { + successCount++; + console.log("Initial example works."); + } +} catch (e) { + console.log("Initial example doesn't work."); + errCount++; } + +try { + ciphertext = basic256.encrypt(testText.split(" ")); // planned error. + errCount++; +} catch (er) { + console.log("String detection before encryption works."); + successCount++; +} + +try { + ciphertext = basic256.encrypt(testText); + returningtext = basic256.decrypt(ciphertext.slice(3)); // planned error. + errCount++; +} catch (err) { + console.log("Cipher text tampering detection works."); + successCount++; +} + +if (errCount === 0 && successCount === 3) { + setTimeout(() => { + console.log("Test passed."); + process.exit(0); + }, 2222); +} \ No newline at end of file From 2c8ac942f1c7d9cab29cd0b46c09456643843a54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lteri=C5=9F=20Ero=C4=9Flu?= Date: Sat, 3 Mar 2018 16:52:39 +0300 Subject: [PATCH 10/15] Updated readme again --- README.md | 4 ++-- package.json | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ab9dc0e..a39f157 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ basic256.js ========================= +[![Build Status](https://travis-ci.org/linuxgemini/basic256.js.svg?branch=master)](https://travis-ci.org/linuxgemini/basic256.js) + WARNING ------- **THIS PACKAGE SAVES IMPORTANT KEYS ON YOUR PROJECT, DON'T LOSE IT.** -[![Build Status](https://travis-ci.org/linuxgemini/basic256.js.svg?branch=master)](https://travis-ci.org/linuxgemini/basic256.js) - A basic encryption/decryption script/API for resting data for Node.js users. *Slightly* modified the work of [Levi Gross](http://www.levigross.com/2014/03/30/how-to-write-an-encrypt-and-decrypt-api-for-data-at-rest-in-nodejs/). diff --git a/package.json b/package.json index f14886f..0ea7f1d 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,9 @@ "name": "basic256.js", "version": "1.2.0", "description": "A basic encryption/decryption script/API for resting data for Node.js users.", + "engines": { + "node": ">=8.4.0" + }, "readme": "README.md", "maintainers": [ "linuxgemini (ilteris@asenkron.com.tr)" From d2ef8413e1942f4b2658106ef1d7886bb15b73b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lteri=C5=9F=20Ero=C4=9Flu?= Date: Sat, 3 Mar 2018 16:56:20 +0300 Subject: [PATCH 11/15] Added missing exit code --- test.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test.js b/test.js index 2e3ea07..d7622d6 100644 --- a/test.js +++ b/test.js @@ -51,4 +51,9 @@ if (errCount === 0 && successCount === 3) { console.log("Test passed."); process.exit(0); }, 2222); +} else { + setTimeout(() => { + console.log("Test failed."); + process.exit(1); + }, 2222); } \ No newline at end of file From 243cd05f74e450f759798f5a1adafb912f9052d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lteri=C5=9F=20Ero=C4=9Flu?= Date: Sat, 3 Mar 2018 16:59:40 +0300 Subject: [PATCH 12/15] Update README.md --- README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/README.md b/README.md index a39f157..c8bd960 100644 --- a/README.md +++ b/README.md @@ -23,12 +23,6 @@ And do this on your terminal if you are not root: $ npm install --save basic256.js ` -If you are running as root, do this: - -` -$ npm install --unsafe-perm --save basic256.js -` - Then make your script connected. Example: ```js From 31e172c8bfe5782d8919b76220033b4141460f7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lteri=C5=9F=20Ero=C4=9Flu?= Date: Sat, 3 Mar 2018 17:46:53 +0300 Subject: [PATCH 13/15] Should fix #2 * Started using INIT_CWD env variable to get to the base folder. * CLRF --> LF --- DontRunMe.js | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DontRunMe.js b/DontRunMe.js index 89f3b9e..39a33ea 100644 --- a/DontRunMe.js +++ b/DontRunMe.js @@ -3,7 +3,7 @@ const detectNewline = require("detect-newline"); const crypto = require("crypto"); // define crypto const fs = require("fs"); // define filesys -let projectRoot = require("path").dirname(require.main.filename); +let projectRoot = process.env.INIT_CWD; let fetchedKey, fetchedHMAC, convertedConfig = false; const exit = (msg) => { diff --git a/package-lock.json b/package-lock.json index 6692f90..26253dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "basic256.js", - "version": "1.2.0", + "version": "1.2.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 0ea7f1d..327f7b5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "basic256.js", - "version": "1.2.0", + "version": "1.2.1", "description": "A basic encryption/decryption script/API for resting data for Node.js users.", "engines": { "node": ">=8.4.0" From 3bc79005ecb1afc446316aa5eb4eb162040fa6ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lteri=C5=9F=20Ero=C4=9Flu?= Date: Sat, 3 Mar 2018 18:07:49 +0300 Subject: [PATCH 14/15] Fixes #2 and any future linking issues --- DontRunMe.js | 2 +- basic256.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DontRunMe.js b/DontRunMe.js index 39a33ea..ef95ea7 100644 --- a/DontRunMe.js +++ b/DontRunMe.js @@ -3,7 +3,7 @@ const detectNewline = require("detect-newline"); const crypto = require("crypto"); // define crypto const fs = require("fs"); // define filesys -let projectRoot = process.env.INIT_CWD; +let projectRoot = require("path").dirname(require.main.children[0].filename).replace(/[\/\\]node_modules[\/\\].*/g, ""); // eslint-disable-line no-useless-escape let fetchedKey, fetchedHMAC, convertedConfig = false; const exit = (msg) => { diff --git a/basic256.js b/basic256.js index af52860..0a0f47b 100644 --- a/basic256.js +++ b/basic256.js @@ -1,7 +1,7 @@ "use strict"; let crypto = require("crypto"); -let projectRoot = require("path").dirname(require.main.filename); +let projectRoot = require("path").dirname(require.main.children[0].filename).replace(/[\/\\]node_modules[\/\\].*/g, ""); // eslint-disable-line no-useless-escape /** * A basic encryption/decryption script/API for resting data for Node.js users. From f4889b0b4ad2bf8920f44623256342f14fb19be5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lteri=C5=9F=20Ero=C4=9Flu?= Date: Sun, 4 Mar 2018 19:58:56 +0300 Subject: [PATCH 15/15] This should fix the issue where execution path is different than root. --- DontRunMe.js | 2 +- basic256.js | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DontRunMe.js b/DontRunMe.js index ef95ea7..40850dd 100644 --- a/DontRunMe.js +++ b/DontRunMe.js @@ -3,7 +3,7 @@ const detectNewline = require("detect-newline"); const crypto = require("crypto"); // define crypto const fs = require("fs"); // define filesys -let projectRoot = require("path").dirname(require.main.children[0].filename).replace(/[\/\\]node_modules[\/\\].*/g, ""); // eslint-disable-line no-useless-escape +let projectRoot = require("path").dirname(require.main.filename).replace(/[\/\\]node_modules[\/\\].*/g, ""); // eslint-disable-line no-useless-escape let fetchedKey, fetchedHMAC, convertedConfig = false; const exit = (msg) => { diff --git a/basic256.js b/basic256.js index 0a0f47b..b27b4f0 100644 --- a/basic256.js +++ b/basic256.js @@ -1,7 +1,7 @@ "use strict"; let crypto = require("crypto"); -let projectRoot = require("path").dirname(require.main.children[0].filename).replace(/[\/\\]node_modules[\/\\].*/g, ""); // eslint-disable-line no-useless-escape +let projectRoot = require("path").dirname(require.main.filename).replace(/[\/\\]node_modules[\/\\].*/g, ""); // eslint-disable-line no-useless-escape /** * A basic encryption/decryption script/API for resting data for Node.js users. diff --git a/package.json b/package.json index 327f7b5..865a697 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "basic256.js", - "version": "1.2.1", + "version": "1.2.3", "description": "A basic encryption/decryption script/API for resting data for Node.js users.", "engines": { "node": ">=8.4.0"