/* globals window */
// var node_cryptojs = require("node-cryptojs-aes");
// var CryptoJS = node_cryptojs.CryptoJS;
//>> Error: Error: ENOENT, no such file or directory '$HOME/dative/.tmp/scripts/core.js'
// var forcingCoreToLoadForRequireJS = require("node-cryptojs-aes/lib/core");
// var CryptoEncoding = {};// require("crypto-js/enc-utf8");
var FieldDBObject = require("./../FieldDBObject").FieldDBObject;
var CryptoJS = require("./Crypto_AES").CryptoJS;
var CryptoEncoding = CryptoJS.enc.Utf8;
var ATOB;
var BTOA;
try {
if (!window.atob) {
console.log("ATOB is not defined, loading from npm");
}
ATOB = window.atob;
BTOA = window.btoa;
} catch (e) {
ATOB = require("atob");
BTOA = require("btoa");
}
/**
* @class Confidential
* @name Confidential
*
* @description makes it possible to generate pass phrases (one per
* corpus) to encrypt and decrypt confidential data points. The
* confidential data is stored encrypted, and can only be decrypted
* if one has the corpus" secret key, or if one is logged into the
* system with their user name and password. This allows the corpus
* to be shared with anyone, with out worrying about confidential
* data or consultant stories being publically accessible. We are
* using the AES cipher algorithm.
*
* The Advanced Encryption Standard (AES) is a U.S. Federal Information
* Processing Standard (FIPS). It was selected after a 5-year process where
* 15 competing designs were evaluated.
*
* <a href="http://code.google.com/p/crypto-js/">More information on
* CryptoJS</a>
*
* @extends Object
*
* @constructs
*
*/
var Confidential = function Confidential(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "Confidential";
}
this.debug("Constructing Confidential: ", options);
if (options && options.filledWithDefaults) {
this.fillWithDefaults();
delete options.filledWithDefaults;
}
FieldDBObject.apply(this, arguments);
};
/**
* The secretkeygenerator uses a "GUID" like generation to create a string
* for the secret key.
*
* @returns {String} a string which is likely unique, in the format of a
* Globally Unique ID (GUID)
*/
Confidential.secretKeyGenerator = FieldDBObject.uuidGenerator;
Confidential.prototype = Object.create(FieldDBObject.prototype, /** @lends Confidential.prototype */ {
constructor: {
value: Confidential
},
/**
* Encrypt accepts a string (UTF8) and returns a CryptoJS object, in base64
* encoding so that it looks like a string, and can be saved as a string in
* the corpus.
*
* @param message
* A UTF8 string
* @returns Returns a base64 string prefixed with "confidential" so that the
* views can choose to not display the entire string for the user.
*/
encrypt: {
value: function(value) {
if (!value) {
return value;
}
if (typeof value === "object") {
value = JSON.stringify(value);
this.debug("Converted object to string before encryption");
}
if (typeof value === "number") {
value = value + "";
this.debug("Converted object to string before encryption");
}
if (!this.secretkey) {
throw new Error("This confidential wasnt set up properly, cant encrypt.");
}
// this.debugMode = true;
this.debug("encrypting " + value);
var result = CryptoJS.AES.encrypt(value, this.secretkey.toString("base64"));
this.verbose(this.secretkey, result.toString(), BTOA(result.toString()));
// return the base64 version to save it as a string in the corpus
return "confidential:" + BTOA(result.toString());
}
},
/**
* Decrypt uses this object's secret key to decode its parameter using the
* AES algorithm.
*
* @param encrypted
* A base64 string prefixed (or not) with the word "confidential"
* @returns Returns the encrypted result as a UTF8 string.
*/
decrypt: {
value: function(encrypted) {
var result = encrypted;
encrypted = encrypted.replace("confidential:", "");
// decode base64
encrypted = ATOB(encrypted);
this.verbose("Decrypting " + encrypted, this.secretkey.toString("base64"));
result = CryptoJS.AES.decrypt(encrypted, this.secretkey.toString("base64")).toString(CryptoEncoding);
try {
if ((result[0] === "{" && result[result.length - 1] === "}") || (result[0] === "[" && result[result.length - 1] === "]")) {
result = JSON.parse(result);
this.debug("Decrypting an object");
}
} catch (e) {
this.verbose("Decrypting a non-object");
}
return result;
}
},
secretkey: {
get: function() {
if (!this._secretkey) {
this._secretkey = "";
}
return this._secretkey;
},
set: function(value) {
if (value === this._secretkey) {
return;
}
if (this._secretkey && this._secretkey.length > 2) {
throw new Error("Confidential key cant be changed once it was created. Please create another Confidential encrypter if you wish to change the key.");
}
if (!value) {
value = "";
}
this._secretkey = value.trim();
}
},
fillWithDefaults: {
value: function() {
if (!this.secretkey) {
this.secretkey = Confidential.secretKeyGenerator();
}
return this;
}
}
});
exports.Confidential = Confidential;