Add config.aead_protect_version option

This commit is contained in:
Daniel Huigens 2018-04-10 16:44:52 +02:00
parent d5d4c97228
commit 28dbbadcff
8 changed files with 56 additions and 20 deletions

View File

@ -51,6 +51,15 @@ export default {
* @property {Boolean} aead_protect
*/
aead_protect: false,
/**
* Use Authenticated Encryption with Additional Data (AEAD) protection for symmetric encryption.
* 0 means we implement a variant of {@link https://tools.ietf.org/html/draft-ford-openpgp-format-00|this IETF draft}.
* 4 means we implement {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04|RFC4880bis-04}.
* Only has an effect when aead_protect is set to true.
* @memberof module:config
* @property {Integer} aead_protect_version
*/
aead_protect_version: 0,
/**
* Default Authenticated Encryption with Additional Data (AEAD) encryption mode
* Only has an effect when aead_protect is set to true.

View File

@ -1261,7 +1261,7 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options) {
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.aes192);
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.cast5);
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.tripledes);
if (config.aead_protect === 'draft04') {
if (config.aead_protect && config.aead_protect_version === 4) {
signaturePacket.preferredAeadAlgorithms = [];
signaturePacket.preferredAeadAlgorithms.push(enums.aead.eax);
signaturePacket.preferredAeadAlgorithms.push(enums.aead.ocb);
@ -1281,7 +1281,7 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options) {
signaturePacket.features = [0];
signaturePacket.features[0] |= enums.features.modification_detection;
}
if (config.aead_protect === 'draft04') {
if (config.aead_protect && config.aead_protect_version === 4) {
signaturePacket.features || (signaturePacket.features = [0]);
signaturePacket.features[0] |= enums.features.aead;
signaturePacket.features[0] |= enums.features.v5_keys;

View File

@ -54,7 +54,7 @@ function PublicKey(date=new Date()) {
* Packet version
* @type {Integer}
*/
this.version = config.aead_protect === 'draft04' ? 5 : 4;
this.version = config.aead_protect && config.aead_protect_version === 4 ? 5 : 4;
/**
* Key creation date.
* @type {Date}

View File

@ -61,7 +61,7 @@ SymEncryptedAEADProtected.prototype.read = function (bytes) {
throw new Error('Invalid packet version.');
}
offset++;
if (config.aead_protect === 'draft04') {
if (config.aead_protect_version === 4) {
this.cipherAlgo = bytes[offset++];
this.aeadAlgo = bytes[offset++];
this.chunkSizeByte = bytes[offset++];
@ -79,7 +79,7 @@ SymEncryptedAEADProtected.prototype.read = function (bytes) {
* @returns {Uint8Array} The encrypted payload
*/
SymEncryptedAEADProtected.prototype.write = function () {
if (config.aead_protect === 'draft04') {
if (config.aead_protect_version === 4) {
return util.concatUint8Array([new Uint8Array([this.version, this.cipherAlgo, this.aeadAlgo, this.chunkSizeByte]), this.iv, this.encrypted]);
}
return util.concatUint8Array([new Uint8Array([this.version]), this.iv, this.encrypted]);
@ -94,7 +94,7 @@ SymEncryptedAEADProtected.prototype.write = function () {
*/
SymEncryptedAEADProtected.prototype.decrypt = async function (sessionKeyAlgorithm, key) {
const mode = crypto[enums.read(enums.aead, this.aeadAlgo)];
if (config.aead_protect === 'draft04') {
if (config.aead_protect_version === 4) {
const cipher = enums.read(enums.symmetric, this.cipherAlgo);
let data = this.encrypted.subarray(0, this.encrypted.length - mode.blockLength);
const authTag = this.encrypted.subarray(this.encrypted.length - mode.blockLength);
@ -132,11 +132,11 @@ SymEncryptedAEADProtected.prototype.decrypt = async function (sessionKeyAlgorith
* @async
*/
SymEncryptedAEADProtected.prototype.encrypt = async function (sessionKeyAlgorithm, key) {
this.aeadAlgo = config.aead_protect === 'draft04' ? enums.write(enums.aead, this.aeadAlgorithm) : enums.aead.gcm;
this.aeadAlgo = config.aead_protect_version === 4 ? enums.write(enums.aead, this.aeadAlgorithm) : enums.aead.gcm;
const mode = crypto[enums.read(enums.aead, this.aeadAlgo)];
this.iv = await crypto.random.getRandomBytes(mode.ivLength); // generate new random IV
let data = this.packets.write();
if (config.aead_protect === 'draft04') {
if (config.aead_protect_version === 4) {
this.cipherAlgo = enums.write(enums.symmetric, sessionKeyAlgorithm);
this.chunkSizeByte = config.aead_chunk_size_byte;
const chunkSize = 2 ** (this.chunkSizeByte + 6); // ((uint64_t)1 << (c + 6))

View File

@ -49,7 +49,7 @@ import util from '../util';
*/
function SymEncryptedSessionKey() {
this.tag = enums.packet.symEncryptedSessionKey;
this.version = config.aead_protect === 'draft04' ? 5 : 4;
this.version = config.aead_protect && config.aead_protect_version === 4 ? 5 : 4;
this.sessionKey = null;
this.sessionKeyEncryptionAlgorithm = null;
this.sessionKeyAlgorithm = 'aes256';

View File

@ -10,12 +10,16 @@ describe('Key', function() {
describe('V5', function() {
let aead_protectVal;
let aead_protect_versionVal;
beforeEach(function() {
aead_protectVal = openpgp.config.aead_protect;
openpgp.config.aead_protect = 'draft04';
aead_protect_versionVal = openpgp.config.aead_protect_version;
openpgp.config.aead_protect = true;
openpgp.config.aead_protect_version = 4;
});
afterEach(function() {
openpgp.config.aead_protect = aead_protectVal;
openpgp.config.aead_protect_version = aead_protect_versionVal;
});
tests();
@ -1220,7 +1224,7 @@ p92yZgB3r2+f6/GIe2+7
expect(key.subKeys[0].bindingSignatures[0].keyFlags[0] & keyFlags.encrypt_storage).to.equal(keyFlags.encrypt_storage);
const sym = openpgp.enums.symmetric;
expect(key.users[0].selfCertifications[0].preferredSymmetricAlgorithms).to.eql([sym.aes256, sym.aes128, sym.aes192, sym.cast5, sym.tripledes]);
if (openpgp.config.aead_protect === 'draft04') {
if (openpgp.config.aead_protect && openpgp.config.aead_protect_version === 4) {
const aead = openpgp.enums.aead;
expect(key.users[0].selfCertifications[0].preferredAeadAlgorithms).to.eql([aead.eax, aead.ocb]);
}
@ -1228,7 +1232,7 @@ p92yZgB3r2+f6/GIe2+7
expect(key.users[0].selfCertifications[0].preferredHashAlgorithms).to.eql([hash.sha256, hash.sha512, hash.sha1]);
const compr = openpgp.enums.compression;
expect(key.users[0].selfCertifications[0].preferredCompressionAlgorithms).to.eql([compr.zlib, compr.zip]);
expect(key.users[0].selfCertifications[0].features).to.eql(openpgp.config.aead_protect === 'draft04' ? [7] : [1]);
expect(key.users[0].selfCertifications[0].features).to.eql(openpgp.config.aead_protect && openpgp.config.aead_protect_version === 4 ? [7] : [1]);
};
const opt = {numBits: 512, userIds: 'test <a@b.com>', passphrase: 'hello'};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys

View File

@ -597,6 +597,7 @@ describe('OpenPGP.js public api tests', function() {
let zero_copyVal;
let use_nativeVal;
let aead_protectVal;
let aead_protect_versionVal;
beforeEach(function(done) {
publicKey = openpgp.key.readArmored(pub_key);
@ -620,6 +621,7 @@ describe('OpenPGP.js public api tests', function() {
zero_copyVal = openpgp.config.zero_copy;
use_nativeVal = openpgp.config.use_native;
aead_protectVal = openpgp.config.aead_protect;
aead_protect_versionVal = openpgp.config.aead_protect_version;
done();
});
@ -627,6 +629,7 @@ describe('OpenPGP.js public api tests', function() {
openpgp.config.zero_copy = zero_copyVal;
openpgp.config.use_native = use_nativeVal;
openpgp.config.aead_protect = aead_protectVal;
openpgp.config.aead_protect_version = aead_protect_versionVal;
});
it('Decrypting key with wrong passphrase rejected', async function () {
@ -671,7 +674,8 @@ describe('OpenPGP.js public api tests', function() {
if: true,
beforeEach: function() {
openpgp.config.use_native = false;
openpgp.config.aead_protect = 'draft04';
openpgp.config.aead_protect = true;
openpgp.config.aead_protect_version = 4;
}
});
@ -679,7 +683,8 @@ describe('OpenPGP.js public api tests', function() {
if: openpgp.util.getWebCryptoAll() || openpgp.util.getNodeCrypto(),
beforeEach: function() {
openpgp.config.use_native = true;
openpgp.config.aead_protect = 'draft04';
openpgp.config.aead_protect = true;
openpgp.config.aead_protect_version = 4;
}
});

View File

@ -144,7 +144,9 @@ describe("Packet", function() {
it('Sym. encrypted AEAD protected packet (draft04)', function() {
let aead_protectVal = openpgp.config.aead_protect;
openpgp.config.aead_protect = 'draft04';
let aead_protect_versionVal = openpgp.config.aead_protect_version;
openpgp.config.aead_protect = true;
openpgp.config.aead_protect_version = 4;
const key = new Uint8Array([1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2]);
const algo = 'aes256';
@ -166,6 +168,7 @@ describe("Packet", function() {
expect(msg2[0].packets[0].data).to.deep.equal(literal.data);
}).finally(function() {
openpgp.config.aead_protect = aead_protectVal;
openpgp.config.aead_protect_version = aead_protect_versionVal;
});
});
@ -181,8 +184,10 @@ describe("Packet", function() {
`.replace(/\s+/g, ''));
let aead_protectVal = openpgp.config.aead_protect;
let aead_protect_versionVal = openpgp.config.aead_protect_version;
let aead_chunk_size_byteVal = openpgp.config.aead_chunk_size_byte;
openpgp.config.aead_protect = 'draft04';
openpgp.config.aead_protect = true;
openpgp.config.aead_protect_version = 4;
openpgp.config.aead_chunk_size_byte = 14;
const iv = openpgp.util.hex_to_Uint8Array('b7 32 37 9f 73 c4 92 8d e2 5f ac fe 65 17 ec 10'.replace(/\s+/g, ''));
@ -212,6 +217,7 @@ describe("Packet", function() {
expect(msg2[0].packets[0].data).to.deep.equal(literal.data);
}).finally(function() {
openpgp.config.aead_protect = aead_protectVal;
openpgp.config.aead_protect_version = aead_protect_versionVal;
openpgp.config.aead_chunk_size_byte = aead_chunk_size_byteVal;
randomBytesStub.restore();
});
@ -417,7 +423,9 @@ describe("Packet", function() {
it('Sym. encrypted session key reading/writing (draft04)', async function() {
let aead_protectVal = openpgp.config.aead_protect;
openpgp.config.aead_protect = 'draft04';
let aead_protect_versionVal = openpgp.config.aead_protect_version;
openpgp.config.aead_protect = true;
openpgp.config.aead_protect_version = 4;
try {
const passphrase = 'hello';
@ -450,6 +458,7 @@ describe("Packet", function() {
expect(stringify(msg2[1].packets[0].data)).to.equal(stringify(literal.data));
} finally {
openpgp.config.aead_protect = aead_protectVal;
openpgp.config.aead_protect_version = aead_protect_versionVal;
}
});
@ -457,9 +466,11 @@ describe("Packet", function() {
// From https://gitlab.com/openpgp-wg/rfc4880bis/blob/00b20923/back.mkd#sample-aead-eax-encryption-and-decryption
let aead_protectVal = openpgp.config.aead_protect;
let aead_protect_versionVal = openpgp.config.aead_protect_version;
let aead_chunk_size_byteVal = openpgp.config.aead_chunk_size_byte;
let s2k_iteration_count_byteVal = openpgp.config.s2k_iteration_count_byte;
openpgp.config.aead_protect = 'draft04';
openpgp.config.aead_protect = true;
openpgp.config.aead_protect_version = 4;
openpgp.config.aead_chunk_size_byte = 14;
openpgp.config.s2k_iteration_count_byte = 0x90;
@ -522,6 +533,7 @@ describe("Packet", function() {
expect(stringify(msg2[1].packets[0].data)).to.equal(stringify(literal.data));
} finally {
openpgp.config.aead_protect = aead_protectVal;
openpgp.config.aead_protect_version = aead_protect_versionVal;
openpgp.config.aead_chunk_size_byte = aead_chunk_size_byteVal;
openpgp.config.s2k_iteration_count_byte = s2k_iteration_count_byteVal;
randomBytesStub.restore();
@ -532,9 +544,11 @@ describe("Packet", function() {
// From https://gitlab.com/openpgp-wg/rfc4880bis/blob/00b20923/back.mkd#sample-aead-ocb-encryption-and-decryption
let aead_protectVal = openpgp.config.aead_protect;
let aead_protect_versionVal = openpgp.config.aead_protect_version;
let aead_chunk_size_byteVal = openpgp.config.aead_chunk_size_byte;
let s2k_iteration_count_byteVal = openpgp.config.s2k_iteration_count_byte;
openpgp.config.aead_protect = 'draft04';
openpgp.config.aead_protect = true;
openpgp.config.aead_protect_version = 4;
openpgp.config.aead_chunk_size_byte = 14;
openpgp.config.s2k_iteration_count_byte = 0x90;
@ -598,6 +612,7 @@ describe("Packet", function() {
expect(stringify(msg2[1].packets[0].data)).to.equal(stringify(literal.data));
} finally {
openpgp.config.aead_protect = aead_protectVal;
openpgp.config.aead_protect_version = aead_protect_versionVal;
openpgp.config.aead_chunk_size_byte = aead_chunk_size_byteVal;
openpgp.config.s2k_iteration_count_byte = s2k_iteration_count_byteVal;
randomBytesStub.restore();
@ -715,7 +730,9 @@ describe("Packet", function() {
it('Writing and encryption of a secret key packet. (draft04)', function() {
let aead_protectVal = openpgp.config.aead_protect;
openpgp.config.aead_protect = 'draft04';
let aead_protect_versionVal = openpgp.config.aead_protect_version;
openpgp.config.aead_protect = true;
openpgp.config.aead_protect_version = 4;
const key = new openpgp.packet.List();
key.push(new openpgp.packet.SecretKey());
@ -742,6 +759,7 @@ describe("Packet", function() {
expect(key[0].params.toString()).to.equal(key2[0].params.toString());
}).finally(function() {
openpgp.config.aead_protect = aead_protectVal;
openpgp.config.aead_protect_version = aead_protect_versionVal;
});
});