node-ebics-client/lib/Key.js
2018-05-31 11:33:59 +03:00

80 lines
2.4 KiB
JavaScript

'use strict';
const crypto = require('crypto');
const BN = require('bn.js');
const NodeRSA = require("node-rsa");
const MGF1 = require('./MGF1');
module.exports = class Key {
constructor(encodedKey, passphrase = null) {
if (encodedKey instanceof NodeRSA) {
this.key = encodedKey
} else {
this.key = new NodeRSA(encodedKey);
}
};
publicDigest() {
const str = [this.e().replace(/^(0+)/g, ''), this.n().replace(/^(0+)/g, '')].map((x) => x.toLowerCase()).join(' ');
return crypto.createHash('sha256').update(str).digest('base64').trim();
};
publicEncrypt(buf) {
return crypto.publicEncrypt({ 'key': this.toPem(), padding: crypto.constants.RSA_PKCS1_PADDING }, buf);
}
n() {
return this.key.exportKey("components-public").n.toString("hex", 1);
};
e() {
return new BN(this.key.exportKey("components-public").e).toBuffer().toString('hex');
};
toPem() {
return this.key.isPrivate() ? this.key.exportKey("pkcs1-private-pem") : this.key.exportKey("pkcs8-public-pem");
}
sign(msg, salt = crypto.randomBytes(32)) {
const base = new BN(this._emsaPSS(msg, salt));
const power = new BN(this.key.keyPair.d.toBuffer());
const mod = new BN(this.key.keyPair.n.toBuffer());
return (this._modPow(base, power, mod)).toBuffer().toString('base64');
}
_emsaPSS(msg, salt) {
const eightNullBytes = Buffer.from("\x00".repeat(8));
const digestedMsg = crypto.createHash('sha256').update(msg).digest();
const mTickHash = crypto.createHash('sha256').update(Buffer.concat([eightNullBytes, digestedMsg, salt]), 'binary').digest();
const ps = Buffer.from("\x00".repeat(190));
const db = Buffer.concat([ps, Buffer.from("\x01"), salt]);
const dbMask = MGF1.generate(mTickHash, db.length);
const maskedDb = MGF1.xor(db, dbMask); // so far so good
let maskedDbMsb = (new MGF1)._rjust(new BN(maskedDb.slice(0, 1), 2).toString(2), 8, "0");
maskedDbMsb = "0" + maskedDbMsb.substr(1);
maskedDb[0] = (new BN(maskedDbMsb, 2).toBuffer())[0];
return Buffer.concat([maskedDb, mTickHash, Buffer.from('BC', 'hex')]);
}
_modPow(base, power, mod) {
let result = new BN(1);
while( power > 0 ) {
result = power.and(new BN(1)) == 1 ? (result.mul(base)).mod(mod) : result;
base = (base.mul(base)).mod(mod);
power = power.shrn(1);
}
return result;
}
};