UNPKG

pqp

Version:
248 lines (196 loc) 9.23 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _cryptoJs = require('crypto-js'); var _cryptoJs2 = _interopRequireDefault(_cryptoJs); var _keygen = require('./keygen'); var _keygen2 = _interopRequireDefault(_keygen); var _qcmdpc = require('./qcmdpc'); var _qcmdpc2 = _interopRequireDefault(_qcmdpc); var _randomgen = require('../operations/randomgen'); var _randomgen2 = _interopRequireDefault(_randomgen); var _keyio = require('../operations/keyio'); var _keyio2 = _interopRequireDefault(_keyio); var _conversion = require('../operations/conversion'); var _encBase = require('crypto-js/enc-base64'); var _encBase2 = _interopRequireDefault(_encBase); var _aesJs = require('aes-js'); var _aesJs2 = _interopRequireDefault(_aesJs); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Pkcs7 = _cryptoJs2.default.pad.Pkcs7; var AES = _cryptoJs2.default.AES; function Utf8ArrayToStr(array) { var out, i, len, c; var char2, char3; out = ""; len = array.length; i = 0; while (i < len) { c = array[i++]; switch (c >> 4) { case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7: // 0xxxxxxx out += String.fromCharCode(c); break; case 12:case 13: // 110x xxxx 10xx xxxx char2 = array[i++]; out += String.fromCharCode((c & 0x1F) << 6 | char2 & 0x3F); break; case 14: // 1110 xxxx 10xx xxxx 10xx xxxx char2 = array[i++]; char3 = array[i++]; out += String.fromCharCode((c & 0x0F) << 12 | (char2 & 0x3F) << 6 | (char3 & 0x3F) << 0); break; } } return out; } // WordArray function sliceWordArray(array, start, end) { return _cryptoJs2.default.enc.Hex.parse(array.toString(_cryptoJs2.default.enc.Hex).substr(start, end * 2)); } var Protocol = function () { function Protocol() { _classCallCheck(this, Protocol); // instantiate primitives this.asymmetric_cipher = new _qcmdpc2.default(); this.randgen = new _randomgen2.default(); this.io = new _keyio2.default(); // just some random salts this.saltA = 'this is just a salt'; this.saltB = 'this is another a salt'; this.ivSalt = 'third salt'; } _createClass(Protocol, [{ key: 'generate_keypair', value: function generate_keypair() { // instantiate keygenerator and set keypair var keygen = new _keygen2.default(); var _keygen$generate = keygen.generate(), _keygen$generate2 = _slicedToArray(_keygen$generate, 2), privateKey = _keygen$generate2[0], publicKey = _keygen$generate2[1]; this.priv_key = privateKey; this.pub_key = publicKey; this.asymmetric_cipher.set_private_key(this.priv_key); } }, { key: 'set_private_key', value: function set_private_key(key) { key = this.io.extract_der_priv_key(key); this.priv_key = key; this.asymmetric_cipher.set_private_key(key); } }, { key: 'set_public_key', value: function set_public_key(key) { key = this.io.extract_der_pub_key(key); this.pub_key = key; } }, { key: 'get_private_key', value: function get_private_key() { return this.io.get_der_priv_key(this.priv_key); } }, { key: 'get_public_key', value: function get_public_key() { return this.io.get_der_pub_key(this.pub_key); } }, { key: 'generate_mac', value: function generate_mac(message, token, key) { var word = message.appendWordArray(token).concat(key); return _cryptoJs2.default.SHA256(word); } }, { key: 'symmetric_cipher_enc', value: function symmetric_cipher_enc(message, mac, key, iv) { var array = message.appendWordArray(mac); var plain = _aesJs2.default.utils.hex.toBytes(array.toString(_cryptoJs2.default.enc.Hex)); plain = _aesJs2.default.padding.pkcs7.pad(plain); key = _aesJs2.default.utils.hex.toBytes(key.toString()); iv = _aesJs2.default.utils.hex.toBytes(iv.toString()); var aesCbc = new _aesJs2.default.ModeOfOperation.cbc(key, iv); var data = aesCbc.encrypt(plain); return Buffer.from(data); } }, { key: 'symmetric_cipher_dec', value: function symmetric_cipher_dec(ciphertext, key, iv) { var encryptedBytes = _aesJs2.default.utils.hex.toBytes(ciphertext.toString()); key = _aesJs2.default.utils.hex.toBytes(key.toString()); iv = _aesJs2.default.utils.hex.toBytes(iv.toString()); var aesCbc = new _aesJs2.default.ModeOfOperation.cbc(key, iv); var decrypted = aesCbc.decrypt(encryptedBytes); decrypted = _aesJs2.default.padding.pkcs7.strip(decrypted); var length = 32; var len = decrypted.length; var mac = new Buffer(decrypted.slice(len - length, len)).toString('hex'); var message = decrypted.slice(0, len - length); message = Utf8ArrayToStr(message); return [message, mac]; } }, { key: 'encrypt_message', value: function encrypt_message(message, recv_pub_key) { // generate random data var randomized = this.randgen.get_random_vector(this.pub_key.block_length); var token = randomized.pack(); // derive keys var keyA = _cryptoJs2.default.SHA256(this.append(token, this.saltA)); // just some conversion var keyB = _cryptoJs2.default.SHA256(this.append(token, this.saltB)); // derive iv var iv = _cryptoJs2.default.SHA512(this.append(token, this.ivSalt)); iv = sliceWordArray(iv, 0, 16); // generate mac var mac = this.generate_mac(message, token, keyB); var _asymmetric_cipher$en = this.asymmetric_cipher.encrypt(recv_pub_key, randomized), _asymmetric_cipher$en2 = _slicedToArray(_asymmetric_cipher$en, 2), c_0 = _asymmetric_cipher$en2[0], c_1 = _asymmetric_cipher$en2[1]; // generate ciphertext return this.io.get_der_ciphertext(c_0, c_1, this.symmetric_cipher_enc(message, mac, keyA, iv)); } }, { key: 'append', value: function append(digest, suffix) { var array = digest.clone(); return array.concat(suffix.toWordArray()); } }, { key: 'decrypt_message', value: function decrypt_message(ciphertext) { // extract ciphertext data from DER var _io$extract_der_ciphe = this.io.extract_der_ciphertext(ciphertext), _io$extract_der_ciphe2 = _slicedToArray(_io$extract_der_ciphe, 3), rc_0 = _io$extract_der_ciphe2[0], rc_1 = _io$extract_der_ciphe2[1], symmetric_stream = _io$extract_der_ciphe2[2]; // decrypt necessary data var decrypted_token = this.asymmetric_cipher.decrypt(rc_0, rc_1).pack(); // derive keys from data var decrypted_keyA = _cryptoJs2.default.SHA256(this.append(decrypted_token, this.saltA)); // just some conversion var decrypted_keyB = _cryptoJs2.default.SHA256(this.append(decrypted_token, this.saltB)); // derive iv var digest = _cryptoJs2.default.SHA512(this.append(decrypted_token, this.ivSalt)); var decrypted_iv = sliceWordArray(digest, 0, 16); // decrypt ciphertext and derive mac var stream = _cryptoJs2.default.lib.WordArray.create(new Uint8Array(symmetric_stream)); var _symmetric_cipher_dec = this.symmetric_cipher_dec(stream, decrypted_keyA, decrypted_iv), _symmetric_cipher_dec2 = _slicedToArray(_symmetric_cipher_dec, 2), decrypted_message = _symmetric_cipher_dec2[0], decrypted_mac = _symmetric_cipher_dec2[1]; var receiver_mac = this.generate_mac(decrypted_message, decrypted_token, decrypted_keyB); return [decrypted_message, receiver_mac.toString(_cryptoJs2.default.enc.Hex) == decrypted_mac]; } }]); return Protocol; }(); exports.default = Protocol;