Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

node-sap-secure-store

Package Overview
Dependencies
Maintainers
2
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-sap-secure-store - npm Package Compare versions

Comparing version
0.1.0
to
0.1.1
+12
.travis.yml
language: node_js
install:
- npm install
node_js:
- 0.10
script:
- gulp build
after_script: "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js"
'use strict';
var fs = require('fs');
require('node-sap-promise');
/**
* Simple file system based store
* @param {string} filename
* @param {string} [encoding]
* @param {number} [fileMode]
* @constructor
*/
function FileStore(filename, encoding, fileMode) {
if (typeof filename !== 'string') {
throw new TypeError('Missing mandatory filename parameter');
}
this.filename = filename;
if (typeof encoding === 'number') {
fileMode = encoding;
encoding = undefined;
}
this.encoding = encoding || 'utf-8';
this.fileMode = fileMode || 420; // default file mode 644
}
module.exports = FileStore;
FileStore.prototype.read = function () {
return Promise.invoke(fs.readFile, this.filename, { encoding: this.encoding })
.then(function (content) {
return JSON.parse(content);
});
};
FileStore.prototype.write = function (store) {
var content;
try {
content = JSON.stringify(store, null, ' ');
return Promise.invoke(fs.writeFile, this.filename, content, { mode: this.fileMode });
}
catch (err) {
return Promise.reject(err);
}
};
+0
-0

@@ -0,0 +0,0 @@

+7
-7

@@ -8,6 +8,6 @@ ## Modules

<dl>
<dt><a href="#readSecureData">readSecureData(filename, [password])</a> ⇒ <code>Promise</code></dt>
<dt><a href="#readSecureData">readSecureData(store, [password])</a> ⇒ <code>Promise</code></dt>
<dd><p>Read encrypted, password protected configuration data</p>
</dd>
<dt><a href="#writeSecureData">writeSecureData(filename, data, [password], [customOptions])</a> ⇒ <code>Promise</code></dt>
<dt><a href="#writeSecureData">writeSecureData(store, data, [password], [customOptions])</a> ⇒ <code>Promise</code></dt>
<dd><p>Write encrypted, password protected configuration data</p>

@@ -29,3 +29,3 @@ </dd>

| options | <code>object</code> | Default encryption options |
| options.algorithm | <code>string</code> | Encryption algorithm (default "aes-256-cbc") |
| options.algorithm | <code>string</code> | Encryption algorithm (default 'aes-256-cbc') |
| options.keyLength | <code>number</code> | Key length in bytes (default 32) |

@@ -38,3 +38,3 @@ | options.ivLength | <code>number</code> | Initialization Vector length in bytes (default 16) |

<a name="readSecureData"></a>
## readSecureData(filename, [password]) ⇒ <code>Promise</code>
## readSecureData(store, [password]) ⇒ <code>Promise</code>
Read encrypted, password protected configuration data

@@ -48,7 +48,7 @@

| --- | --- | --- |
| filename | <code>string</code> | Encrypted configuration file |
| store | <code>string</code> &#124; <code>object</code> | Encrypted store or filename of the encrypted FileStore |
| [password] | <code>string</code> | Password |
<a name="writeSecureData"></a>
## writeSecureData(filename, data, [password], [customOptions]) ⇒ <code>Promise</code>
## writeSecureData(store, data, [password], [customOptions]) ⇒ <code>Promise</code>
Write encrypted, password protected configuration data

@@ -61,3 +61,3 @@

| --- | --- | --- |
| filename | <code>string</code> | Encrypted configuration file |
| store | <code>string</code> &#124; <code>Store</code> | Encrypted store or filename of the encrypted FileStore |
| data | <code>object</code> &#124; <code>string</code> &#124; <code>buffer</code> | Configuration data |

@@ -64,0 +64,0 @@ | [password] | <code>string</code> | Password |

#!/usr/bin/env node
var helper = require("./helper.js");
var secureStore = require("../index.js");
'use strict';
var helper = require('./helper.js');
var secureStore = require('../index.js');
var usage = "\nUsage: cryptjson [-p <password>] [-e <environment-variable>] filename | -h\n\nEncrypts a JSON configuration file ('cryptjson -h' displays this help).\n\n";
usage += " -p <password> specifies that file will be encrypted using password '<password>'\n";
usage += " -e <environment-variable> specifies that file will be encrypted using the password stored in the environment variable <environment-variable>\n";
usage += " filename path of the JSON file to encrypt\n\n";
usage += "If neither -p nor -e options are used, password is read from CRYPT_JSON_PWD environment variable.";
var usage = '\nUsage: cryptjson [-p <password>] [-e <environment-variable>] filename | -h\n\nEncrypts a JSON configuration file ("cryptjson -h" displays this help).\n\n';
usage += ' -p <password> specifies that file will be encrypted using password "<password>"\n';
usage += ' -e <environment-variable> specifies that file will be encrypted using the password stored in the environment variable "<environment-variable>"\n';
usage += ' filename path of the JSON file to encrypt\n\n';
usage += 'If neither -p nor -e options are used, password is read from CRYPT_JSON_PWD environment variable.';

