pqp
Version:
NodeJS version of libPQP
191 lines (152 loc) • 5.86 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
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 _public_key = require('./public_key');
var _public_key2 = _interopRequireDefault(_public_key);
var _randomgen = require('../operations/randomgen');
var _randomgen2 = _interopRequireDefault(_randomgen);
var _arithmetic = require('../operations/arithmetic');
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 McEliece = function () {
function McEliece() {
_classCallCheck(this, McEliece);
this.randgen = new _randomgen2.default();
}
_createClass(McEliece, [{
key: 'set_private_key',
value: function set_private_key(priv_key) {
this.H_0 = priv_key.H_0;
this.H_1 = priv_key.H_1;
this.G = (0, _arithmetic.mul_poly)(priv_key.H_0, priv_key.H_1inv); // compute public key
this.block_length = priv_key.block_length;
this.block_error = priv_key.block_error;
this.block_weight = priv_key.block_weight;
}
}, {
key: 'get_public_key',
value: function get_public_key() {
var pub_key = new _public_key2.default();
pub_key.G = this.G;
pub_key.block_error = this.block_error;
return pub_key;
}
}, {
key: 'encrypt',
value: function encrypt(pub_key, m) {
// non-constant weight to achieve cipertext indistinguishability
var temp = (0, _arithmetic.mul_poly)(pub_key.G, m.clone());
var t = this.randgen.get_random_weight_vector(pub_key.block_length, pub_key.block_error + this.randgen.flip_coin());
var v = temp.add(t).mod(2);
t = this.randgen.get_random_weight_vector(pub_key.block_length, pub_key.block_error + this.randgen.flip_coin());
var u = m.add(t).mod(2);
return [u, v];
}
}, {
key: 'syndrome',
value: function syndrome(c_0, c_1) {
return (0, _arithmetic.mul_poly)(this.H_0, c_0).add((0, _arithmetic.mul_poly)(this.H_1, c_1)).mod(2);
}
}, {
key: 'decrypt',
value: function decrypt(c_0, c_1) {
var synd = this.syndrome(c_0, c_1);
// compute correlations with syndrome
var H0_ind = this.H_0.nonzero();
var H1_ind = this.H_1.nonzero();
var kBL = this.block_length;
var unsat_H0 = Float32Array.createZero(kBL);
H0_ind.forEach(function (i) {
for (var j = 0; j < synd.length; ++j) {
if (synd[j]) {
var idx = (j + kBL - i) % kBL;
unsat_H0[idx] += 1;
}
}
});
var unsat_H1 = Float32Array.createZero(kBL);
H1_ind.forEach(function (i) {
for (var j = 0; j < synd.length; ++j) {
if (synd[j]) {
var idx = (j + kBL - i) % kBL;
unsat_H1[idx] += 1;
}
}
});
var rounds = 10;
var delta = 5;
var threshold = 100;
var r = 0;
while (true) {
var max_unsat = Math.max(unsat_H0.max(), unsat_H1.max());
// if so, we are done decoding
if (max_unsat == 0) {
break;
}
// we have reach the upper bound on rounds
if (r >= rounds) {
throw new Error('Decryption error');
break;
}
r += 1;
// update threshold
if (max_unsat > delta) {
threshold = max_unsat - delta;
}
var round_unsat_H0 = unsat_H0.clone();
var round_unsat_H1 = unsat_H1.clone();
// first block sweep
var _loop = function _loop(i) {
if (round_unsat_H0[i] <= threshold) {
return 'continue';
}
H0_ind.forEach(function (j) {
var increase = synd[(i + j) % kBL] == 0;
H0_ind.forEach(function (k) {
var m = (i + j - k + kBL) % kBL;
if (increase) unsat_H0[m] += 1;else unsat_H0[m] += -1;
});
H1_ind.forEach(function (k) {
var m = (i + j - k + kBL) % kBL;
if (increase) unsat_H1[m] += 1;else unsat_H1[m] += -1;
});
synd[(i + j) % kBL] ^= 1;
});
c_0[i] ^= 1;
};
for (var i = 0; i < kBL; ++i) {
var _ret = _loop(i);
if (_ret === 'continue') continue;
}
// second block sweep
var _loop2 = function _loop2(i) {
if (round_unsat_H1[i] <= threshold) {
return 'continue';
}
H1_ind.forEach(function (j) {
var increase = synd[(i + j) % kBL] == 0;
H0_ind.forEach(function (k) {
var m = (i + j - k + kBL) % kBL;
if (increase) unsat_H0[m] += 1;else unsat_H0[m] += -1;
});
H1_ind.forEach(function (k) {
var m = (i + j - k + kBL) % kBL;
if (increase) unsat_H1[m] += 1;else unsat_H1[m] += -1;
});
synd[(i + j) % kBL] ^= 1;
});
c_1[i] ^= 1;
};
for (var i = 0; i < kBL; ++i) {
var _ret2 = _loop2(i);
if (_ret2 === 'continue') continue;
}
}
return c_0;
}
}]);
return McEliece;
}();
exports.default = McEliece;