OP-01-005 Side-channel leak in RSA decryption (High). Add config option for RSA blinding, default true. Update jsbn to 1.3. Remove decrypted packets after Message.decrypt().
This commit is contained in:
parent
e1fcc51d0e
commit
9f23c6a891
|
@ -35,14 +35,15 @@ module.exports = {
|
|||
prefer_hash_algorithm: enums.hash.sha256,
|
||||
encryption_cipher: enums.symmetric.aes256,
|
||||
compression: enums.compression.zip,
|
||||
integrity_protect: true,
|
||||
rsa_blinding: true,
|
||||
|
||||
show_version: true,
|
||||
show_comment: true,
|
||||
integrity_protect: true,
|
||||
keyserver: "keyserver.linux.it", // "pgp.mit.edu:11371"
|
||||
|
||||
versionstring: "OpenPGP.js VERSION",
|
||||
commentstring: "http://openpgpjs.org",
|
||||
|
||||
keyserver: "keyserver.linux.it", // "pgp.mit.edu:11371"
|
||||
node_store: './openpgp.store',
|
||||
|
||||
debug: false
|
||||
|
|
|
@ -93,12 +93,15 @@ module.exports = {
|
|||
case 'rsa_encrypt':
|
||||
var rsa = new publicKey.rsa();
|
||||
// 0 and 1 are the public key.
|
||||
var n = keyIntegers[0].toBigInteger();
|
||||
var e = keyIntegers[1].toBigInteger();
|
||||
// 2 to 5 are the private key.
|
||||
var d = keyIntegers[2].toBigInteger();
|
||||
p = keyIntegers[3].toBigInteger();
|
||||
var q = keyIntegers[4].toBigInteger();
|
||||
var u = keyIntegers[5].toBigInteger();
|
||||
var m = dataIntegers[0].toBigInteger();
|
||||
return rsa.decrypt(m, d, p, q, u);
|
||||
return rsa.decrypt(m, n, e, d, p, q, u);
|
||||
case 'elgamal':
|
||||
var elgamal = new publicKey.elgamal();
|
||||
var x = keyIntegers[3].toBigInteger();
|
||||
|
|
|
@ -293,7 +293,7 @@ function bnCompareTo(a) {
|
|||
if (r != 0) return r;
|
||||
var i = this.t;
|
||||
r = i - a.t;
|
||||
if (r != 0) return r;
|
||||
if (r != 0) return (this.s < 0) ? -r : r;
|
||||
while (--i >= 0) if ((r = this[i] - a[i]) != 0) return r;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
|
||||
var BigInteger = require('./jsbn.js'),
|
||||
util = require('../../util.js'),
|
||||
random = require('../random.js');
|
||||
random = require('../random.js'),
|
||||
config = require('../../config');
|
||||
|
||||
function SecureRandom() {
|
||||
function nextBytes(byteArray) {
|
||||
|
@ -37,11 +38,33 @@ function SecureRandom() {
|
|||
this.nextBytes = nextBytes;
|
||||
}
|
||||
|
||||
var blinder = BigInteger.ZERO;
|
||||
var unblinder = BigInteger.ZERO;
|
||||
var TWO = BigInteger.ONE.add(BigInteger.ONE);
|
||||
|
||||
function blind(m, n, e) {
|
||||
if (unblinder.bitLength() === n.bitLength()) {
|
||||
unblinder = unblinder.square().mod(n);
|
||||
} else {
|
||||
unblinder = random.getRandomBigIntegerInRange(TWO, n);
|
||||
}
|
||||
blinder = unblinder.modInverse(n).modPow(e, n);
|
||||
return m.multiply(blinder).mod(n);
|
||||
}
|
||||
|
||||
function unblind(t, n) {
|
||||
return t.multiply(unblinder).mod(n);
|
||||
}
|
||||
|
||||
function RSA() {
|
||||
/**
|
||||
* This function uses jsbn Big Num library to decrypt RSA
|
||||
* @param m
|
||||
* message
|
||||
* @param n
|
||||
* RSA public modulus n as BigInteger
|
||||
* @param e
|
||||
* RSA public exponent as BigInteger
|
||||
* @param d
|
||||
* RSA d as BigInteger
|
||||
* @param p
|
||||
|
@ -52,7 +75,10 @@ function RSA() {
|
|||
* RSA u as BigInteger
|
||||
* @return {BigInteger} The decrypted value of the message
|
||||
*/
|
||||
function decrypt(m, d, p, q, u) {
|
||||
function decrypt(m, n, e, d, p, q, u) {
|
||||
if (config.rsa_blinding) {
|
||||
m = blind(m, n, e);
|
||||
}
|
||||
var xp = m.mod(p).modPow(d.mod(p.subtract(BigInteger.ONE)), p);
|
||||
var xq = m.mod(q).modPow(d.mod(q.subtract(BigInteger.ONE)), q);
|
||||
util.print_debug("rsa.js decrypt\nxpn:" + util.hexstrdump(xp.toMPI()) + "\nxqn:" + util.hexstrdump(xq.toMPI()));
|
||||
|
@ -65,7 +91,11 @@ function RSA() {
|
|||
} else {
|
||||
t = t.multiply(u).mod(q);
|
||||
}
|
||||
return t.multiply(p).add(xp);
|
||||
t = t.multiply(p).add(xp);
|
||||
if (config.rsa_blinding) {
|
||||
t = unblind(t, n);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -94,8 +94,8 @@ module.exports = {
|
|||
* @return {BigInteger} Resulting big integer
|
||||
*/
|
||||
getRandomBigInteger: function(bits) {
|
||||
if (bits < 0) {
|
||||
return null;
|
||||
if (bits < 1) {
|
||||
throw new Error('Illegal parameter value: bits < 1');
|
||||
}
|
||||
var numBytes = Math.floor((bits + 7) / 8);
|
||||
|
||||
|
@ -114,7 +114,7 @@ module.exports = {
|
|||
|
||||
getRandomBigIntegerInRange: function(min, max) {
|
||||
if (max.compareTo(min) <= 0) {
|
||||
return;
|
||||
throw new Error('Illegal parameter value: max <= min');
|
||||
}
|
||||
|
||||
var range = max.subtract(min);
|
||||
|
|
|
@ -107,7 +107,10 @@ Message.prototype.decrypt = function(privateKey) {
|
|||
if (symEncryptedPacketlist.length !== 0) {
|
||||
var symEncryptedPacket = symEncryptedPacketlist[0];
|
||||
symEncryptedPacket.decrypt(pkESKeyPacket.sessionKeyAlgorithm, pkESKeyPacket.sessionKey);
|
||||
return new Message(symEncryptedPacket.packets);
|
||||
var resultMsg = new Message(symEncryptedPacket.packets);
|
||||
// remove packets after decryption
|
||||
symEncryptedPacket.packets = new packet.List();
|
||||
return resultMsg;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -257,6 +257,13 @@ describe('Basic', function() {
|
|||
expect(decrypted).to.equal(plaintext);
|
||||
done();
|
||||
});
|
||||
|
||||
it('Decrypt message 2x', function() {
|
||||
decrypted = openpgp.decryptMessage(privKey, message);
|
||||
var decrypted2 = openpgp.decryptMessage(privKey, message);
|
||||
expect(decrypted).to.equal(decrypted2);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("Message 3DES decryption", function() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user