@@ -19,9 +20,9 @@ function run() {

else {
console.log("Encrypting JSON file " + args.filename);
console.log('Encrypting JSON file ' + args.filename);
secureStore.cryptJSON(args.filename, args.password)
.then(function () {
console.log("File encrypted");
console.log('File encrypted');
})
.catch(function (err) {
console.error("Failed to encrypt file: " + err.message);
console.error('Failed to encrypt file: ' + err.message);
});

@@ -28,0 +29,0 @@ }

#!/usr/bin/env node
var helper = require("./helper.js");
var secureStore = require("../index.js");
'use strict';
var helper = require('./helper.js');
var secureStore = require('../index.js');
var usage = "\nUsage: decryptjson [-p <password>] [-e <environment-variable>] filename | -h\n\nDecrypts a JSON configuration file ('cryptjson -h' displays this help).\n\n";
usage += " -p <password> specifies that file will be decrypted using password '<password>'\n";
usage += " -e <environment-variable> specifies that file will be decrypted using the password stored in the environment variable <environment-variable>\n";
usage += " filename path of the JSON file to decrypt\n\n";
usage += "If neither -p nor -e options are used, password is read from CRYPT_JSON_PWD environment variable.";
var usage = '\nUsage: decryptjson [-p <password>] [-e <environment-variable>] filename | -h\n\nDecrypts a JSON configuration file ("decryptjson -h" displays this help).\n\n';
usage += ' -p <password> specifies that file will be decrypted using password "<password>"\n';
usage += ' -e <environment-variable> specifies that file will be decrypted using the password stored in the environment variable "<environment-variable>"\n';
usage += ' filename path of the JSON file to decrypt\n\n';
usage += 'If neither -p nor -e options are used, password is read from CRYPT_JSON_PWD environment variable.';

@@ -19,9 +20,9 @@ function run() {

else {
console.log("Decrypting JSON file " + args.filename);
console.log('Decrypting JSON file ' + args.filename);
secureStore.decryptJSON(args.filename, args.password, 2)
.then(function () {
console.log("File decrypted");
console.log('File decrypted');
})
.catch(function (err) {
console.error("Failed to decrypt file: " + err.message);
console.error('Failed to decrypt file: ' + err.message);
});

@@ -28,0 +29,0 @@ }

@@ -1,3 +0,4 @@

var path = require("path");
var util = require("util");
'use strict';
var path = require('path');
var util = require('util');

@@ -9,5 +10,5 @@ function CommandLineError(message) {

util.inherits(CommandLineError, Error);
CommandLineError.prototype.name = "CommandLineError";
CommandLineError.prototype.name = 'CommandLineError';
function parseCommandLine () {
function parseCommandLine() {
var k, n, args = {}, argv = process.argv;

@@ -17,14 +18,14 @@ n = argv.length;

switch (argv[k]) {
case "-h":
case '-h':
args.help = true;
break;
case "-p":
case '-p':
if (k >= n - 2) {
throw new CommandLineError("-p option requires an additional password argument");
throw new CommandLineError('-p option requires an additional password argument');
}
args.password = argv[++k];
break;
case "-e":
case '-e':
if (k >= n - 2) {
throw new CommandLineError("-e option requires an additional environment variable name argument");
throw new CommandLineError('-e option requires an additional environment variable name argument');
}

@@ -39,3 +40,3 @@ args.password = process.env[argv[++k]];

if (!args.filename && !args.help) {
throw new CommandLineError("Missing filename argument");
throw new CommandLineError('Missing filename argument');
}

@@ -51,2 +52,2 @@ if (!args.password) {

parseCommandLine: parseCommandLine
};
};
+53
-43

@@ -1,13 +0,14 @@

"use strict";
var fs = require("fs");
var crypto = require("crypto");
var util = require("util");
require("node-sap-promise");
'use strict';
var fs = require('fs');
var crypto = require('crypto');
var util = require('util');
require('node-sap-promise');
var FileStore = require('./lib/FileStore');
var pbkdf2 = crypto.pbkdf2;
var defaultOptions = {
algorithm: "aes-256-cbc",
algorithm: 'aes-256-cbc',
keyLength: 32,
ivLength: 16,
digest: "sha256",
digest: 'sha256',
iterationCount: 10000,

@@ -19,3 +20,3 @@ fileMode: 420 // default file mode 644

// In 0.10.x, digest option not supported (hard-coded to SHA1)
defaultOptions.digest = "sha1";
defaultOptions.digest = 'sha1';
pbkdf2 = function (password, salt, iterations, keylen, digest, callback) {

@@ -31,18 +32,18 @@ // digest no supported on 0.10.x

result.buffer = data;
result.type = "buffer";
result.type = 'buffer';
}
else {
switch (typeof data) {
case "object":
case 'object':
result.buffer = new Buffer(JSON.stringify(data));
result.type = "object";
result.type = 'object';
break;
case "string":
encoding = encoding || "utf-8";
case 'string':
encoding = encoding || 'utf-8';
result.buffer = new Buffer(data, encoding);
result.type = "string";
result.type = 'string';
result.encoding = encoding;
break;
default:
throw new TypeError("Unsupported data type");
throw new TypeError('Unsupported data type');
}

@@ -56,13 +57,13 @@ }

switch (type) {
case "buffer":
case 'buffer':
result = buffer;
break;
case "object":
case 'object':
result = JSON.parse(buffer.toString());
break;
case "string":
case 'string':
result = buffer.toString(encoding);
break;
default:
throw new TypeError("Unsupported data type");
throw new TypeError('Unsupported data type');
}

@@ -73,7 +74,7 @@ return result;

function checkStore(store) {
var props = [ "algorithm", "keyLength", "ivLength", "digest", "salt", "iterationCount", "type", "data" ];
var props = [ 'algorithm', 'keyLength', 'ivLength', 'digest', 'salt', 'iterationCount', 'type', 'data' ];
var k, n = props.length;
for (k = 0; k < n; ++k) {
if (!store[props[k]]) {
throw new TypeError("Invalid encrypted configuration, \"" + props[k] + "\" property is missing");
throw new TypeError('Invalid encrypted configuration, \'' + props[k] + '\' property is missing');
}

@@ -85,3 +86,3 @@ }

* Read encrypted, password protected configuration data
* @param {string} filename Encrypted configuration file
* @param {string|object} store Encrypted store or filename of the encrypted FileStore
* @param {string} [password] Password

@@ -91,11 +92,15 @@ * @returns {Promise} Promise eventually fulfilled with the configuration data

*/
function readSecureData(filename, password) {
var store = {};
password = password || "";
return Promise.invoke(fs.readFile, filename, { encoding: "utf-8" })
.then(function (content) {
store = JSON.parse(content);
checkStore(store);
function readSecureData(storeReader, password) {
var store;
if (typeof storeReader === 'string') {
storeReader = new FileStore(storeReader);
}
password = password || '';
return storeReader.read()
.then(function (storeObj) {
checkStore(storeObj);
store = storeObj;
var pwdBuffer = new Buffer(password);
var salt = new Buffer(store.salt, "base64");
var salt = new Buffer(store.salt, 'base64');
return Promise.invoke(pbkdf2, pwdBuffer, salt, store.iterationCount, store.keyLength + store.ivLength, store.digest);

@@ -107,3 +112,3 @@ })

var decipher = crypto.createDecipheriv(store.algorithm, key, iv);
var buffer = decipher.update(store.data, "base64");
var buffer = decipher.update(store.data, 'base64');
buffer = Buffer.concat([buffer, decipher.final() ]);

@@ -116,3 +121,3 @@ return decodeData(buffer, store.type, store.encoding);

* Write encrypted, password protected configuration data
* @param {string} filename Encrypted configuration file
* @param {string|Store} store Encrypted store or filename of the encrypted FileStore
* @param {object|string|buffer} data Configuration data

@@ -124,9 +129,12 @@ * @param {string} [password] Password

*/
function writeSecureData(filename, data, password, customOptions) {
function writeSecureData(storeWriter, data, password, customOptions) {
var options, pwdBuffer, salt;
if (typeof password === "object") {
if (typeof password === 'object') {
customOptions = password;
password = undefined;
}
password = password || "";
if (typeof storeWriter === 'string') {
storeWriter = new FileStore(storeWriter);
}
password = password || '';
try {

@@ -136,3 +144,3 @@ options = util._extend({}, module.exports.options);

pwdBuffer = new Buffer(password);
salt = crypto.randomBytes(options.keyLength + options.ivLength); // Salt entropy should match key + IV
salt = crypto.randomBytes(options.keyLength); // Salt entropy should match key
return Promise.invoke(pbkdf2, pwdBuffer, salt, options.iterationCount, options.keyLength + options.ivLength, options.digest)

@@ -144,4 +152,4 @@ .then(function (kiv) {

var encodedData = encodeData(data);
var cipherData = cipher.update(encodedData.buffer, "buffer", "base64");
cipherData += cipher.final("base64");
var cipherData = cipher.update(encodedData.buffer, 'buffer', 'base64');
cipherData += cipher.final('base64');
var store = {

@@ -152,3 +160,3 @@ algorithm: options.algorithm,

digest: options.digest,
salt: salt.toString("base64"),
salt: salt.toString('base64'),
iterationCount: options.iterationCount,

@@ -159,3 +167,3 @@ type: encodedData.type,

};
return Promise.invoke(fs.writeFile, filename, JSON.stringify(store, null, " "), { mode: options.fileMode });
return storeWriter.write(store);
});

@@ -176,3 +184,3 @@ }

function cryptJSON(filename, password, customOptions) {
return Promise.invoke(fs.readFile, filename, { encoding: "utf-8" })
return Promise.invoke(fs.readFile, filename, { encoding: 'utf-8' })
.then(function (content) {

@@ -201,3 +209,3 @@ var data = JSON.parse(content);

* @property {object} options Default encryption options
* @property {string} options.algorithm Encryption algorithm (default "aes-256-cbc")
* @property {string} options.algorithm Encryption algorithm (default 'aes-256-cbc')
* @property {number} options.keyLength Key length in bytes (default 32)

@@ -214,3 +222,5 @@ * @property {number} options.ivLength Initialization Vector length in bytes (default 16)

readSecureData: readSecureData,
writeSecureData: writeSecureData
writeSecureData: writeSecureData,
FileStore: FileStore
};

@@ -0,0 +0,0 @@ # License #

{
"name": "node-sap-secure-store",
"version": "0.1.0",
"version": "0.1.1",
"description": "Password protected encrypted configuration",
"repository": {
"type": "git",
"url": "https://github.com/SAP/BUILD.git"
"url": "https://github.com/sapbuild/node-sap-secure-store.git"
},
"maintainers": [
{
"name": "BUILD Team",
"email": "contact.build@sap.com"
}
],
"licenses": [
{
"type": "Apache License, Version 2.0",
"url": "https://github.com/SAP/BUILD/node-sap-secure-store/blob/master/LICENSE.md"
"url": "https://github.com/sapbuild/node-sap-secure-store/blob/master/LICENSE.md"
}

@@ -32,12 +26,13 @@ ],

"devDependencies": {
"chai": "^2.2.0",
"del": "^1.1.1",
"gulp": "^3.8.11",
"gulp-concat": "^2.5.2",
"gulp-eslint": "^0.9.0",
"gulp-istanbul": "^0.8.1",
"gulp-jsdoc-to-markdown": "^1.0.2",
"gulp-mocha": "^2.0.1",
"gulp-util": "^3.0.4"
"chai": "~2.2.0",
"coveralls": "^2.11.3",
"del": "~1.2.0",
"gulp": "~3.9.0",
"gulp-concat": "~2.6.0",
"gulp-eslint": "~0.15.0",
"gulp-istanbul": "~0.10.0",
"gulp-jsdoc-to-markdown": "~1.1.1",
"gulp-mocha": "~2.1.2",
"gulp-util": "~3.0.5"
}
}
}

@@ -0,1 +1,6 @@

[![Build](https://img.shields.io/travis/sapbuild/node-sap-secure-store.svg?style=flat-square)](http://travis-ci.org/sapbuild/node-sap-secure-store)
[![Version](https://img.shields.io/npm/v/node-sap-secure-store.svg?style=flat-square)](https://npmjs.org/package/node-sap-secure-store)
[![Dependency Status](https://david-dm.org/sapbuild/node-sap-secure-store.svg)](https://david-dm.org/sapbuild/node-sap-secure-store)
[![devDependency Status](https://david-dm.org/sapbuild/node-sap-secure-store/dev-status.svg)](https://david-dm.org/sapbuild/node-sap-secure-store#info=devDependencies)
[![Coverage](https://img.shields.io/coveralls/sapbuild/node-sap-secure-store/master.svg?style=flat-square)](https://coveralls.io/r/sapbuild/node-sap-secure-store?branch=master)
node-sap-secure-store

@@ -6,7 +11,2 @@ ====================

Further Information
======================
*node-sap-secure-store* is part of [BUILD](https://github.com/SAP/BUILD).
# Module use

@@ -13,0 +13,0 @@

{
"env": {
"node": true
},
"globals": {
"__Promise": true
},
"rules": {
"no-alert": 1,
"no-array-constructor": 1,
"no-bitwise": 0,
"no-caller": 1,
"no-catch-shadow": 1,
"no-comma-dangle": 1,
"no-cond-assign": 1,
"no-console": 0,
"no-constant-condition": 1,
"no-control-regex": 1,
"no-debugger": 1,
"no-delete-var": 1,
"no-div-regex": 0,
"no-dupe-keys": 1,
"no-else-return": 0,
"no-empty": 1,
"no-empty-class": 1,
"no-empty-label": 1,
"no-eq-null": 0,
"no-eval": 1,
"no-ex-assign": 1,
"no-extend-native": 1,
"no-extra-bind": 1,
"no-extra-boolean-cast": 1,
"no-extra-parens": 0,
"no-extra-semi": 1,
"no-extra-strict": 1,
"no-fallthrough": 1,
"no-floating-decimal": 0,
"no-func-assign": 1,
"no-implied-eval": 1,
"no-inline-comments": 0,
"no-inner-declarations": [1, "functions"],
"no-invalid-regexp": 1,
"no-irregular-whitespace": 0,
"no-iterator": 1,
"no-label-var": 1,
"no-labels": 1,
"no-lone-blocks": 1,
"no-lonely-if": 0,
"no-loop-func": 1,
"no-mixed-requires": [0, false],
"no-mixed-spaces-and-tabs": [0, false],
"no-multi-spaces": 1,
"no-multi-str": 1,
"no-multiple-empty-lines": [0, {"max": 1}],
"no-native-reassign": 1,
"no-negated-in-lhs": 1,
"no-nested-ternary": 0,
"no-new": 1,
"no-new-func": 1,
"no-new-object": 1,
"no-new-require": 0,
"no-new-wrappers": 1,
"no-obj-calls": 1,
"no-octal": 1,
"no-octal-escape": 1,
"no-path-concat": 0,
"no-plusplus": 0,
"no-process-env": 0,
"no-process-exit": 1,
"no-proto": 1,
"no-redeclare": 1,
"no-regex-spaces": 1,
"no-reserved-keys": 0,
"no-restricted-modules": 0,
"no-return-assign": 1,
"no-script-url": 1,
"no-self-compare": 0,
"no-sequences": 1,
"no-shadow": 1,
"no-shadow-restricted-names": 1,
"no-space-before-semi": 1,
"no-spaced-func": 1,
"no-sparse-arrays": 1,
"no-sync": 0,
"no-ternary": 0,
"no-trailing-spaces": 1,
"no-undef": 1,
"no-undef-init": 1,
"no-undefined": 0,
"no-underscore-dangle": 0,
"no-unreachable": 1,
"no-unused-expressions": 1,
"no-unused-vars": [1, {"vars": "all", "args": "after-used"}],
"no-use-before-define": 1,
"no-void": 0,
"no-warning-comments": [0, { "terms": ["todo", "fixme", "xxx"], "location": "start" }],
"no-with": 1,
"no-wrap-func": 1,
"block-scoped-var": 0,
"brace-style": [0, "1tbs"],
"camelcase": 0,
"comma-spacing": 1,
"comma-style": 0,
"complexity": [0, 11],
"consistent-return": 1,
"consistent-this": [0, "that"],
"curly": 0,
"default-case": 0,
"dot-notation": 1,
"eol-last": 1,
"eqeqeq": 1,
"func-names": 0,
"func-style": [0, "declaration"],
"global-strict": 0,
"guard-for-in": 0,
"handle-callback-err": 0,
"key-spacing": [1, { "beforeColon": false, "afterColon": true }],
"max-depth": [0, 4],
"max-len": [0, 80, 4],
"max-nested-callbacks": [0, 1],
"max-params": [0, 3],
"max-statements": [0, 10],
"new-cap": 1,
"new-parens": 1,
"one-var": 0,
"operator-assignment": [0, "always"],
"padded-blocks": 0,
"quote-props": 0,
"quotes": [1, "double"],
"radix": 0,
"semi": 1,
"sort-vars": 0,
"space-after-function-name": [0, "never"],
"space-after-keywords": [0, "always"],
"space-before-blocks": [0, "always"],
"space-in-brackets": [0, "never"],
"space-in-parens": [0, "never"],
"space-infix-ops": 1,
"space-return-throw-case": 1,
"space-unary-ops": [1, { "words": true, "nonwords": false }],
"spaced-line-comment": [0, "always"],
"strict": 1,
"use-isnan": 1,
"valid-jsdoc": 0,
"valid-typeof": 1,
"vars-on-top": 0,
"wrap-iife": 0,
"wrap-regex": 0,
"yoda": [1, "never"]
}
}
var exec = require("child_process").exec;
var gulp = require("gulp");
var helper = {
plugins: {},
getPlugin: function (name) {
var plugin = this.plugins[name];
if (!plugin) {
plugin = require(name);
this.plugins[name] = plugin;
}
return plugin;
}
};
var pkg = require("./package.json");
gulp.task("default", [ "build" ], function () {
});
gulp.task("clean", function (done) {
var del = helper.getPlugin("del");
del([ "coverage", "tmp" ], function (err) {
done(err);
});
});
gulp.task("build", [ "clean", "eslint", "coverage" ], function () {
});
gulp.task("dist", [ "build" ], function () {
});
gulp.task("doc", [ "mddoc" ], function () {
});
gulp.task("eslint", function () {
var eslint = helper.getPlugin("gulp-eslint");
return gulp.src(["index.js", "lib/**/*.js"])
.pipe(eslint())
.pipe(eslint.format())
.pipe(eslint.failOnError());
});
gulp.task("test", function () {
return gulp.src("test/**/*.spec.js", { read: false })
.pipe(helper.getPlugin("gulp-mocha")({ slow: 200 }));
});
gulp.task("coverage", [ "clean" ], function (done) {
var mocha = helper.getPlugin("gulp-mocha");
var istanbul = helper.getPlugin("gulp-istanbul");
gulp.src(["lib/**/*.js", "bin/**/*.js", "index.js"])
.pipe(istanbul()) // Covering files
.pipe(istanbul.hookRequire()) // Force `require` to return covered files
.on('finish', function () {
gulp.src("test/**/*.spec.js", { read: false })
.pipe(mocha({ slow: 200 }))
.pipe(istanbul.writeReports({})) // Creating the reports after tests ran
.on('end', done);
});
});
gulp.task("mddoc", [ "eslint" ], function () {
var gutil = helper.getPlugin("gulp-util");
var gulpJsdoc2md = helper.getPlugin("gulp-jsdoc-to-markdown");
var concat = helper.getPlugin("gulp-concat");
return gulp.src([ "index.js" ])
.pipe(concat("API.md"))
.pipe(gulpJsdoc2md())
.on("error", function (err) {
gutil.log("jsdoc2md failed:", err.message);
})
.pipe(gulp.dest(""));
});

Sorry, the diff of this file is not supported yet

{
"algorithm": "aes-256-cbc",
"keyLength": 32,
"ivLength": 16,
"digest": "sha1",
"iterationCount": 10000,
"type": "object",
"data": "dsDuUA+sDoPtMbsx3tSR/rctzZEuBtzhABuLnq+bdmK0AaSJgwQFLQsZj/BEi//J"
}
{
"algorithm": "aes-256-cbc",
"keyLength": 32,
"ivLength": 16,
"digest": "sha1",
"salt": "4wh54a912AMBT4yKfWJQCDEYmmR8ahx+GNcEWWwIva9xCT1woQsJQAkvJF0lMwvC",
"iterationCount": 10000,
"type": "buffer",
"data": "wtCAP4qXj0Dy1ypwxVHwKg=="
}
{
"algorithm": "aes-256-cbc",
"keyLength": 32,
"ivLength": 16,
"digest": "sha1",
"salt": "4wh54a912AMBT4yKfWJQCDEYmmR8ahx+GNcEWWwIva9xCT1woQsJQAkvJF0lMwvC",
"iterationCount": 10000,
"type": "number",
"data": "wtCAP4qXj0Dy1ypwxVHwKg=="
}
{
"algorithm": "aes-256-cbc",
"keyLength": 32,
"ivLength": 16,
"digest": "sha1",
"salt": "Vy7frmWVyca4geuyin1ZfNu1iz7AP6NommBIw47431dmXwlLFpxhRydttOcosaUd",
"iterationCount": 10000,
"type": "object",
"data": "dsDuUA+sDoPtMbsx3tSR/rctzZEuBtzhABuLnq+bdmK0AaSJgwQFLQsZj/BEi//J"
}
{
"algorithm": "aes-256-cbc",
"keyLength": 32,
"ivLength": 16,
"digest": "sha1",
"salt": "Jxhc3mUEhjERYFolK1uXgU71bfZJjP/WFs5G0EeEWY4OHG467mjEQzW12xT3AMgg",
"iterationCount": 10000,
"type": "string",
"encoding": "utf-8",
"data": "KFecIZP49mq/c9uV+0C7ZSbvDmiY6Y91NFbWVBXdm90="
}
var fs = require("fs");
var path = require("path");
var crypto = require("crypto");
require("node-sap-promise");
var expect = require("chai").expect;
var secureStore = require("../index.js");
var password = "Oops, no magic today!";
var objConfigFile = path.join(__dirname, "../tmp/object-config.json");
var strConfigFile = path.join(__dirname, "../tmp/string-config.json");
var bufferConfigFile = path.join(__dirname, "../tmp/buffer-config.json");
var jsonConfigFile = path.join(__dirname, "../tmp/json-config.json");
var jsonEncryptedConfigFile = path.join(__dirname, "../tmp/json-enc-config.json");
var binConfigFile = path.join(__dirname, "../tmp/bin-config.json");
var binEncryptedConfigFile = path.join(__dirname, "../tmp/bin-enc-config.json");
var objConfig = {
foo: "bar",
toto: {
a: 1,
b: 2
}
};
var strConfig = "A simple string-based config";
var bufferConfig = new Buffer([0, 1, 2, 3, 4, 5, 6, 7]);
var savedArgs = process.argv.slice();
process.env.CRYPT_JSON_PWD = password;
function testPassed(done) {
return function () {
done();
};
}
function testFailed(done) {
return function (err) {
done(err);
};
}
function preventOnFulfilled() {
throw new Error("Promise should not be fulfilled");
}
function checkTempDir() {
var tempPath = path.join(__dirname, "../tmp");
if (!fs.existsSync(tempPath)) {
fs.mkdirSync(tempPath);
}
}
function deleteConfigFiles() {
var files = [ objConfigFile, strConfigFile, bufferConfigFile, jsonConfigFile, jsonEncryptedConfigFile, binConfigFile, binEncryptedConfigFile ];
files.forEach(function (file) {
try {
fs.unlinkSync(file);
}
catch (err) {
// ignore errors
}
});
}
function mockRun(scriptFile, args, done) {
var error, binFile = require.resolve(scriptFile);
delete require.cache[binFile];
process.argv = savedArgs.slice(0, 2).concat(args);
console.log("Running " + scriptFile + " with arguments: ", process.argv);
try {
require(scriptFile);
}
catch (err) {
error = err;
}
process.argv = savedArgs;
if (error) {
done(error);
}
else {
Promise.delay(200).callback(done);
}
}
describe("node-sap-secure-conf", function () {
before(checkTempDir);
before(deleteConfigFiles);
after(deleteConfigFiles);
describe("readSecureData", function () {
it("should decrypt an object configuration", function (done) {
secureStore.readSecureData(path.join(__dirname, "data/object-config.json"), password)
.then(function (config) {
expect(config).to.be.an("object");
expect(config).to.deep.equal(objConfig);
})
.then(testPassed(done), testFailed(done));
});
it("should decrypt a string configuration", function (done) {
secureStore.readSecureData(path.join(__dirname, "data/string-config.json"), password)
.then(function (config) {
expect(config).to.be.a("string");
expect(config).to.equal(strConfig);
})
.then(testPassed(done), testFailed(done));
});
it("should decrypt a buffer configuration", function (done) {
secureStore.readSecureData(path.join(__dirname, "data/buffer-config.json"), password)
.then(function (config) {
var k;
expect(Buffer.isBuffer(config)).to.be.true;
expect(config.length).to.equal(8);
for (k = 0; k < 8; ++k) {
expect(config[k]).to.equal(k);
}
})
.then(testPassed(done), testFailed(done));
});
it("should fail on invalid data type", function (done) {
secureStore.readSecureData(path.join(__dirname, "data/invalid-config.json"), password)
.then(preventOnFulfilled, function (err) {
expect(err).to.be.an.instanceof(TypeError);
})
.then(testPassed(done), testFailed(done));
});
it("should fail for an invalid password", function (done) {
secureStore.readSecureData(path.join(__dirname, "data/object-config.json"), "bad password")
.then(preventOnFulfilled, function (err) {
expect(err).to.be.an.instanceof(Error);
})
.then(testPassed(done), testFailed(done));
});
it("should fail for an invalid input file", function (done) {
secureStore.readSecureData(path.join(__dirname, "data/bad-config.json"), password)
.then(preventOnFulfilled, function (err) {
expect(err).to.be.an.instanceof(TypeError);
})
.then(testPassed(done), testFailed(done));
});
});
describe("writeSecureData", function () {
it("should encrypt an object configuration", function (done) {
secureStore.writeSecureData(objConfigFile, objConfig, password)
.then(function () {
return secureStore.readSecureData(objConfigFile, password);
})
.then(function (config) {
expect(config).to.be.an("object");
expect(config).to.deep.equal(objConfig);
})
.then(testPassed(done), testFailed(done));
});
it("should encrypt a string configuration", function (done) {
secureStore.writeSecureData(strConfigFile, strConfig, password)
.then(function () {
return secureStore.readSecureData(strConfigFile, password);
})
.then(function (config) {
expect(config).to.be.a("string");
expect(config).to.equal(strConfig);
})
.then(testPassed(done), testFailed(done));
});
it("should encrypt a buffer configuration", function (done) {
secureStore.writeSecureData(bufferConfigFile, bufferConfig, password)
.then(function () {
return secureStore.readSecureData(bufferConfigFile, password);
})
.then(function (config) {
var k;
expect(Buffer.isBuffer(config)).to.be.true;
expect(config.length).to.equal(8);
for (k = 0; k < 8; ++k) {
expect(config[k]).to.equal(k);
}
})
.then(testPassed(done), testFailed(done));
});
it("should fail on other type of data", function (done) {
secureStore.writeSecureData(bufferConfigFile, 42, password)
.then(preventOnFulfilled, function (err) {
expect(err).to.be.an.instanceof(TypeError);
})
.then(testPassed(done), testFailed(done));
});
it("should fail if crypto.randomBytes fails", function (done) {
var randomBytes = crypto.randomBytes;
crypto.randomBytes = function () {
throw new Error("Entropy sources drained");
};
secureStore.writeSecureData(bufferConfigFile, objConfig, password)
.then(preventOnFulfilled, function (err) {
expect(err).to.be.an.instanceof(Error);
})
.then(testPassed(done), testFailed(done));
crypto.randomBytes = randomBytes;
});
it("should support a missing or empty password", function (done) {
secureStore.writeSecureData(objConfigFile, objConfig)
.then(function () {
return secureStore.readSecureData(objConfigFile)
})
.then(function (config) {
expect(config).to.be.an("object");
expect(config).to.deep.equal(objConfig);
})
.then(testPassed(done), testFailed(done));
});
it("should support custom options", function (done) {
secureStore.writeSecureData(objConfigFile, objConfig, password, { iterationCount: 1000 })
.then(function () {
return secureStore.readSecureData(objConfigFile, password)
})
.then(function (config) {
expect(config).to.be.an("object");
expect(config).to.deep.equal(objConfig);
})
.then(testPassed(done), testFailed(done));
});
it("should support custom options with an empty password", function (done) {
secureStore.writeSecureData(objConfigFile, objConfig, { iterationCount: 1000 })
.then(function () {
return secureStore.readSecureData(objConfigFile)
})
.then(function (config) {
expect(config).to.be.an("object");
expect(config).to.deep.equal(objConfig);
})
.then(testPassed(done), testFailed(done));
});
});
describe("cryptJSON", function () {
it("should encrypt a JSON configuration file", function (done) {
Promise.invoke(fs.writeFile, jsonConfigFile, JSON.stringify(objConfig))
.then(function () {
return secureStore.cryptJSON(jsonConfigFile, password);
})
.then(function () {
return secureStore.readSecureData(jsonConfigFile, password);
})
.then(function (config) {
expect(config).to.be.an("object");
expect(config).to.deep.equal(objConfig);
})
.then(testPassed(done), testFailed(done));
});
});
describe("decryptJSON", function () {
it("should decrypt a JSON configuration file", function (done) {
Promise.invoke(fs.writeFile, jsonEncryptedConfigFile, JSON.stringify(objConfig))
.then(function () {
return secureStore.cryptJSON(jsonEncryptedConfigFile, password);
})
.then(function () {
return secureStore.decryptJSON(jsonEncryptedConfigFile, password);
})
.then(function () {
return Promise.invoke(fs.readFile, jsonEncryptedConfigFile, { encoding: "utf-8" });
})
.then(function (content) {
var config = JSON.parse(content);
expect(config).to.be.an("object");
expect(config).to.deep.equal(objConfig);
})
.then(function () {
return secureStore.cryptJSON(jsonEncryptedConfigFile, password);
})
.then(function () {
return secureStore.decryptJSON(jsonEncryptedConfigFile, password, 2);
})
.then(function () {
return Promise.invoke(fs.readFile, jsonEncryptedConfigFile, { encoding: "utf-8" });
})
.then(function (content) {
var config = JSON.parse(content);
expect(config).to.be.an("object");
expect(config).to.deep.equal(objConfig);
expect(content.search(/\n|\r/)).to.not.equal(-1); // Check that optional indentLevel parameter yields a multi-line JSON output
})
.then(testPassed(done), testFailed(done));
});
});
describe("bin/cryptJSON", function () {
this.slow(600);
it("should require a filename argument", function (done) {
mockRun("../bin/cryptjson.js", [], done);
});
it("should require a password argument after -p option", function (done) {
mockRun("../bin/cryptjson.js", [ "-p", binConfigFile ], done);
});
it("should require an environment variable name argument after -e option", function (done) {
mockRun("../bin/cryptjson.js", [ "-e", binConfigFile ], done);
});
it("should fail on a missing file", function (done) {
mockRun("../bin/cryptjson.js", [ "NonExistingFile.json" ], done);
});
it("should display help", function (done) {
mockRun("../bin/cryptjson.js", [ "-h" ], done);
});
it("should encrypt a JSON configuration file with CRYPT_JSON_PWD environment variable as default password", function (done) {
Promise.invoke(fs.writeFile, binConfigFile, JSON.stringify(objConfig))
.then(function () {
var args = [ binConfigFile ];
return Promise.invoke(mockRun, "../bin/cryptjson.js", args);
})
.then(function () {
return secureStore.readSecureData(binConfigFile, password);
})
.then(function (config) {
expect(config).to.be.an("object");
expect(config).to.deep.equal(objConfig);
})
.then(testPassed(done), testFailed(done));
});
it("should encrypt a JSON configuration file with explicit password argument", function (done) {
Promise.invoke(fs.writeFile, binConfigFile, JSON.stringify(objConfig))
.then(function () {
var args = [ "-p", password, binConfigFile ];
return Promise.invoke(mockRun, "../bin/cryptjson.js", args);
})
.then(function () {
return secureStore.readSecureData(binConfigFile, password);
})
.then(function (config) {
expect(config).to.be.an("object");
expect(config).to.deep.equal(objConfig);
})
.then(testPassed(done), testFailed(done));
});
it("should encrypt a JSON configuration file reading password from a given environment variable", function (done) {
Promise.invoke(fs.writeFile, binConfigFile, JSON.stringify(objConfig))
.then(function () {
var args = [ "-e", "CRYPT_JSON_PWD", binConfigFile ];
return Promise.invoke(mockRun, "../bin/cryptjson.js", args);
})
.then(function () {
return secureStore.readSecureData(binConfigFile, password);
})
.then(function (config) {
expect(config).to.be.an("object");
expect(config).to.deep.equal(objConfig);
})
.then(testPassed(done), testFailed(done));
});
});
describe("bin/decryptJSON", function () {
this.slow(600);
it("should require a filename argument", function (done) {
mockRun("../bin/decryptjson.js", [], done);
});
it("should require a password argument after -p option", function (done) {
mockRun("../bin/decryptjson.js", [ "-p", binEncryptedConfigFile ], done);
});
it("should require an environment variable name argument after -e option", function (done) {
mockRun("../bin/decryptjson.js", [ "-e", binEncryptedConfigFile ], done);
});
it("should fail on a missing file", function (done) {
mockRun("../bin/decryptjson.js", [ "NonExistingFile.json" ], done);
});
it("should display help", function (done) {
mockRun("../bin/decryptjson.js", [ "-h" ], done);
});
it("should decrypt a JSON configuration file with CRYPT_JSON_PWD environment variable as default password", function (done) {
Promise.invoke(fs.writeFile, binEncryptedConfigFile, JSON.stringify(objConfig))
.then(function () {
return secureStore.cryptJSON(binEncryptedConfigFile, password);
})
.then(function () {
var args = [ binEncryptedConfigFile ];
return Promise.invoke(mockRun, "../bin/decryptjson.js", args);
})
.then(function () {
return Promise.invoke(fs.readFile, binEncryptedConfigFile, { encoding: "utf-8" });
})
.then(function (content) {
var config = JSON.parse(content);
expect(config).to.be.an("object");
expect(config).to.deep.equal(objConfig);
})
.then(testPassed(done), testFailed(done));
});
it("should decrypt a JSON configuration file with explicit password argument", function (done) {
Promise.invoke(fs.writeFile, binEncryptedConfigFile, JSON.stringify(objConfig))
.then(function () {
return secureStore.cryptJSON(binEncryptedConfigFile, password);
})
.then(function () {
var args = [ "-p", password, binEncryptedConfigFile ];
return Promise.invoke(mockRun, "../bin/decryptjson.js", args);
})
.then(function () {
return Promise.invoke(fs.readFile, binEncryptedConfigFile, { encoding: "utf-8" });
})
.then(function (content) {
var config = JSON.parse(content);
expect(config).to.be.an("object");
expect(config).to.deep.equal(objConfig);
})
.then(testPassed(done), testFailed(done));
});
it("should decrypt a JSON configuration file reading password from a given environment variable", function (done) {
Promise.invoke(fs.writeFile, binEncryptedConfigFile, JSON.stringify(objConfig))
.then(function () {
return secureStore.cryptJSON(binEncryptedConfigFile, password);
})
.then(function () {
var args = [ "-p", password, "-e", "CRYPT_JSON_PWD", binEncryptedConfigFile ];
return Promise.invoke(mockRun, "../bin/decryptjson.js", args);
})
.then(function () {
return Promise.invoke(fs.readFile, binEncryptedConfigFile, { encoding: "utf-8" });
})
.then(function (content) {
var config = JSON.parse(content);
expect(config).to.be.an("object");
expect(config).to.deep.equal(objConfig);
})
.then(testPassed(done), testFailed(done));
});
});
});