Major changes. Separating responsibilities. Orders builder, serializer.

This commit is contained in:
Vladislav Hristov
2018-06-11 11:38:32 +03:00
parent 90f51544b7
commit ff9a3a16b4
29 changed files with 986 additions and 1025 deletions

View File

@@ -0,0 +1,40 @@
'use strict';
const fs = require('fs');
/* const extractKeys = (keysObject, encryptAlgorithm, passphrase) => Object.entries(keysObject).reduce((keys, [key, data]) => {
keys[key] = decrypt(data, encryptAlgorithm, passphrase);
return keys;
}, {}); */
module.exports = class FsKeyStorage {
/**
* @param {String} path - destingiton file to save the keys
*/
constructor({ path }) {
if (!path)
throw new Error('Invalid path provided');
this._path = path;
}
get path() {
return this._path;
}
read() {
return fs.readFileSync(this._path, { encoding: 'utf8' });
// return extractKeys(JSON.parse(fs.readFileSync(this._path, { encoding: 'utf8' })), this.algorithm, this.passphrase);
}
save(data) {
fs.writeFileSync(this._path, data, { encoding: 'utf8' });
// fs.writeFileSync(this._path, encrypt(JSON.stringify(data), this.algorithm, this.passphrase), { encoding: 'utf8' });
}
hasData() {
if (fs.existsSync(this._path))
return this.read() !== '';
return false;
}
};

50
lib/keymanagers/Key.js Normal file
View File

@@ -0,0 +1,50 @@
'use strict';
const BN = require('bn.js');
const NodeRSA = require('node-rsa');
module.exports = class Key {
constructor(encodedKey/* , passphrase = null */) {
this._key = (encodedKey instanceof NodeRSA) ? encodedKey : new NodeRSA(encodedKey);
}
static generate(keysize = 2048) {
return new NodeRSA({ b: keysize });
}
static importKey({ mod, exp }) {
const key = new NodeRSA();
key.importKey({ n: mod, e: exp }, 'components-public');
return new Key(key);
}
get key() {
return this._key;
}
n(to = 'buff') {
const keyN = Buffer.from(this.key.exportKey('components-public').n);
return to === 'hex'
? keyN.toString('hex', 1)
: keyN;
}
e(to = 'buff') {
const eKey = new BN(this.key.exportKey('components-public').e).toBuffer();
return to === 'hex'
? eKey.toString('hex')
: eKey;
}
d() {
return this.key.keyPair.d.toBuffer();
}
toPem() {
return this.key.isPrivate() ? this.key.exportKey('pkcs1-private-pem') : this.key.exportKey('pkcs8-public-pem');
}
};

58
lib/keymanagers/Keys.js Normal file
View File

@@ -0,0 +1,58 @@
'use strict';
const Key = require('./Key');
const keyOrNull = key => (key ? new Key(key) : null);
module.exports = class Keys {
constructor({
A006,
E002,
X002,
bankX002,
bankE002,
}) {
this.keys = {
A006: keyOrNull(A006),
E002: keyOrNull(E002),
X002: keyOrNull(X002),
bankX002: keyOrNull(bankX002),
bankE002: keyOrNull(bankE002),
};
}
static generate() {
const keys = {};
Object.keys({ A006: '', X002: '', E002: '' }).forEach((key) => {
keys[key] = Key.generate();
});
return new Keys(keys);
}
setBankKeys(bankKeys) {
this.keys.bankX002 = Key.importKey(bankKeys.bankX002);
this.keys.bankE002 = Key.importKey(bankKeys.bankE002);
}
a() {
return this.keys.A006;
}
e() {
return this.keys.E002;
}
x() {
return this.keys.X002;
}
bankX() {
return this.keys.bankX002;
}
bankE() {
return this.keys.bankE002;
}
};

View File

@@ -0,0 +1,94 @@
'use strict';
const crypto = require('crypto');
const Keys = require('./Keys');
const encrypt = (data, algorithm, passphrase) => {
const cipher = crypto.createCipher(algorithm, passphrase);
const encrypted = cipher.update(data, 'utf8', 'hex') + cipher.final('hex');
return Buffer.from(encrypted).toString('base64');
};
const decrypt = (data, algorithm, passphrase) => {
data = (Buffer.from(data, 'base64')).toString();
const decipher = crypto.createDecipher(algorithm, passphrase);
const decrypted = decipher.update(data, 'hex', 'utf8') + decipher.final('utf8');
return decrypted;
};
module.exports = class KeysManager {
constructor(keysStorage, passphrase, algorithm = 'aes-256-cbc', createIfNone = true) {
this._storage = keysStorage;
this._passphrase = passphrase;
this._algorithm = algorithm;
if (createIfNone && !this._storage.hasData())
this.generate();
}
/**
* Generates the keys to work with. Then either
* saves them to the storage or returnes the keys generated
*
* @param {Boolean} save
* @default true
*
* @returns void | Keys object
*/
generate(save = true) {
const keys = Keys.generate();
if (save) this.write(keys);
return keys;
}
/**
* Writes the keys to the storage
*
* @param {Keys} keysObject
*
* @returns void
*/
write(keysObject) {
keysObject = keysObject.keys;
Object.keys(keysObject).map((key) => {
keysObject[key] = keysObject[key] === null ? null : keysObject[key].toPem();
return key;
});
this._storage.save(encrypt(JSON.stringify(keysObject), this._algorithm, this._passphrase));
}
setBankKeys(bankKeys) {
const keys = this.keys();
keys.setBankKeys(bankKeys);
this.write(keys);
}
/**
* Gets the keys
*
* @returns Keys object
*/
keys() {
return this._read();
}
/**
* Reads the keys from the storage
*
* @returns Keys object
*/
_read() {
const keysString = this._storage.read();
return new Keys(JSON.parse(decrypt(keysString, this._algorithm, this._passphrase)));
}
};