From 0a3246a6972f3f69e97c31b66558f401e6da1ced Mon Sep 17 00:00:00 2001 From: larabr <7375870+larabr@users.noreply.github.com> Date: Tue, 20 Apr 2021 23:31:26 +0200 Subject: [PATCH 1/8] Cleanup PacketList type definitions and make push() compatible with super class --- openpgp.d.ts | 20 +++++--------------- src/packet/packetlist.js | 32 +++++++++++++++++++------------- test/typescript/definitions.ts | 9 +++++++-- 3 files changed, 31 insertions(+), 30 deletions(-) diff --git a/openpgp.d.ts b/openpgp.d.ts index 34429fc6f..6d610ae87 100644 --- a/openpgp.d.ts +++ b/openpgp.d.ts @@ -455,24 +455,14 @@ export type AnyKeyPacket = BasePublicKeyPacket; type DataPacketType = 'utf8' | 'binary' | 'text' | 'mime'; -export class PacketList extends Array { - [index: number]: PACKET_TYPE; +export class PacketList extends Array { public length: number; public read(bytes: Uint8Array, allowedPackets?: object, config?: Config): void; public write(): Uint8Array; - public push(...packet: PACKET_TYPE[]): number; - public pop(): PACKET_TYPE; - public filter(callback: (packet: PACKET_TYPE, i: number, self: PacketList) => void): PacketList; - public filterByTag(...args: enums.packet[]): PacketList; - public forEach(callback: (packet: PACKET_TYPE, i: number, self: PacketList) => void): void; - public map(callback: (packet: PACKET_TYPE, i: number, self: PacketList) => RETURN_TYPE): PacketList; - // some() - // every() - // findPacket() - // indexOfTag() - // slice() - // concat() - // fromStructuredClone() + public filterByTag(...args: enums.packet[]): PacketList; + public indexOfTag(...tags: enums.packet[]): number[]; + public findPacket(tag: enums.packet): T | undefined; + public concat(packets: Array): PacketList; // in place } /* ############## v5 STREAM #################### */ diff --git a/src/packet/packetlist.js b/src/packet/packetlist.js index 742c17147..81f1d9625 100644 --- a/src/packet/packetlist.js +++ b/src/packet/packetlist.js @@ -130,27 +130,29 @@ class PacketList extends Array { * Adds a packet to the list. This is the only supported method of doing so; * writing to packetlist[i] directly will result in an error. * @param {Object} packet - Packet to push + * @returns {Integer} length of resulting packetlist */ push(packet) { if (!packet) { - return; + return this.length; } packet.packets = packet.packets || new PacketList(); - - super.push(packet); + return super.push(packet); } /** - * Creates a new PacketList with all packets from the given types + * Creates a new PacketList with all packets matching the given tag(s) + * @param {...module:enums.packet} tags - packet tags to look for + * @returns {PacketList} */ - filterByTag(...args) { + filterByTag(...tags) { const filtered = new PacketList(); const handle = tag => packetType => tag === packetType; for (let i = 0; i < this.length; i++) { - if (args.some(handle(this[i].constructor.tag))) { + if (tags.some(handle(this[i].constructor.tag))) { filtered.push(this[i]); } } @@ -159,25 +161,27 @@ class PacketList extends Array { } /** - * Traverses packet tree and returns first matching packet - * @param {module:enums.packet} type - The packet type + * Traverses packet list and returns first packet with matching tag + * @param {module:enums.packet} tag - The packet tag * @returns {Packet|undefined} */ - findPacket(type) { - return this.find(packet => packet.constructor.tag === type); + findPacket(tag) { + return this.find(packet => packet.constructor.tag === tag); } /** - * Returns array of found indices by tag + * Find indices of packets with the given tag(s) + * @param {...module:enums.packet} tags - packet tags to look for + * @returns {Integer[]} packet indices */ - indexOfTag(...args) { + indexOfTag(...tags) { const tagIndex = []; const that = this; const handle = tag => packetType => tag === packetType; for (let i = 0; i < this.length; i++) { - if (args.some(handle(that[i].constructor.tag))) { + if (tags.some(handle(that[i].constructor.tag))) { tagIndex.push(i); } } @@ -186,6 +190,8 @@ class PacketList extends Array { /** * Concatenates packetlist or array of packets + * @param {PacketList|Packet} packets - packets to concatenate + * @returns {PacketList} this packetlist */ concat(packetlist) { if (packetlist) { diff --git a/test/typescript/definitions.ts b/test/typescript/definitions.ts index 60db7c601..abfa32e0b 100644 --- a/test/typescript/definitions.ts +++ b/test/typescript/definitions.ts @@ -6,9 +6,9 @@ * - if it fails to run, edit this file to match the actual library API, then edit the definitions file (openpgp.d.ts) accordingly. */ -import { generateKey, readKey, readKeys, Key, readMessage, createMessage, Message, createCleartextMessage, encrypt, decrypt, sign, verify, config } from '../..'; - import { expect } from 'chai'; +import { generateKey, readKey, readKeys, Key, readMessage, createMessage, Message, createCleartextMessage, encrypt, decrypt, sign, verify, config, LiteralDataPacket, PacketList, enums } from '../..'; + (async () => { @@ -78,6 +78,11 @@ import { expect } from 'chai'; const verifiedBinaryData: Uint8Array = verifiedBinary.data; expect(verifiedBinaryData).to.deep.equal(binary); + const packets = new PacketList(); + expect(packets.push()).to.equal(0); + expect(packets.push(new LiteralDataPacket())).to.equal(1); + expect(packets[0].tag).to.equal(enums.packet.literalData); + // // Detached - sign cleartext message (armored) // import { Message, sign } from 'openpgp'; // const message = await createMessage({ text: util.removeTrailingSpaces(text) }); From cc17eed1d40852c255ba86a6fa5854e7d4b9d764 Mon Sep 17 00:00:00 2001 From: larabr <7375870+larabr@users.noreply.github.com> Date: Tue, 20 Apr 2021 23:56:15 +0200 Subject: [PATCH 2/8] Fix packet.tag declaration --- openpgp.d.ts | 34 +++++++++++++++++----------------- test/typescript/definitions.ts | 4 +++- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/openpgp.d.ts b/openpgp.d.ts index 6d610ae87..5ee4bf2eb 100644 --- a/openpgp.d.ts +++ b/openpgp.d.ts @@ -294,7 +294,7 @@ interface PartialConfig extends Partial {} /* ############## v5 PACKET #################### */ declare abstract class BasePacket { - public tag: enums.packet; + static tag: enums.packet; public read(bytes: Uint8Array): void; public write(): Uint8Array; } @@ -319,11 +319,11 @@ declare abstract class BasePublicKeyPacket extends BasePacket { } export class PublicKeyPacket extends BasePublicKeyPacket { - public tag: enums.packet.publicKey; + static tag: enums.packet.publicKey; } export class PublicSubkeyPacket extends BasePublicKeyPacket { - public tag: enums.packet.publicSubkey; + static tag: enums.packet.publicSubkey; } declare abstract class BaseSecretKeyPacket extends BasePublicKeyPacket { @@ -336,51 +336,51 @@ declare abstract class BaseSecretKeyPacket extends BasePublicKeyPacket { } export class SecretKeyPacket extends BaseSecretKeyPacket { - public tag: enums.packet.secretKey; + static tag: enums.packet.secretKey; } export class SecretSubkeyPacket extends BaseSecretKeyPacket { - public tag: enums.packet.secretSubkey; + static tag: enums.packet.secretSubkey; } export class CompressedDataPacket extends BasePacket { - public tag: enums.packet.compressedData; + static tag: enums.packet.compressedData; } export class SymEncryptedIntegrityProtectedDataPacket extends BasePacket { - public tag: enums.packet.symEncryptedIntegrityProtectedData; + static tag: enums.packet.symEncryptedIntegrityProtectedData; } export class AEADEncryptedDataPacket extends BasePacket { - public tag: enums.packet.aeadEncryptedData; + static tag: enums.packet.aeadEncryptedData; } export class PublicKeyEncryptedSessionKeyPaclet extends BasePacket { - public tag: enums.packet.publicKeyEncryptedSessionKey; + static tag: enums.packet.publicKeyEncryptedSessionKey; } export class SymEncryptedSessionKey extends BasePacket { - public tag: enums.packet.symEncryptedSessionKey; + static tag: enums.packet.symEncryptedSessionKey; } export class LiteralDataPacket extends BasePacket { - public tag: enums.packet.literalData; + static tag: enums.packet.literalData; } export class SymmetricallyEncryptedDataPacket extends BasePacket { - public tag: enums.packet.symmetricallyEncryptedData; + static tag: enums.packet.symmetricallyEncryptedData; } export class MarkerPacket extends BasePacket { - public tag: enums.packet.marker; + static tag: enums.packet.marker; } export class UserAttributePacket extends BasePacket { - public tag: enums.packet.userAttribute; + static tag: enums.packet.userAttribute; } export class OnePassSignaturePacket extends BasePacket { - public tag: enums.packet.onePassSignature; + static tag: enums.packet.onePassSignature; public correspondingSig?: Promise; } @@ -394,7 +394,7 @@ export class UserIDPacket extends BasePacket { } export class SignaturePacket extends BasePacket { - public tag: enums.packet.signature; + static tag: enums.packet.signature; public version: number; public signatureType: enums.signature | null; public hashAlgorithm: enums.hash | null; @@ -445,7 +445,7 @@ export class SignaturePacket extends BasePacket { } export class TrustPacket extends BasePacket { - public tag: enums.packet.trust; + static tag: enums.packet.trust; } export type AnyPacket = BasePacket; diff --git a/test/typescript/definitions.ts b/test/typescript/definitions.ts index abfa32e0b..d13182f1c 100644 --- a/test/typescript/definitions.ts +++ b/test/typescript/definitions.ts @@ -81,7 +81,9 @@ import { generateKey, readKey, readKeys, Key, readMessage, createMessage, Messag const packets = new PacketList(); expect(packets.push()).to.equal(0); expect(packets.push(new LiteralDataPacket())).to.equal(1); - expect(packets[0].tag).to.equal(enums.packet.literalData); + packets[0].write(); + + expect(LiteralDataPacket.tag).to.equal(enums.packet.literalData) // // Detached - sign cleartext message (armored) // import { Message, sign } from 'openpgp'; From 42c5fbfa96b1d5762ace844fda23670ecb3fd5f1 Mon Sep 17 00:00:00 2001 From: larabr <7375870+larabr@users.noreply.github.com> Date: Wed, 21 Apr 2021 16:02:29 +0200 Subject: [PATCH 3/8] Add write method to Marker and Trust packets, add type definitions and tests for more packet methods --- openpgp.d.ts | 56 +++++++++++++++++++++++----------- src/packet/marker.js | 26 +++++++++------- src/packet/trust.js | 5 +++ test/typescript/definitions.ts | 23 +++++++++++--- 4 files changed, 76 insertions(+), 34 deletions(-) diff --git a/openpgp.d.ts b/openpgp.d.ts index 5ee4bf2eb..96415079f 100644 --- a/openpgp.d.ts +++ b/openpgp.d.ts @@ -294,7 +294,7 @@ interface PartialConfig extends Partial {} /* ############## v5 PACKET #################### */ declare abstract class BasePacket { - static tag: enums.packet; + static readonly tag: enums.packet; public read(bytes: Uint8Array): void; public write(): Uint8Array; } @@ -319,11 +319,11 @@ declare abstract class BasePublicKeyPacket extends BasePacket { } export class PublicKeyPacket extends BasePublicKeyPacket { - static tag: enums.packet.publicKey; + static readonly tag: enums.packet.publicKey; } export class PublicSubkeyPacket extends BasePublicKeyPacket { - static tag: enums.packet.publicSubkey; + static readonly tag: enums.packet.publicSubkey; } declare abstract class BaseSecretKeyPacket extends BasePublicKeyPacket { @@ -336,56 +336,76 @@ declare abstract class BaseSecretKeyPacket extends BasePublicKeyPacket { } export class SecretKeyPacket extends BaseSecretKeyPacket { - static tag: enums.packet.secretKey; + static readonly tag: enums.packet.secretKey; } export class SecretSubkeyPacket extends BaseSecretKeyPacket { - static tag: enums.packet.secretSubkey; + static readonly tag: enums.packet.secretSubkey; } export class CompressedDataPacket extends BasePacket { - static tag: enums.packet.compressedData; + static readonly tag: enums.packet.compressedData; + private compress(): void; + private decompress(): void; } export class SymEncryptedIntegrityProtectedDataPacket extends BasePacket { - static tag: enums.packet.symEncryptedIntegrityProtectedData; + static readonly tag: enums.packet.symEncryptedIntegrityProtectedData; } export class AEADEncryptedDataPacket extends BasePacket { - static tag: enums.packet.aeadEncryptedData; + static readonly tag: enums.packet.aeadEncryptedData; + private decrypt(sessionKeyAlgorithm: string, sessionKey: Uint8Array): void; + private encrypt(sessionKeyAlgorithm: string, sessionKey: Uint8Array, config?: Config): void; + private crypt(fn: Function, sessionKey: Uint8Array, data: MaybeStream): MaybeStream } export class PublicKeyEncryptedSessionKeyPaclet extends BasePacket { - static tag: enums.packet.publicKeyEncryptedSessionKey; + static readonly tag: enums.packet.publicKeyEncryptedSessionKey; + private decrypt(keyPacket: SecretKeyPacket): Promise; // throws on error + private encrypt(keyPacket: PublicKeyPacket): Promise; // throws on error } export class SymEncryptedSessionKey extends BasePacket { - static tag: enums.packet.symEncryptedSessionKey; + static readonly tag: enums.packet.symEncryptedSessionKey; + private decrypt(passphrase: string): Promise; + private encrypt(passphrase: string, config?: Config): Promise; } export class LiteralDataPacket extends BasePacket { - static tag: enums.packet.literalData; + static readonly tag: enums.packet.literalData; + private getText(clone?: boolean): MaybeStream; + private getBytes(clone?: boolean): MaybeStream; + private setText(text: MaybeStream, format?: DataPacketType); + private setBytes(bytes: MaybeStream, format?: DataPacketType); + private setFilename(filename: string); + private getFilename(): string; + private writeHeader(): Uint8Array; } export class SymmetricallyEncryptedDataPacket extends BasePacket { - static tag: enums.packet.symmetricallyEncryptedData; + static readonly tag: enums.packet.symmetricallyEncryptedData; + private decrypt(sessionKeyAlgorithm: enums.symmetric, sessionKey: Uint8Array, config?: Config): void; + private encrypt(sessionKeyAlgorithm: enums.symmetric, sessionKey: Uint8Array, config?: Config): void; } export class MarkerPacket extends BasePacket { - static tag: enums.packet.marker; + static readonly tag: enums.packet.marker; } export class UserAttributePacket extends BasePacket { - static tag: enums.packet.userAttribute; + static readonly tag: enums.packet.userAttribute; + private equals(packet: UserAttributePacket): boolean; } export class OnePassSignaturePacket extends BasePacket { - static tag: enums.packet.onePassSignature; + static readonly tag: enums.packet.onePassSignature; public correspondingSig?: Promise; + private verify: SignaturePacket['verify']; } export class UserIDPacket extends BasePacket { - public readonly tag: enums.packet.userID; + static readonly tag: enums.packet.userID; public readonly name: string; public readonly comment: string; public readonly email: string; @@ -394,7 +414,7 @@ export class UserIDPacket extends BasePacket { } export class SignaturePacket extends BasePacket { - static tag: enums.packet.signature; + static readonly tag: enums.packet.signature; public version: number; public signatureType: enums.signature | null; public hashAlgorithm: enums.hash | null; @@ -445,7 +465,7 @@ export class SignaturePacket extends BasePacket { } export class TrustPacket extends BasePacket { - static tag: enums.packet.trust; + static readonly tag: enums.packet.trust; } export type AnyPacket = BasePacket; diff --git a/src/packet/marker.js b/src/packet/marker.js index d55df6d17..1ee18fbf7 100644 --- a/src/packet/marker.js +++ b/src/packet/marker.js @@ -28,7 +28,13 @@ import enums from '../enums'; * tag. With PGP 5.x, this packet has been reassigned and is reserved for use as * the Marker packet. * - * Such a packet MUST be ignored when received. + * The body of this packet consists of: + * The three octets 0x50, 0x47, 0x50 (which spell "PGP" in UTF-8). + * + * Such a packet MUST be ignored when received. It may be placed at the + * beginning of a message that uses features not available in PGP + * version 2.6 in order to cause that version to report that newer + * software is necessary to process the message. */ class MarkerPacket { static get tag() { @@ -36,15 +42,9 @@ class MarkerPacket { } /** - * Parsing function for a literal data packet (tag 10). - * - * @param {String} input - Payload of a tag 10 packet - * @param {Integer} position - * Position to start reading from the input string - * @param {Integer} len - * Length of the packet or the remaining length of - * input at position - * @returns {MarkerPacket} Object representation. + * Parsing function for a marker data packet (tag 10). + * @param {Uint8Array} bytes - Payload of a tag 10 packet + * @returns {Boolean} whether the packet payload contains "PGP" */ read(bytes) { if (bytes[0] === 0x50 && // P @@ -52,9 +52,13 @@ class MarkerPacket { bytes[2] === 0x50) { // P return true; } - // marker packet does not contain "PGP" return false; } + + // eslint-disable-next-line class-methods-use-this + write() { + return new Uint8Array([0x50, 0x47, 0x50]); + } } export default MarkerPacket; diff --git a/src/packet/trust.js b/src/packet/trust.js index b1aeec4f4..8d1bc93b4 100644 --- a/src/packet/trust.js +++ b/src/packet/trust.js @@ -28,6 +28,11 @@ class TrustPacket { * @param {String} byptes - Payload of a tag 12 packet */ read() {} // TODO + + // eslint-disable-next-line class-methods-use-this + write() { + throw new Error('Trust packets are not supported'); + } } export default TrustPacket; diff --git a/test/typescript/definitions.ts b/test/typescript/definitions.ts index d13182f1c..14a38dc66 100644 --- a/test/typescript/definitions.ts +++ b/test/typescript/definitions.ts @@ -7,8 +7,7 @@ */ import { expect } from 'chai'; -import { generateKey, readKey, readKeys, Key, readMessage, createMessage, Message, createCleartextMessage, encrypt, decrypt, sign, verify, config, LiteralDataPacket, PacketList, enums } from '../..'; - +import { generateKey, readKey, readKeys, Key, readMessage, createMessage, Message, createCleartextMessage, encrypt, decrypt, sign, verify, config, enums, LiteralDataPacket, PacketList, CompressedDataPacket } from '../..'; (async () => { @@ -78,12 +77,26 @@ import { generateKey, readKey, readKeys, Key, readMessage, createMessage, Messag const verifiedBinaryData: Uint8Array = verifiedBinary.data; expect(verifiedBinaryData).to.deep.equal(binary); + // Generic packetlist const packets = new PacketList(); expect(packets.push()).to.equal(0); expect(packets.push(new LiteralDataPacket())).to.equal(1); - packets[0].write(); - - expect(LiteralDataPacket.tag).to.equal(enums.packet.literalData) + packets.map(packet => packet.write); + // @ts-expect-error for unsafe downcasting + packets.map((packet: LiteralDataPacket) => packet.getText()); + // @ts-expect-error for non-packet element + try { new PacketList().push(1); } catch (e) {} + + + // Packetlist of specific type + const literalPackets = new PacketList(); + literalPackets.push(new LiteralDataPacket()); + literalPackets[0].write(); + literalPackets.map((packet: LiteralDataPacket) => packet); + // @ts-expect-error for incompatible packet type + new PacketList().push(new CompressedDataPacket()); + + expect(LiteralDataPacket.tag).to.equal(enums.packet.literalData); // // Detached - sign cleartext message (armored) // import { Message, sign } from 'openpgp'; From 94ab861521d243b27417f2719e54f934e04b9f45 Mon Sep 17 00:00:00 2001 From: larabr <7375870+larabr@users.noreply.github.com> Date: Wed, 21 Apr 2021 17:05:10 +0200 Subject: [PATCH 4/8] Rename `PacketList.concat` to `append` --- openpgp.d.ts | 2 +- src/key/key.js | 8 ++++---- src/key/subkey.js | 4 ++-- src/key/user.js | 6 +++--- src/message.js | 10 +++++----- src/packet/packetlist.js | 8 +++----- test/general/openpgp.js | 4 ++-- test/general/packet.js | 4 ++-- test/security/subkey_trust.js | 2 +- test/security/unsigned_subpackets.js | 2 +- test/typescript/definitions.ts | 3 +++ 11 files changed, 27 insertions(+), 26 deletions(-) diff --git a/openpgp.d.ts b/openpgp.d.ts index 96415079f..ef554ed01 100644 --- a/openpgp.d.ts +++ b/openpgp.d.ts @@ -482,7 +482,7 @@ export class PacketList extends Array { public filterByTag(...args: enums.packet[]): PacketList; public indexOfTag(...tags: enums.packet[]): number[]; public findPacket(tag: enums.packet): T | undefined; - public concat(packets: Array): PacketList; // in place + public append(packets: Array): void; } /* ############## v5 STREAM #################### */ diff --git a/src/key/key.js b/src/key/key.js index 44240da4d..334118680 100644 --- a/src/key/key.js +++ b/src/key/key.js @@ -150,10 +150,10 @@ class Key { toPacketlist() { const packetlist = new PacketList(); packetlist.push(this.keyPacket); - packetlist.concat(this.revocationSignatures); - packetlist.concat(this.directSignatures); - this.users.map(user => packetlist.concat(user.toPacketlist())); - this.subKeys.map(subKey => packetlist.concat(subKey.toPacketlist())); + packetlist.append(this.revocationSignatures); + packetlist.append(this.directSignatures); + this.users.map(user => packetlist.append(user.toPacketlist())); + this.subKeys.map(subKey => packetlist.append(subKey.toPacketlist())); return packetlist; } diff --git a/src/key/subkey.js b/src/key/subkey.js index 52be0d859..488df5f1d 100644 --- a/src/key/subkey.js +++ b/src/key/subkey.js @@ -34,8 +34,8 @@ class SubKey { toPacketlist() { const packetlist = new PacketList(); packetlist.push(this.keyPacket); - packetlist.concat(this.revocationSignatures); - packetlist.concat(this.bindingSignatures); + packetlist.append(this.revocationSignatures); + packetlist.append(this.bindingSignatures); return packetlist; } diff --git a/src/key/user.js b/src/key/user.js index 1bd14d43b..d155a7fa4 100644 --- a/src/key/user.js +++ b/src/key/user.js @@ -30,9 +30,9 @@ class User { toPacketlist() { const packetlist = new PacketList(); packetlist.push(this.userID || this.userAttribute); - packetlist.concat(this.revocationSignatures); - packetlist.concat(this.selfCertifications); - packetlist.concat(this.otherCertifications); + packetlist.append(this.revocationSignatures); + packetlist.append(this.selfCertifications); + packetlist.append(this.otherCertifications); return packetlist; } diff --git a/src/message.js b/src/message.js index 1416aa176..cf67aa06c 100644 --- a/src/message.js +++ b/src/message.js @@ -385,7 +385,7 @@ export class Message { delete pkESKeyPacket.sessionKey; // delete plaintext session key after encryption return pkESKeyPacket; })); - packetlist.concat(results); + packetlist.append(results); } if (passwords) { const testDecrypt = async function(keyPacket, password) { @@ -420,7 +420,7 @@ export class Message { }; const results = await Promise.all(passwords.map(pwd => encryptPassword(sessionKey, algorithm, aeadAlgorithm, pwd))); - packetlist.concat(results); + packetlist.append(results); } return new Message(packetlist); @@ -487,7 +487,7 @@ export class Message { }); packetlist.push(literalDataPacket); - packetlist.concat(await createSignaturePackets(literalDataPacket, privateKeys, signature, signingKeyIDs, date, userIDs, false, config)); + packetlist.append(await createSignaturePackets(literalDataPacket, privateKeys, signature, signingKeyIDs, date, userIDs, false, config)); return new Message(packetlist); } @@ -551,7 +551,7 @@ export class Message { throw new Error('Can only verify message with one literal data packet.'); } if (stream.isArrayStream(msg.packets.stream)) { - msg.packets.concat(await stream.readToEnd(msg.packets.stream, _ => _)); + msg.packets.append(await stream.readToEnd(msg.packets.stream, _ => _)); } const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature).reverse(); const signatureList = msg.packets.filterByTag(enums.packet.signature); @@ -686,7 +686,7 @@ export async function createSignaturePackets(literalDataPacket, privateKeys, sig if (signature) { const existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature); - packetlist.concat(existingSigPacketlist); + packetlist.append(existingSigPacketlist); } return packetlist; } diff --git a/src/packet/packetlist.js b/src/packet/packetlist.js index 81f1d9625..4c14c5cc2 100644 --- a/src/packet/packetlist.js +++ b/src/packet/packetlist.js @@ -189,17 +189,15 @@ class PacketList extends Array { } /** - * Concatenates packetlist or array of packets - * @param {PacketList|Packet} packets - packets to concatenate - * @returns {PacketList} this packetlist + * Append packetlist or array of packets, in place + * @param {PacketList|Array} packets - packets to append */ - concat(packetlist) { + append(packetlist) { if (packetlist) { for (let i = 0; i < packetlist.length; i++) { this.push(packetlist[i]); } } - return this; } } diff --git a/test/general/openpgp.js b/test/general/openpgp.js index 060d696ce..bb2900350 100644 --- a/test/general/openpgp.js +++ b/test/general/openpgp.js @@ -2665,7 +2665,7 @@ module.exports = () => describe('OpenPGP.js public api tests', function() { }; return openpgp.sign(signOpt).then(async function (signed) { const message = await openpgp.readMessage({ binaryMessage: signed }); - message.packets.concat(await openpgp.stream.readToEnd(message.packets.stream, _ => _)); + message.packets.append(await openpgp.stream.readToEnd(message.packets.stream, _ => _)); const packets = new openpgp.PacketList(); packets.push(message.packets.findPacket(openpgp.enums.packet.signature)); packets.push(message.packets.findPacket(openpgp.enums.packet.literalData)); @@ -2705,7 +2705,7 @@ module.exports = () => describe('OpenPGP.js public api tests', function() { return openpgp.sign(signOpt).then(async function (signed) { expect(openpgp.stream.isStream(signed)).to.equal(global.ReadableStream ? 'web' : 'node'); const message = await openpgp.readMessage({ binaryMessage: signed }); - message.packets.concat(await openpgp.stream.readToEnd(message.packets.stream, _ => _)); + message.packets.append(await openpgp.stream.readToEnd(message.packets.stream, _ => _)); const packets = new openpgp.PacketList(); packets.push(message.packets.findPacket(openpgp.enums.packet.signature)); packets.push(message.packets.findPacket(openpgp.enums.packet.literalData)); diff --git a/test/general/packet.js b/test/general/packet.js index e9f261bb8..181fa95c2 100644 --- a/test/general/packet.js +++ b/test/general/packet.js @@ -747,7 +747,7 @@ module.exports = () => describe("Packet", function() { await encData.decrypt(pkesk.sessionKeyAlgorithm, pkesk.sessionKey); const payload = encData.packets[0].packets; - payload.concat(await openpgp.stream.readToEnd(payload.stream, arr => arr)); + payload.append(await openpgp.stream.readToEnd(payload.stream, arr => arr)); const literal = payload[1]; const signature = payload[2]; @@ -942,7 +942,7 @@ V+HOQJQxXJkVRYa3QrFUehiMzTeqqMdgC6ZqJy7+ const signed2 = new openpgp.PacketList(); await signed2.read(raw, allAllowedPackets); - signed2.concat(await openpgp.stream.readToEnd(signed2.stream, arr => arr)); + signed2.append(await openpgp.stream.readToEnd(signed2.stream, arr => arr)); await Promise.all([ signed2[1].verify(key, openpgp.enums.signature.text, signed2[0]), diff --git a/test/security/subkey_trust.js b/test/security/subkey_trust.js index 387a6cc94..d532d9ba1 100644 --- a/test/security/subkey_trust.js +++ b/test/security/subkey_trust.js @@ -56,7 +56,7 @@ async function testSubkeyTrust() { fakeBindingSignature.keyFlags = [enums.keyFlags.signData]; await fakeBindingSignature.sign(attackerPrivKey.keyPacket, dataToSign); const newList = new PacketList(); - newList.concat([ + newList.append([ pktPrivAttacker[0], // attacker private key pktPrivAttacker[1], // attacker user pktPrivAttacker[2], // attacker self signature diff --git a/test/security/unsigned_subpackets.js b/test/security/unsigned_subpackets.js index 2029ea6fe..f63bc7aa0 100644 --- a/test/security/unsigned_subpackets.js +++ b/test/security/unsigned_subpackets.js @@ -81,7 +81,7 @@ async function makeKeyValid() { pusersig.readSubPackets(fake.writeHashedSubPackets(), false); // reconstruct the modified key const newlist = new PacketList(); - newlist.concat([pubkey, puser, pusersig]); + newlist.append([pubkey, puser, pusersig]); let modifiedkey = new Key(newlist); // re-read the message to eliminate any // behaviour due to cached values. diff --git a/test/typescript/definitions.ts b/test/typescript/definitions.ts index 14a38dc66..edd527225 100644 --- a/test/typescript/definitions.ts +++ b/test/typescript/definitions.ts @@ -93,6 +93,9 @@ import { generateKey, readKey, readKeys, Key, readMessage, createMessage, Messag literalPackets.push(new LiteralDataPacket()); literalPackets[0].write(); literalPackets.map((packet: LiteralDataPacket) => packet); + packets.append(literalPackets); + // @ts-expect-error for incompatible packetlist type + literalPackets.append(packets); // @ts-expect-error for incompatible packet type new PacketList().push(new CompressedDataPacket()); From ed22a33175589e5fbf1f393bd2700d49899284a8 Mon Sep 17 00:00:00 2001 From: larabr <7375870+larabr@users.noreply.github.com> Date: Wed, 21 Apr 2021 19:50:37 +0200 Subject: [PATCH 5/8] Fix session key count check --- src/message.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/message.js b/src/message.js index cf67aa06c..37597c13d 100644 --- a/src/message.js +++ b/src/message.js @@ -170,7 +170,7 @@ export class Message { let exception; if (passwords) { const symESKeyPacketlist = this.packets.filterByTag(enums.packet.symEncryptedSessionKey); - if (!symESKeyPacketlist) { + if (symESKeyPacketlist.length === 0) { throw new Error('No symmetrically encrypted session key packet found.'); } await Promise.all(passwords.map(async function(password, i) { @@ -192,7 +192,7 @@ export class Message { })); } else if (privateKeys) { const pkESKeyPacketlist = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey); - if (!pkESKeyPacketlist) { + if (pkESKeyPacketlist.length === 0) { throw new Error('No public key encrypted session key packet found.'); } await Promise.all(pkESKeyPacketlist.map(async function(keyPacket) { From 13786c2eafb2c658a3d5970130edcf4e39586949 Mon Sep 17 00:00:00 2001 From: larabr <7375870+larabr@users.noreply.github.com> Date: Thu, 29 Apr 2021 14:34:11 +0200 Subject: [PATCH 6/8] Use Array.push instead of PacketList.push and append --- openpgp.d.ts | 1 - src/key/key.js | 8 +- src/key/subkey.js | 4 +- src/key/user.js | 6 +- src/message.js | 12 +-- src/packet/aead_encrypted_data.js | 2 + src/packet/compressed_data.js | 2 + src/packet/packetlist.js | 27 ------- .../sym_encrypted_integrity_protected_data.js | 12 +-- src/packet/symmetrically_encrypted_data.js | 2 + test/general/openpgp.js | 4 +- test/general/packet.js | 75 ++++++++++--------- test/security/subkey_trust.js | 2 +- test/security/unsigned_subpackets.js | 2 +- test/typescript/definitions.ts | 4 +- 15 files changed, 68 insertions(+), 95 deletions(-) diff --git a/openpgp.d.ts b/openpgp.d.ts index ef554ed01..e15826e27 100644 --- a/openpgp.d.ts +++ b/openpgp.d.ts @@ -482,7 +482,6 @@ export class PacketList extends Array { public filterByTag(...args: enums.packet[]): PacketList; public indexOfTag(...tags: enums.packet[]): number[]; public findPacket(tag: enums.packet): T | undefined; - public append(packets: Array): void; } /* ############## v5 STREAM #################### */ diff --git a/src/key/key.js b/src/key/key.js index 334118680..f02ad4967 100644 --- a/src/key/key.js +++ b/src/key/key.js @@ -150,10 +150,10 @@ class Key { toPacketlist() { const packetlist = new PacketList(); packetlist.push(this.keyPacket); - packetlist.append(this.revocationSignatures); - packetlist.append(this.directSignatures); - this.users.map(user => packetlist.append(user.toPacketlist())); - this.subKeys.map(subKey => packetlist.append(subKey.toPacketlist())); + packetlist.push(...this.revocationSignatures); + packetlist.push(...this.directSignatures); + this.users.map(user => packetlist.push(...user.toPacketlist())); + this.subKeys.map(subKey => packetlist.push(...subKey.toPacketlist())); return packetlist; } diff --git a/src/key/subkey.js b/src/key/subkey.js index 488df5f1d..a4ad6521e 100644 --- a/src/key/subkey.js +++ b/src/key/subkey.js @@ -34,8 +34,8 @@ class SubKey { toPacketlist() { const packetlist = new PacketList(); packetlist.push(this.keyPacket); - packetlist.append(this.revocationSignatures); - packetlist.append(this.bindingSignatures); + packetlist.push(...this.revocationSignatures); + packetlist.push(...this.bindingSignatures); return packetlist; } diff --git a/src/key/user.js b/src/key/user.js index d155a7fa4..61c540e58 100644 --- a/src/key/user.js +++ b/src/key/user.js @@ -30,9 +30,9 @@ class User { toPacketlist() { const packetlist = new PacketList(); packetlist.push(this.userID || this.userAttribute); - packetlist.append(this.revocationSignatures); - packetlist.append(this.selfCertifications); - packetlist.append(this.otherCertifications); + packetlist.push(...this.revocationSignatures); + packetlist.push(...this.selfCertifications); + packetlist.push(...this.otherCertifications); return packetlist; } diff --git a/src/message.js b/src/message.js index 37597c13d..89d0e2b3c 100644 --- a/src/message.js +++ b/src/message.js @@ -385,7 +385,7 @@ export class Message { delete pkESKeyPacket.sessionKey; // delete plaintext session key after encryption return pkESKeyPacket; })); - packetlist.append(results); + packetlist.push(...results); } if (passwords) { const testDecrypt = async function(keyPacket, password) { @@ -420,7 +420,7 @@ export class Message { }; const results = await Promise.all(passwords.map(pwd => encryptPassword(sessionKey, algorithm, aeadAlgorithm, pwd))); - packetlist.append(results); + packetlist.push(...results); } return new Message(packetlist); @@ -487,7 +487,7 @@ export class Message { }); packetlist.push(literalDataPacket); - packetlist.append(await createSignaturePackets(literalDataPacket, privateKeys, signature, signingKeyIDs, date, userIDs, false, config)); + packetlist.push(...(await createSignaturePackets(literalDataPacket, privateKeys, signature, signingKeyIDs, date, userIDs, false, config))); return new Message(packetlist); } @@ -551,7 +551,7 @@ export class Message { throw new Error('Can only verify message with one literal data packet.'); } if (stream.isArrayStream(msg.packets.stream)) { - msg.packets.append(await stream.readToEnd(msg.packets.stream, _ => _)); + msg.packets.push(...await stream.readToEnd(msg.packets.stream, _ => _ || [])); } const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature).reverse(); const signatureList = msg.packets.filterByTag(enums.packet.signature); @@ -686,7 +686,7 @@ export async function createSignaturePackets(literalDataPacket, privateKeys, sig if (signature) { const existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature); - packetlist.append(existingSigPacketlist); + packetlist.push(...existingSigPacketlist); } return packetlist; } @@ -752,7 +752,7 @@ async function createVerificationObject(signature, literalDataList, keys, date = signature: (async () => { const sig = await signaturePacket; const packetlist = new PacketList(); - packetlist.push(sig); + sig && packetlist.push(sig); return new Signature(packetlist); })() }; diff --git a/src/packet/aead_encrypted_data.js b/src/packet/aead_encrypted_data.js index 0cd0464cb..aa9c86eb5 100644 --- a/src/packet/aead_encrypted_data.js +++ b/src/packet/aead_encrypted_data.js @@ -25,6 +25,7 @@ import LiteralDataPacket from './literal_data'; import CompressedDataPacket from './compressed_data'; import OnePassSignaturePacket from './one_pass_signature'; import SignaturePacket from './signature'; +import PacketList from './packetlist'; // An AEAD-encrypted Data packet can contain the following packet types const allowedPackets = /*#__PURE__*/ util.constructAllowedPackets([ @@ -93,6 +94,7 @@ class AEADEncryptedDataPacket { * @async */ async decrypt(sessionKeyAlgorithm, key) { + this.packets = new PacketList(); await this.packets.read(await this.crypt('decrypt', key, stream.clone(this.encrypted)), allowedPackets); } diff --git a/src/packet/compressed_data.js b/src/packet/compressed_data.js index a3413a414..cda81e97e 100644 --- a/src/packet/compressed_data.js +++ b/src/packet/compressed_data.js @@ -27,6 +27,7 @@ import defaultConfig from '../config'; import LiteralDataPacket from './literal_data'; import OnePassSignaturePacket from './one_pass_signature'; import SignaturePacket from './signature'; +import PacketList from './packetlist'; // A Compressed Data packet can contain the following packet types const allowedPackets = /*#__PURE__*/ util.constructAllowedPackets([ @@ -116,6 +117,7 @@ class CompressedDataPacket { throw new Error(this.algorithm + ' decompression not supported'); } + this.packets = new PacketList(); await this.packets.read(decompress_fns[this.algorithm](this.compressed), allowedPackets); } diff --git a/src/packet/packetlist.js b/src/packet/packetlist.js index 4c14c5cc2..1be3fa697 100644 --- a/src/packet/packetlist.js +++ b/src/packet/packetlist.js @@ -126,21 +126,6 @@ class PacketList extends Array { return util.concat(arr); } - /** - * Adds a packet to the list. This is the only supported method of doing so; - * writing to packetlist[i] directly will result in an error. - * @param {Object} packet - Packet to push - * @returns {Integer} length of resulting packetlist - */ - push(packet) { - if (!packet) { - return this.length; - } - - packet.packets = packet.packets || new PacketList(); - return super.push(packet); - } - /** * Creates a new PacketList with all packets matching the given tag(s) * @param {...module:enums.packet} tags - packet tags to look for @@ -187,18 +172,6 @@ class PacketList extends Array { } return tagIndex; } - - /** - * Append packetlist or array of packets, in place - * @param {PacketList|Array} packets - packets to append - */ - append(packetlist) { - if (packetlist) { - for (let i = 0; i < packetlist.length; i++) { - this.push(packetlist[i]); - } - } - } } export default PacketList; diff --git a/src/packet/sym_encrypted_integrity_protected_data.js b/src/packet/sym_encrypted_integrity_protected_data.js index 15deffbcf..d49e1642d 100644 --- a/src/packet/sym_encrypted_integrity_protected_data.js +++ b/src/packet/sym_encrypted_integrity_protected_data.js @@ -25,6 +25,7 @@ import LiteralDataPacket from './literal_data'; import CompressedDataPacket from './compressed_data'; import OnePassSignaturePacket from './one_pass_signature'; import SignaturePacket from './signature'; +import PacketList from './packetlist'; // A SEIP packet can contain the following packet types const allowedPackets = /*#__PURE__*/ util.constructAllowedPackets([ @@ -53,15 +54,7 @@ class SymEncryptedIntegrityProtectedDataPacket { constructor() { this.version = VERSION; - /** The encrypted payload. */ - this.encrypted = null; // string - /** - * If after decrypting the packet this is set to true, - * a modification has been detected and thus the contents - * should be discarded. - * @type {Boolean} - */ - this.modification = false; + this.encrypted = null; this.packets = null; } @@ -138,6 +131,7 @@ class SymEncryptedIntegrityProtectedDataPacket { if (!util.isStream(encrypted) || !config.allowUnauthenticatedStream) { packetbytes = await stream.readToEnd(packetbytes); } + this.packets = new PacketList(); await this.packets.read(packetbytes, allowedPackets); return true; } diff --git a/src/packet/symmetrically_encrypted_data.js b/src/packet/symmetrically_encrypted_data.js index b532a3465..e7711e781 100644 --- a/src/packet/symmetrically_encrypted_data.js +++ b/src/packet/symmetrically_encrypted_data.js @@ -25,6 +25,7 @@ import LiteralDataPacket from './literal_data'; import CompressedDataPacket from './compressed_data'; import OnePassSignaturePacket from './one_pass_signature'; import SignaturePacket from './signature'; +import PacketList from './packetlist'; // A SE packet can contain the following packet types const allowedPackets = /*#__PURE__*/ util.constructAllowedPackets([ @@ -91,6 +92,7 @@ class SymmetricallyEncryptedDataPacket { encrypted.subarray(2, crypto.cipher[sessionKeyAlgorithm].blockSize + 2) ); + this.packets = new PacketList(); await this.packets.read(decrypted, allowedPackets); } diff --git a/test/general/openpgp.js b/test/general/openpgp.js index bb2900350..2c2e2e01a 100644 --- a/test/general/openpgp.js +++ b/test/general/openpgp.js @@ -2665,7 +2665,7 @@ module.exports = () => describe('OpenPGP.js public api tests', function() { }; return openpgp.sign(signOpt).then(async function (signed) { const message = await openpgp.readMessage({ binaryMessage: signed }); - message.packets.append(await openpgp.stream.readToEnd(message.packets.stream, _ => _)); + message.packets.push(...await openpgp.stream.readToEnd(message.packets.stream, _ => _)); const packets = new openpgp.PacketList(); packets.push(message.packets.findPacket(openpgp.enums.packet.signature)); packets.push(message.packets.findPacket(openpgp.enums.packet.literalData)); @@ -2705,7 +2705,7 @@ module.exports = () => describe('OpenPGP.js public api tests', function() { return openpgp.sign(signOpt).then(async function (signed) { expect(openpgp.stream.isStream(signed)).to.equal(global.ReadableStream ? 'web' : 'node'); const message = await openpgp.readMessage({ binaryMessage: signed }); - message.packets.append(await openpgp.stream.readToEnd(message.packets.stream, _ => _)); + message.packets.push(...await openpgp.stream.readToEnd(message.packets.stream, _ => _)); const packets = new openpgp.PacketList(); packets.push(message.packets.findPacket(openpgp.enums.packet.signature)); packets.push(message.packets.findPacket(openpgp.enums.packet.literalData)); diff --git a/test/general/packet.js b/test/general/packet.js index 181fa95c2..b9fc4e0d1 100644 --- a/test/general/packet.js +++ b/test/general/packet.js @@ -10,6 +10,7 @@ chai.use(require('chai-as-promised')); const { expect } = chai; const input = require('./testInputs.js'); +const { PacketList } = require('../../src/packet'); function stringify(array) { if (openpgp.stream.isStream(array)) { @@ -81,8 +82,9 @@ module.exports = () => describe("Packet", function() { try { const enc = new openpgp.SymmetricallyEncryptedDataPacket(); - message.push(enc); + enc.packets = new openpgp.PacketList(); enc.packets.push(literal); + message.push(enc); 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'; @@ -112,8 +114,9 @@ module.exports = () => describe("Packet", function() { literal.setText(testText); const enc = new openpgp.SymmetricallyEncryptedDataPacket(); + enc.packets = new openpgp.PacketList(); + enc.packets.push(literal); message.push(enc); - await enc.packets.push(literal); 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'; @@ -135,11 +138,12 @@ module.exports = () => describe("Packet", function() { const literal = new openpgp.LiteralDataPacket(); const enc = new openpgp.SymEncryptedIntegrityProtectedDataPacket(); + enc.packets = new openpgp.PacketList(); + enc.packets.push(literal); const msg = new openpgp.PacketList(); - msg.push(enc); + literal.setText(testText); - enc.packets.push(literal); await enc.encrypt(algo, key, undefined, openpgp.config); const msg2 = new openpgp.PacketList(); @@ -158,12 +162,12 @@ module.exports = () => describe("Packet", function() { const algo = 'aes256'; const testText = input.createSomeMessage(); const literal = new openpgp.LiteralDataPacket(); + literal.setText(testText); const enc = new openpgp.AEADEncryptedDataPacket(); + enc.packets = new openpgp.PacketList(); + enc.packets.push(literal); const msg = new openpgp.PacketList(); - msg.push(enc); - literal.setText(testText); - enc.packets.push(literal); const msg2 = new openpgp.PacketList(); @@ -210,13 +214,13 @@ module.exports = () => describe("Packet", function() { const algo = 'aes256'; const literal = new openpgp.LiteralDataPacket(); + literal.setText(testText); const enc = new openpgp.AEADEncryptedDataPacket(); - const msg = new openpgp.PacketList(); enc.aeadAlgorithm = 'experimentalGCM'; - - msg.push(enc); - literal.setText(testText); + enc.packets = new openpgp.PacketList(); enc.packets.push(literal); + const msg = new openpgp.PacketList(); + msg.push(enc); const msg2 = new openpgp.PacketList(); @@ -252,13 +256,13 @@ module.exports = () => describe("Packet", function() { const algo = 'aes128'; const literal = new openpgp.LiteralDataPacket(0); - const enc = new openpgp.AEADEncryptedDataPacket(); - const msg = new openpgp.PacketList(); - - msg.push(enc); literal.setBytes(util.stringToUint8Array('Hello, world!\n'), openpgp.enums.literal.binary); literal.filename = ''; + const enc = new openpgp.AEADEncryptedDataPacket(); + enc.packets = new openpgp.PacketList(); enc.packets.push(literal); + const msg = new openpgp.PacketList(); + msg.push(enc); const msg2 = new openpgp.PacketList(); @@ -446,8 +450,11 @@ module.exports = () => describe("Packet", function() { const testText = input.createSomeMessage(); const literal = new openpgp.LiteralDataPacket(); + literal.setText(testText); const skesk = new openpgp.SymEncryptedSessionKeyPacket(); const seip = new openpgp.SymEncryptedIntegrityProtectedDataPacket(); + seip.packets = new openpgp.PacketList(); + seip.packets.push(literal); const msg = new openpgp.PacketList(); msg.push(skesk); @@ -457,9 +464,6 @@ module.exports = () => describe("Packet", function() { await skesk.encrypt(passphrase, openpgp.config); const key = skesk.sessionKey; - - literal.setText(testText); - seip.packets.push(literal); await seip.encrypt(algo, key, undefined, openpgp.config); const msg2 = new openpgp.PacketList(); @@ -485,10 +489,12 @@ module.exports = () => describe("Packet", function() { const testText = input.createSomeMessage(); const literal = new openpgp.LiteralDataPacket(); + literal.setText(testText); const skesk = new openpgp.SymEncryptedSessionKeyPacket(); const aeadEnc = new openpgp.AEADEncryptedDataPacket(); + aeadEnc.packets = new openpgp.PacketList(); + aeadEnc.packets.push(literal); const msg = new openpgp.PacketList(); - msg.push(skesk); msg.push(aeadEnc); @@ -496,9 +502,6 @@ module.exports = () => describe("Packet", function() { await skesk.encrypt(passphrase, openpgp.config); const key = skesk.sessionKey; - - literal.setText(testText); - aeadEnc.packets.push(literal); await aeadEnc.encrypt(algo, key, undefined, openpgp.config); const msg2 = new openpgp.PacketList(); @@ -556,21 +559,20 @@ module.exports = () => describe("Packet", function() { const algo = 'aes128'; const literal = new openpgp.LiteralDataPacket(0); + literal.setBytes(util.stringToUint8Array('Hello, world!\n'), openpgp.enums.literal.binary); + literal.filename = ''; const skesk = new openpgp.SymEncryptedSessionKeyPacket(); + skesk.sessionKeyAlgorithm = algo; const encData = new openpgp.AEADEncryptedDataPacket(); + encData.packets = new openpgp.PacketList(); + encData.packets.push(literal); const msg = new openpgp.PacketList(); - msg.push(skesk); msg.push(encData); - skesk.sessionKeyAlgorithm = algo; await skesk.encrypt(passphrase, openpgp.config); const key = skesk.sessionKey; - - literal.setBytes(util.stringToUint8Array('Hello, world!\n'), openpgp.enums.literal.binary); - literal.filename = ''; - encData.packets.push(literal); await encData.encrypt(algo, key, undefined, openpgp.config); const data = msg.write(); @@ -634,22 +636,21 @@ module.exports = () => describe("Packet", function() { const algo = 'aes128'; const literal = new openpgp.LiteralDataPacket(0); + literal.setBytes(util.stringToUint8Array('Hello, world!\n'), openpgp.enums.literal.binary); + literal.filename = ''; const key_enc = new openpgp.SymEncryptedSessionKeyPacket(); + key_enc.sessionKeyAlgorithm = algo; const enc = new openpgp.AEADEncryptedDataPacket(); - const msg = new openpgp.PacketList(); + enc.packets = new openpgp.PacketList(); + enc.packets.push(literal); enc.aeadAlgorithm = key_enc.aeadAlgorithm = 'ocb'; - + const msg = new openpgp.PacketList(); msg.push(key_enc); msg.push(enc); - key_enc.sessionKeyAlgorithm = algo; await key_enc.encrypt(passphrase, openpgp.config); const key = key_enc.sessionKey; - - literal.setBytes(util.stringToUint8Array('Hello, world!\n'), openpgp.enums.literal.binary); - literal.filename = ''; - enc.packets.push(literal); await enc.encrypt(algo, key, undefined, openpgp.config); const data = msg.write(); @@ -747,7 +748,7 @@ module.exports = () => describe("Packet", function() { await encData.decrypt(pkesk.sessionKeyAlgorithm, pkesk.sessionKey); const payload = encData.packets[0].packets; - payload.append(await openpgp.stream.readToEnd(payload.stream, arr => arr)); + payload.push(...await openpgp.stream.readToEnd(payload.stream, arr => arr)); const literal = payload[1]; const signature = payload[2]; @@ -942,7 +943,7 @@ V+HOQJQxXJkVRYa3QrFUehiMzTeqqMdgC6ZqJy7+ const signed2 = new openpgp.PacketList(); await signed2.read(raw, allAllowedPackets); - signed2.append(await openpgp.stream.readToEnd(signed2.stream, arr => arr)); + signed2.push(...await openpgp.stream.readToEnd(signed2.stream, arr => arr)); await Promise.all([ signed2[1].verify(key, openpgp.enums.signature.text, signed2[0]), diff --git a/test/security/subkey_trust.js b/test/security/subkey_trust.js index d532d9ba1..d32a378a1 100644 --- a/test/security/subkey_trust.js +++ b/test/security/subkey_trust.js @@ -56,7 +56,7 @@ async function testSubkeyTrust() { fakeBindingSignature.keyFlags = [enums.keyFlags.signData]; await fakeBindingSignature.sign(attackerPrivKey.keyPacket, dataToSign); const newList = new PacketList(); - newList.append([ + newList.push(...[ pktPrivAttacker[0], // attacker private key pktPrivAttacker[1], // attacker user pktPrivAttacker[2], // attacker self signature diff --git a/test/security/unsigned_subpackets.js b/test/security/unsigned_subpackets.js index f63bc7aa0..66c091433 100644 --- a/test/security/unsigned_subpackets.js +++ b/test/security/unsigned_subpackets.js @@ -81,7 +81,7 @@ async function makeKeyValid() { pusersig.readSubPackets(fake.writeHashedSubPackets(), false); // reconstruct the modified key const newlist = new PacketList(); - newlist.append([pubkey, puser, pusersig]); + newlist.push(...[pubkey, puser, pusersig]); let modifiedkey = new Key(newlist); // re-read the message to eliminate any // behaviour due to cached values. diff --git a/test/typescript/definitions.ts b/test/typescript/definitions.ts index edd527225..711a1dc04 100644 --- a/test/typescript/definitions.ts +++ b/test/typescript/definitions.ts @@ -93,9 +93,9 @@ import { generateKey, readKey, readKeys, Key, readMessage, createMessage, Messag literalPackets.push(new LiteralDataPacket()); literalPackets[0].write(); literalPackets.map((packet: LiteralDataPacket) => packet); - packets.append(literalPackets); + packets.push(...literalPackets); // @ts-expect-error for incompatible packetlist type - literalPackets.append(packets); + literalPackets.push(...packets); // @ts-expect-error for incompatible packet type new PacketList().push(new CompressedDataPacket()); From 9c402b8f655995d36f9ebacd67a150c62202db4c Mon Sep 17 00:00:00 2001 From: larabr <7375870+larabr@users.noreply.github.com> Date: Thu, 29 Apr 2021 16:44:53 +0200 Subject: [PATCH 7/8] Fix linting error --- test/general/packet.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/general/packet.js b/test/general/packet.js index b9fc4e0d1..187bf1346 100644 --- a/test/general/packet.js +++ b/test/general/packet.js @@ -10,7 +10,6 @@ chai.use(require('chai-as-promised')); const { expect } = chai; const input = require('./testInputs.js'); -const { PacketList } = require('../../src/packet'); function stringify(array) { if (openpgp.stream.isStream(array)) { From c8ca609c92db3e58f3537b1b156105ff8436744c Mon Sep 17 00:00:00 2001 From: larabr <7375870+larabr@users.noreply.github.com> Date: Thu, 29 Apr 2021 16:58:58 +0200 Subject: [PATCH 8/8] Prevent TS from accepting key packets when expecting subkey ones, and vice versa --- openpgp.d.ts | 8 ++++++++ test/typescript/definitions.ts | 11 ++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/openpgp.d.ts b/openpgp.d.ts index e15826e27..7b8101076 100644 --- a/openpgp.d.ts +++ b/openpgp.d.ts @@ -316,14 +316,20 @@ declare abstract class BasePublicKeyPacket extends BasePacket { public getKeyID(): KeyID; public isDecrypted(): boolean; public publicParams: object; + // `isSubkey` is a dummy method to ensure that Subkey packets are not accepted as Key one, and vice versa. + // The key class hierarchy is already modelled to cover this, but the concrete key packet classes + // have compatible structure and TS can't detect the difference. + protected isSubkey(): boolean; } export class PublicKeyPacket extends BasePublicKeyPacket { static readonly tag: enums.packet.publicKey; + protected isSubkey(): false; } export class PublicSubkeyPacket extends BasePublicKeyPacket { static readonly tag: enums.packet.publicSubkey; + protected isSubkey(): true; } declare abstract class BaseSecretKeyPacket extends BasePublicKeyPacket { @@ -337,10 +343,12 @@ declare abstract class BaseSecretKeyPacket extends BasePublicKeyPacket { export class SecretKeyPacket extends BaseSecretKeyPacket { static readonly tag: enums.packet.secretKey; + protected isSubkey(): false; } export class SecretSubkeyPacket extends BaseSecretKeyPacket { static readonly tag: enums.packet.secretSubkey; + protected isSubkey(): true; } export class CompressedDataPacket extends BasePacket { diff --git a/test/typescript/definitions.ts b/test/typescript/definitions.ts index 711a1dc04..4e9f42b9d 100644 --- a/test/typescript/definitions.ts +++ b/test/typescript/definitions.ts @@ -7,7 +7,12 @@ */ import { expect } from 'chai'; -import { generateKey, readKey, readKeys, Key, readMessage, createMessage, Message, createCleartextMessage, encrypt, decrypt, sign, verify, config, enums, LiteralDataPacket, PacketList, CompressedDataPacket } from '../..'; +import { + generateKey, readKey, readKeys, Key, + readMessage, createMessage, Message, createCleartextMessage, + encrypt, decrypt, sign, verify, config, enums, + LiteralDataPacket, PacketList, CompressedDataPacket, PublicKeyPacket, PublicSubkeyPacket, SecretKeyPacket, SecretSubkeyPacket +} from '../..'; (async () => { @@ -98,6 +103,10 @@ import { generateKey, readKey, readKeys, Key, readMessage, createMessage, Messag literalPackets.push(...packets); // @ts-expect-error for incompatible packet type new PacketList().push(new CompressedDataPacket()); + // @ts-expect-error for incompatible packet type + new PacketList().push(new PublicSubkeyPacket()); + // @ts-expect-error for incompatible packet type + new PacketList().push(new SecretSubkeyPacket()); expect(LiteralDataPacket.tag).to.equal(enums.packet.literalData);