diff --git a/src/packet/sym_encrypted_aead_protected.js b/src/packet/sym_encrypted_aead_protected.js index eb42ffe7..36dcfb05 100644 --- a/src/packet/sym_encrypted_aead_protected.js +++ b/src/packet/sym_encrypted_aead_protected.js @@ -16,8 +16,7 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /** - * Implementation of the Symmetrically Encrypted AEAD Protected Data Packet
- *
+ * Implementation of the Symmetrically Encrypted Authenticated Encryption with Additional Data (AEAD) Protected Data Packet * {@link https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1}: AEAD Protected Data Packet */ @@ -27,7 +26,8 @@ import util from '../util.js'; import crypto from '../crypto'; import enums from '../enums.js'; -const IV_LEN = crypto.gcm.ivLength; +const VERSION = 1; // A one-octet version number of the data packet. +const IV_LEN = crypto.gcm.ivLength; // currently only AES-GCM is supported /** * @constructor @@ -36,31 +36,52 @@ export default function SymEncryptedAEADProtected() { this.tag = enums.packet.symEncryptedAEADProtected; this.iv = null; this.encrypted = null; - /** Decrypted packets contained within. - * @type {module:packet/packetlist} */ this.packets = null; } +/** + * Parse an encrypted payload of bytes in the order: version, IV, ciphertext (see specification) + */ SymEncryptedAEADProtected.prototype.read = function (bytes) { - this.iv = bytes.subarray(0, IV_LEN); - this.encrypted = bytes.subarray(IV_LEN, bytes.length); + let offset = 0; + if (bytes[offset] !== VERSION) { // The only currently defined value is 1. + throw new Error('Invalid packet version.'); + } + offset++; + this.iv = bytes.subarray(offset, IV_LEN + offset); + offset += IV_LEN; + this.encrypted = bytes.subarray(offset, bytes.length); }; +/** + * Write the encrypted payload of bytes in the order: version, IV, ciphertext (see specification) + * @return {Uint8Array} The encrypted payload + */ SymEncryptedAEADProtected.prototype.write = function () { - return util.concatUint8Array([this.iv, this.encrypted]); + return util.concatUint8Array([new Uint8Array([VERSION]), this.iv, this.encrypted]); }; +/** + * Decrypt the encrypted payload. + * @param {String} sessionKeyAlgorithm The session key's cipher algorithm e.g. 'aes128' + * @param {Uint8Array} key The session key used to encrypt the payload + * @return {Promise} Nothing is returned + */ SymEncryptedAEADProtected.prototype.decrypt = function (sessionKeyAlgorithm, key) { return crypto.gcm.decrypt(sessionKeyAlgorithm, this.encrypted, key, this.iv).then(decrypted => { this.packets.read(decrypted); }); }; +/** + * Encrypt the packet list payload. + * @param {String} sessionKeyAlgorithm The session key's cipher algorithm e.g. 'aes128' + * @param {Uint8Array} key The session key used to encrypt the payload + * @return {Promise} Nothing is returned + */ SymEncryptedAEADProtected.prototype.encrypt = function (sessionKeyAlgorithm, key) { - var data = this.packets.write(); - this.iv = crypto.random.getRandomValues(new Uint8Array(IV_LEN)); - - return crypto.gcm.encrypt(sessionKeyAlgorithm, data, key, this.iv).then(encrypted => { + this.iv = crypto.random.getRandomValues(new Uint8Array(IV_LEN)); // generate new random IV + return crypto.gcm.encrypt(sessionKeyAlgorithm, this.packets.write(), key, this.iv).then(encrypted => { this.encrypted = encrypted; }); -}; +}; \ No newline at end of file diff --git a/test/general/packet.js b/test/general/packet.js index 0bc59f14..759630a2 100644 --- a/test/general/packet.js +++ b/test/general/packet.js @@ -121,6 +121,29 @@ describe("Packet", function() { done(); }); + it('Sym. encrypted AEAD protected packet', function(done) { + var 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]), + algo = 'aes256'; + + var literal = new openpgp.packet.Literal(), + enc = new openpgp.packet.SymEncryptedAEADProtected(), + msg = new openpgp.packet.List(); + + msg.push(enc); + literal.setText('Hello world!'); + enc.packets.push(literal); + + var msg2 = new openpgp.packet.List(); + + enc.encrypt(algo, key).then(function() { + msg2.read(msg.write()); + return msg2[0].decrypt(algo, key); + }).then(function() { + expect(msg2[0].packets[0].data).to.deep.equal(literal.data); + done(); + }); + }); + it('Sym encrypted session key with a compressed packet', function(done) { var msg = '-----BEGIN PGP MESSAGE-----\n' +