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,
|
prefer_hash_algorithm: enums.hash.sha256,
|
||||||
encryption_cipher: enums.symmetric.aes256,
|
encryption_cipher: enums.symmetric.aes256,
|
||||||
compression: enums.compression.zip,
|
compression: enums.compression.zip,
|
||||||
|
integrity_protect: true,
|
||||||
|
rsa_blinding: true,
|
||||||
|
|
||||||
show_version: true,
|
show_version: true,
|
||||||
show_comment: true,
|
show_comment: true,
|
||||||
integrity_protect: true,
|
|
||||||
keyserver: "keyserver.linux.it", // "pgp.mit.edu:11371"
|
|
||||||
|
|
||||||
versionstring: "OpenPGP.js VERSION",
|
versionstring: "OpenPGP.js VERSION",
|
||||||
commentstring: "http://openpgpjs.org",
|
commentstring: "http://openpgpjs.org",
|
||||||
|
|
||||||
|
keyserver: "keyserver.linux.it", // "pgp.mit.edu:11371"
|
||||||
node_store: './openpgp.store',
|
node_store: './openpgp.store',
|
||||||
|
|
||||||
debug: false
|
debug: false
|
||||||
|
|
|
@ -93,12 +93,15 @@ module.exports = {
|
||||||
case 'rsa_encrypt':
|
case 'rsa_encrypt':
|
||||||
var rsa = new publicKey.rsa();
|
var rsa = new publicKey.rsa();
|
||||||
// 0 and 1 are the public key.
|
// 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();
|
var d = keyIntegers[2].toBigInteger();
|
||||||
p = keyIntegers[3].toBigInteger();
|
p = keyIntegers[3].toBigInteger();
|
||||||
var q = keyIntegers[4].toBigInteger();
|
var q = keyIntegers[4].toBigInteger();
|
||||||
var u = keyIntegers[5].toBigInteger();
|
var u = keyIntegers[5].toBigInteger();
|
||||||
var m = dataIntegers[0].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':
|
case 'elgamal':
|
||||||
var elgamal = new publicKey.elgamal();
|
var elgamal = new publicKey.elgamal();
|
||||||
var x = keyIntegers[3].toBigInteger();
|
var x = keyIntegers[3].toBigInteger();
|
||||||
|
|
|
@ -293,7 +293,7 @@ function bnCompareTo(a) {
|
||||||
if (r != 0) return r;
|
if (r != 0) return r;
|
||||||
var i = this.t;
|
var i = this.t;
|
||||||
r = i - a.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;
|
while (--i >= 0) if ((r = this[i] - a[i]) != 0) return r;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,8 @@
|
||||||
|
|
||||||
var BigInteger = require('./jsbn.js'),
|
var BigInteger = require('./jsbn.js'),
|
||||||
util = require('../../util.js'),
|
util = require('../../util.js'),
|
||||||
random = require('../random.js');
|
random = require('../random.js'),
|
||||||
|
config = require('../../config');
|
||||||
|
|
||||||
function SecureRandom() {
|
function SecureRandom() {
|
||||||
function nextBytes(byteArray) {
|
function nextBytes(byteArray) {
|
||||||
|
@ -37,11 +38,33 @@ function SecureRandom() {
|
||||||
this.nextBytes = nextBytes;
|
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() {
|
function RSA() {
|
||||||
/**
|
/**
|
||||||
* This function uses jsbn Big Num library to decrypt RSA
|
* This function uses jsbn Big Num library to decrypt RSA
|
||||||
* @param m
|
* @param m
|
||||||
* message
|
* message
|
||||||
|
* @param n
|
||||||
|
* RSA public modulus n as BigInteger
|
||||||
|
* @param e
|
||||||
|
* RSA public exponent as BigInteger
|
||||||
* @param d
|
* @param d
|
||||||
* RSA d as BigInteger
|
* RSA d as BigInteger
|
||||||
* @param p
|
* @param p
|
||||||
|
@ -52,7 +75,10 @@ function RSA() {
|
||||||
* RSA u as BigInteger
|
* RSA u as BigInteger
|
||||||
* @return {BigInteger} The decrypted value of the message
|
* @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 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);
|
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()));
|
util.print_debug("rsa.js decrypt\nxpn:" + util.hexstrdump(xp.toMPI()) + "\nxqn:" + util.hexstrdump(xq.toMPI()));
|
||||||
|
@ -65,7 +91,11 @@ function RSA() {
|
||||||
} else {
|
} else {
|
||||||
t = t.multiply(u).mod(q);
|
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
|
* @return {BigInteger} Resulting big integer
|
||||||
*/
|
*/
|
||||||
getRandomBigInteger: function(bits) {
|
getRandomBigInteger: function(bits) {
|
||||||
if (bits < 0) {
|
if (bits < 1) {
|
||||||
return null;
|
throw new Error('Illegal parameter value: bits < 1');
|
||||||
}
|
}
|
||||||
var numBytes = Math.floor((bits + 7) / 8);
|
var numBytes = Math.floor((bits + 7) / 8);
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ module.exports = {
|
||||||
|
|
||||||
getRandomBigIntegerInRange: function(min, max) {
|
getRandomBigIntegerInRange: function(min, max) {
|
||||||
if (max.compareTo(min) <= 0) {
|
if (max.compareTo(min) <= 0) {
|
||||||
return;
|
throw new Error('Illegal parameter value: max <= min');
|
||||||
}
|
}
|
||||||
|
|
||||||
var range = max.subtract(min);
|
var range = max.subtract(min);
|
||||||
|
|
|
@ -107,7 +107,10 @@ Message.prototype.decrypt = function(privateKey) {
|
||||||
if (symEncryptedPacketlist.length !== 0) {
|
if (symEncryptedPacketlist.length !== 0) {
|
||||||
var symEncryptedPacket = symEncryptedPacketlist[0];
|
var symEncryptedPacket = symEncryptedPacketlist[0];
|
||||||
symEncryptedPacket.decrypt(pkESKeyPacket.sessionKeyAlgorithm, pkESKeyPacket.sessionKey);
|
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);
|
expect(decrypted).to.equal(plaintext);
|
||||||
done();
|
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() {
|
describe("Message 3DES decryption", function() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user