Add PacketList.fromBinary and add missing config param in some functions (#1294)

- Add `PacketList.fromBinary` which parses binary data and returns a
  `PacketList`. Using it instead of `PacketList.read` avoids being left
  with partially read data in case of errors.
- Rename `toPacketlist` to `toPacketList` in `Key`, `Subkey` and `User`
  classes
- In `readMessage`, pass down `config` to `PacketList.read`
- Add `config` param to `CompressedDataPacket.decompress`,
  `AEADEncryptedDataPacket.decrypt` and `Message.appendSignature`
This commit is contained in:
larabr 2021-05-05 16:56:11 +02:00 committed by GitHub
parent aeddac438e
commit 247ad58344
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 161 additions and 73 deletions

12
openpgp.d.ts vendored
View File

@ -257,7 +257,7 @@ export class Message<T extends MaybeStream<Data>> {
* Append signature to unencrypted message object
* @param {String|Uint8Array} detachedSignature - The detached ASCII-armored or Uint8Array PGP signature
*/
public appendSignature(detachedSignature: string | Uint8Array): Promise<void>;
public appendSignature(detachedSignature: string | Uint8Array, config?: Config): Promise<void>;
}
@ -352,7 +352,7 @@ export class SecretSubkeyPacket extends BaseSecretKeyPacket {
export class CompressedDataPacket extends BasePacket {
static readonly tag: enums.packet.compressedData;
private compress(): void;
private decompress(): void;
private decompress(config?: Config): void;
}
export class SymEncryptedIntegrityProtectedDataPacket extends BasePacket {
@ -361,7 +361,7 @@ export class SymEncryptedIntegrityProtectedDataPacket extends BasePacket {
export class AEADEncryptedDataPacket extends BasePacket {
static readonly tag: enums.packet.aeadEncryptedData;
private decrypt(sessionKeyAlgorithm: string, sessionKey: Uint8Array): void;
private decrypt(sessionKeyAlgorithm: string, sessionKey: Uint8Array, config?: Config): void;
private encrypt(sessionKeyAlgorithm: string, sessionKey: Uint8Array, config?: Config): void;
private crypt(fn: Function, sessionKey: Uint8Array, data: MaybeStream<Uint8Array>): MaybeStream<Uint8Array>
}
@ -480,10 +480,10 @@ export type AnyKeyPacket = BasePublicKeyPacket;
type DataPacketType = 'utf8' | 'binary' | 'text' | 'mime';
type AllowedPackets = Map<enums.packet, object>; // mapping to Packet classes (i.e. typeof LiteralDataPacket etc.)
export class PacketList<T extends AnyPacket> extends Array<T> {
public length: number;
public read(bytes: Uint8Array, allowedPackets?: object, config?: Config): void;
static fromBinary(bytes: MaybeStream<Uint8Array>, allowedPackets: AllowedPackets, config?: Config): PacketList<AnyPacket>; // the packet types depend on`allowedPackets`
public read(bytes: MaybeStream<Uint8Array>, allowedPackets: AllowedPackets, config?: Config): void;
public write(): Uint8Array;
public filterByTag(...args: enums.packet[]): PacketList<T>;
public indexOfTag(...tags: enums.packet[]): number[];

View File

@ -144,8 +144,7 @@ export async function readCleartextMessage({ cleartextMessage, config }) {
if (input.type !== enums.armor.signed) {
throw new Error('No cleartext signed message.');
}
const packetlist = new PacketList();
await packetlist.read(input.data, allowedPackets, undefined, config);
const packetlist = await PacketList.fromBinary(input.data, allowedPackets, config);
verifyHeaders(input.headers, packetlist);
const signature = new Signature(packetlist);
return new CleartextMessage(input.text, signature);

View File

@ -150,7 +150,6 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, conf
}));
const packetlist = new PacketList();
packetlist.push(secretKeyPacket);
await Promise.all(options.userIDs.map(async function(userID, index) {
@ -281,8 +280,7 @@ export async function readKey({ armoredKey, binaryKey, config }) {
} else {
input = binaryKey;
}
const packetlist = new PacketList();
await packetlist.read(input, allowedKeyPackets, undefined, config);
const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config);
return new Key(packetlist);
}
@ -316,8 +314,7 @@ export async function readKeys({ armoredKeys, binaryKeys, config }) {
input = data;
}
const keys = [];
const packetlist = new PacketList();
await packetlist.read(input, allowedKeyPackets, undefined, config);
const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config);
const keyIndex = packetlist.indexOfTag(enums.packet.publicKey, enums.packet.secretKey);
if (keyIndex.length === 0) {
throw new Error('No key packet found');

View File

@ -147,13 +147,13 @@ class Key {
* Transforms structured key data to packetlist
* @returns {PacketList} The packets that form a key.
*/
toPacketlist() {
toPacketList() {
const packetlist = new PacketList();
packetlist.push(this.keyPacket);
packetlist.push(...this.revocationSignatures);
packetlist.push(...this.directSignatures);
this.users.map(user => packetlist.push(...user.toPacketlist()));
this.subKeys.map(subKey => packetlist.push(...subKey.toPacketlist()));
this.users.map(user => packetlist.push(...user.toPacketList()));
this.subKeys.map(subKey => packetlist.push(...subKey.toPacketList()));
return packetlist;
}
@ -164,7 +164,7 @@ class Key {
* @async
*/
async clone(deep = false) {
const key = new Key(this.toPacketlist());
const key = new Key(this.toPacketList());
if (deep) {
key.getKeys().forEach(k => {
// shallow clone the key packets
@ -255,7 +255,7 @@ class Key {
*/
toPublic() {
const packetlist = new PacketList();
const keyPackets = this.toPacketlist();
const keyPackets = this.toPacketList();
let bytes;
let pubKeyPacket;
let pubSubkeyPacket;
@ -285,7 +285,7 @@ class Key {
* @returns {Uint8Array} Binary key.
*/
write() {
return this.toPacketlist().write();
return this.toPacketList().write();
}
/**
@ -295,7 +295,7 @@ class Key {
*/
armor(config = defaultConfig) {
const type = this.isPublic() ? enums.armor.publicKey : enums.armor.privateKey;
return armor(type, this.toPacketlist().write(), undefined, undefined, undefined, config);
return armor(type, this.toPacketList().write(), undefined, undefined, undefined, config);
}
/**
@ -755,8 +755,7 @@ class Key {
*/
async applyRevocationCertificate(revocationCertificate, config = defaultConfig) {
const input = await unarmor(revocationCertificate, config);
const packetlist = new PacketList();
await packetlist.read(input.data, allowedRevocationPackets, undefined, config);
const packetlist = await PacketList.fromBinary(input.data, allowedRevocationPackets, config);
const revocationSignature = packetlist.findPacket(enums.packet.signature);
if (!revocationSignature || revocationSignature.signatureType !== enums.signature.keyRevocation) {
throw new Error('Could not find revocation signature packet');
@ -900,9 +899,8 @@ class Key {
options = helper.sanitizeKeyOptions(options, defaultOptions);
const keyPacket = await helper.generateSecretSubkey(options);
const bindingSignature = await helper.createBindingSignature(keyPacket, secretKeyPacket, options, config);
const packetList = this.toPacketlist();
packetList.push(keyPacket);
packetList.push(bindingSignature);
const packetList = this.toPacketList();
packetList.push(keyPacket, bindingSignature);
return new Key(packetList);
}
}

View File

@ -31,7 +31,7 @@ class SubKey {
* Transforms structured subkey data to packetlist
* @returns {PacketList}
*/
toPacketlist() {
toPacketList() {
const packetlist = new PacketList();
packetlist.push(this.keyPacket);
packetlist.push(...this.revocationSignatures);

View File

@ -27,7 +27,7 @@ class User {
* Transforms structured user data to packetlist
* @returns {PacketList}
*/
toPacketlist() {
toPacketList() {
const packetlist = new PacketList();
packetlist.push(this.userID || this.userAttribute);
packetlist.push(...this.revocationSignatures);

View File

@ -176,8 +176,7 @@ export class Message {
await Promise.all(passwords.map(async function(password, i) {
let packets;
if (i) {
packets = new PacketList();
await packets.read(symESKeyPacketlist.write(), allowedSymSessionKeyPackets);
packets = await PacketList.fromBinary(symESKeyPacketlist.write(), allowedSymSessionKeyPackets, config);
} else {
packets = symESKeyPacketlist;
}
@ -524,12 +523,12 @@ export class Message {
* @returns {Promise<Signature>} New detached signature of message content.
* @async
*/
async signDetached(privateKeys = [], signature = null, signingKeyIds = [], date = new Date(), userIDs = [], config = defaultConfig) {
async signDetached(privateKeys = [], signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) {
const literalDataPacket = this.packets.findPacket(enums.packet.literalData);
if (!literalDataPacket) {
throw new Error('No literal data packet to sign.');
}
return new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, signingKeyIds, date, userIDs, true, config));
return new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, signingKeyIDs, date, userIDs, true, config));
}
/**
@ -626,11 +625,13 @@ export class Message {
/**
* Append signature to unencrypted message object
* @param {String|Uint8Array} detachedSignature - The detached ASCII-armored or Uint8Array PGP signature
* @param {Object} [config] - Full configuration, defaults to openpgp.config
*/
async appendSignature(detachedSignature) {
async appendSignature(detachedSignature, config = defaultConfig) {
await this.packets.read(
util.isUint8Array(detachedSignature) ? detachedSignature : (await unarmor(detachedSignature)).data,
allowedDetachedSignaturePackets
allowedDetachedSignaturePackets,
config
);
}
@ -826,8 +827,7 @@ export async function readMessage({ armoredMessage, binaryMessage, config }) {
}
input = data;
}
const packetlist = new PacketList();
await packetlist.read(input, allowedMessagePackets, streamType, config);
const packetlist = await PacketList.fromBinary(input, allowedMessagePackets, config);
const message = new Message(packetlist);
message.fromStream = streamType;
return message;

View File

@ -90,12 +90,16 @@ class AEADEncryptedDataPacket {
* 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
* @param {Object} [config] - Full configuration, defaults to openpgp.config
* @throws {Error} if decryption was not successful
* @async
*/
async decrypt(sessionKeyAlgorithm, key) {
this.packets = new PacketList();
await this.packets.read(await this.crypt('decrypt', key, stream.clone(this.encrypted)), allowedPackets);
async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) {
this.packets = await PacketList.fromBinary(
await this.crypt('decrypt', key, stream.clone(this.encrypted)),
allowedPackets,
config
);
}
/**

View File

@ -79,8 +79,9 @@ class CompressedDataPacket {
/**
* Parsing function for the packet.
* @param {Uint8Array | ReadableStream<Uint8Array>} bytes - Payload of a tag 8 packet
* @param {Object} [config] - Full configuration, defaults to openpgp.config
*/
async read(bytes) {
async read(bytes, config = defaultConfig) {
await stream.parse(bytes, async reader => {
// One octet that gives the algorithm used to compress the packet.
@ -89,7 +90,7 @@ class CompressedDataPacket {
// Compressed data, which makes up the remainder of the packet.
this.compressed = reader.remainder();
await this.decompress();
await this.decompress(config);
});
}
@ -110,15 +111,15 @@ class CompressedDataPacket {
/**
* Decompression method for decompressing the compressed data
* read by read_packet
* @param {Object} [config] - Full configuration, defaults to openpgp.config
*/
async decompress() {
async decompress(config = defaultConfig) {
if (!decompress_fns[this.algorithm]) {
throw new Error(this.algorithm + ' decompression not supported');
}
this.packets = new PacketList();
await this.packets.read(decompress_fns[this.algorithm](this.compressed), allowedPackets);
this.packets = await PacketList.fromBinary(decompress_fns[this.algorithm](this.compressed), allowedPackets, config);
}
/**

View File

@ -17,7 +17,7 @@ import defaultConfig from '../config';
*/
export function newPacketFromTag(tag, allowedPackets) {
if (!allowedPackets[tag]) {
throw new Error(`Packet not allowed in this context: ${enums.read(enums.packets, tag)}`);
throw new Error(`Packet not allowed in this context: ${enums.read(enums.packet, tag)}`);
}
return new allowedPackets[tag]();
}
@ -29,9 +29,29 @@ export function newPacketFromTag(tag, allowedPackets) {
* @extends Array
*/
class PacketList extends Array {
/**
* Parses the given binary data and returns a list of packets.
* Equivalent to calling `read` on an empty PacketList instance.
* @param {Uint8Array | ReadableStream<Uint8Array} bytes - binary data to parse
* @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class
* @param {Object} [config] - full configuration, defaults to openpgp.config
* @returns {PacketList} parsed list of packets
* @throws on parsing errors
* @async
*/
static async fromBinary(bytes, allowedPackets, config = defaultConfig) {
const packets = new PacketList();
await packets.read(bytes, allowedPackets, config);
return packets;
}
/**
* Reads a stream of binary data and interprets it as a list of packets.
* @param {Uint8Array | ReadableStream<Uint8Array>} bytes - A Uint8Array of bytes.
* @param {Uint8Array | ReadableStream<Uint8Array>} bytes - binary data to parse
* @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class
* @param {Object} [config] - full configuration, defaults to openpgp.config
* @throws on parsing errors
* @async
*/
async read(bytes, allowedPackets, config = defaultConfig) {
this.stream = stream.transformPair(bytes, async (readable, writable) => {

View File

@ -131,8 +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);
this.packets = await PacketList.fromBinary(packetbytes, allowedPackets, config);
return true;
}
}

View File

@ -92,8 +92,7 @@ class SymmetricallyEncryptedDataPacket {
encrypted.subarray(2, crypto.cipher[sessionKeyAlgorithm].blockSize + 2)
);
this.packets = new PacketList();
await this.packets.read(decrypted, allowedPackets);
this.packets = await PacketList.fromBinary(decrypted, allowedPackets, config);
}
/**

View File

@ -82,7 +82,6 @@ export async function readSignature({ armoredSignature, binarySignature, config
}
input = data;
}
const packetlist = new PacketList();
await packetlist.read(input, allowedPackets, undefined, config);
const packetlist = await PacketList.fromBinary(input, allowedPackets, config);
return new Signature(packetlist);
}

View File

@ -3,6 +3,72 @@ const { expect } = require('chai');
const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp : require('../..');
module.exports = () => describe('Custom configuration', function() {
it('openpgp.readMessage', async function() {
const armoredMessage = await openpgp.encrypt({ message: await openpgp.createMessage({ text:"hello world" }), passwords: 'password' });
const message = await openpgp.readMessage({ armoredMessage });
message.packets.unshift(new openpgp.MarkerPacket()); // MarkerPacket is not allowed in the Message context
const config = { tolerant: true };
const parsedMessage = await openpgp.readMessage({ armoredMessage: message.armor(), config });
expect(parsedMessage.packets.length).to.equal(2);
config.tolerant = false;
await expect(
openpgp.readMessage({ armoredMessage: message.armor(), config })
).to.be.rejectedWith(/Packet not allowed in this context/);
});
it('openpgp.readSignature', async function() {
const armoredSignature = `-----BEGIN PGP SIGNATURE-----
wnUEARYKAAYFAmCPyjwAIQkQk5xMVrwBTN4WIQT7kMrxk1s/unaTxxmTnExW
vAFM3jjrAQDgJPXsv8PqCrLGDuMa/2r6SgzYd03aw/xt1WM6hgUvhQD+J54Z
3KkV9TCnZibYM9OXuIvQpkoIKn4qbyFv7AaSIgs=
=hgTd
-----END PGP SIGNATURE-----`;
const signature = await openpgp.readSignature({ armoredSignature });
signature.packets.unshift(new openpgp.MarkerPacket()); // MarkerPacket is not allowed in the Signature context
const config = { tolerant: true };
const parsedSignature = await openpgp.readSignature({ armoredSignature: signature.armor(), config });
expect(parsedSignature.packets.length).to.equal(1);
config.tolerant = false;
await expect(
openpgp.readSignature({ armoredSignature: signature.armor(), config })
).to.be.rejectedWith(/Packet not allowed in this context/);
});
it('openpgp.readKey', async function() {
const armoredKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
xjMEYI/KsBYJKwYBBAHaRw8BAQdAW2lu0r97hQztwP8+WbSF9N/QJ5hkevhm
CGJbM3HBvznNEHRlc3QgPHRlc3RAYS5pdD7CjAQQFgoAHQUCYI/KsAQLCQcI
AxUICgQWAAIBAhkBAhsDAh4BACEJEKgxHS8jVhd9FiEE8hy8OerCaNGuKPDw
qDEdLyNWF32XOQD/dq2/D394eW67VwUhvRpQl9gwToDf+SixATEFigok5JgA
/3ZeH9eXiZqo3rChfdQ+3VKTd7yoI2gM/pjbHupemYYAzjgEYI/KsBIKKwYB
BAGXVQEFAQEHQN/8mxAaro95FmvPQ4wlAfk3WKUHZtNvpaqzXo1K6WdMAwEI
B8J4BBgWCAAJBQJgj8qwAhsMACEJEKgxHS8jVhd9FiEE8hy8OerCaNGuKPDw
qDEdLyNWF30o6wD/fZYCV8aS4dAu2U3fpN5y5+PbuXFRYljA5gQ/1zrGN/UA
/3r62WsCVupzKdISZYOMPwEY5qN/4f9i6ZWxIynmVX0E
=6+P3
-----END PGP PUBLIC KEY BLOCK-----`;
const keyPackets = (await openpgp.readKey({ armoredKey })).toPacketList();
keyPackets.unshift(new openpgp.MarkerPacket()); // MarkerPacket is not allowed in the Signature context
const config = { tolerant: true };
const parsedKey = await openpgp.readKey({ binaryKey: keyPackets.write(), config });
expect(parsedKey.toPacketList().length).to.equal(5);
config.tolerant = false;
await expect(
openpgp.readKey({ binaryKey: keyPackets.write(), config })
).to.be.rejectedWith(/Packet not allowed in this context/);
});
it('openpgp.generateKey', async function() {
const v5KeysVal = openpgp.config.v5Keys;
const preferredHashAlgorithmVal = openpgp.config.preferredHashAlgorithm;

View File

@ -2763,8 +2763,7 @@ module.exports = () => describe('Key', function() {
43 ee 3b 24 06
`.replace(/\s+/g, ''));
const packetlist = new openpgp.PacketList();
await packetlist.read(packetBytes, util.constructAllowedPackets([openpgp.PublicKeyPacket]), undefined, openpgp.config);
const packetlist = await openpgp.PacketList.fromBinary(packetBytes, util.constructAllowedPackets([openpgp.PublicKeyPacket]), openpgp.config);
const key = packetlist[0];
expect(key).to.exist;
});
@ -2792,12 +2791,9 @@ module.exports = () => describe('Key', function() {
const pubKey = await openpgp.readKey({ armoredKey: pub_sig_test });
expect(pubKey).to.exist;
const packetlist = new openpgp.PacketList();
await packetlist.read(
const packetlist = await openpgp.PacketList.fromBinary(
(await openpgp.unarmor(pub_sig_test)).data,
util.constructAllowedPackets([...Object.values(openpgp).filter(packetClass => !!packetClass.tag)]),
undefined,
openpgp.config
);
@ -3288,8 +3284,7 @@ module.exports = () => describe('Key', function() {
const revocationCertificate = await revKey.getRevocationCertificate();
const input = await openpgp.unarmor(revocation_certificate_arm4);
const packetlist = new openpgp.PacketList();
await packetlist.read(input.data, util.constructAllowedPackets([openpgp.SignaturePacket]), undefined, openpgp.config);
const packetlist = await openpgp.PacketList.fromBinary(input.data, util.constructAllowedPackets([openpgp.SignaturePacket]), openpgp.config);
const armored = openpgp.armor(openpgp.enums.armor.publicKey, packetlist.write());
expect(revocationCertificate.replace(/^Comment: .*$\n/mg, '')).to.equal(armored.replace(/^Comment: .*$\n/mg, ''));

View File

@ -67,6 +67,21 @@ module.exports = () => describe("Packet", function() {
'=KXkj\n' +
'-----END PGP PRIVATE KEY BLOCK-----';
it('Ignores disallowed packet with tolerant mode enabled', async function() {
const packets = new openpgp.PacketList();
packets.push(new openpgp.MarkerPacket());
const bytes = packets.write();
const parsed = await openpgp.PacketList.fromBinary(bytes, {}, { ...openpgp.config, tolerant: true });
expect(parsed.length).to.equal(0);
});
it('Throws on disallowed packet with tolerant mode disabled', async function() {
const packets = new openpgp.PacketList();
packets.push(new openpgp.MarkerPacket());
const bytes = packets.write();
await expect(openpgp.PacketList.fromBinary(bytes, {}, { ...openpgp.config, tolerant: false })).to.be.rejectedWith(/Packet not allowed in this context/);
});
it('Symmetrically encrypted packet without integrity protection - allow decryption', async function() {
const aeadProtectVal = openpgp.config.aeadProtect;
const allowUnauthenticatedMessagesVal = openpgp.config.allowUnauthenticatedMessages;
@ -702,8 +717,7 @@ module.exports = () => describe("Packet", function() {
});
it('Secret key reading with signature verification.', async function() {
const packets = new openpgp.PacketList();
await packets.read((await openpgp.unarmor(armored_key)).data, allAllowedPackets);
const packets = await openpgp.PacketList.fromBinary((await openpgp.unarmor(armored_key)).data, allAllowedPackets);
const [keyPacket, userIDPacket, keySigPacket, subkeyPacket, subkeySigPacket] = packets;
expect(keySigPacket.verified).to.be.null;
expect(subkeySigPacket.verified).to.be.null;
@ -733,8 +747,7 @@ module.exports = () => describe("Packet", function() {
'=htrB\n' +
'-----END PGP MESSAGE-----';
const packets = new openpgp.PacketList();
await packets.read((await openpgp.unarmor(armored_key)).data, allAllowedPackets);
const packets = await openpgp.PacketList.fromBinary((await openpgp.unarmor(armored_key)).data, allAllowedPackets);
const keyPacket = packets[0];
const subkeyPacket = packets[3];
await subkeyPacket.decrypt('test');
@ -849,8 +862,7 @@ V+HOQJQxXJkVRYa3QrFUehiMzTeqqMdgC6ZqJy7+
const raw = new openpgp.PacketList();
raw.push(secretKeyPacket);
const packetList = new openpgp.PacketList();
await packetList.read(raw.write(), allAllowedPackets, undefined, openpgp.config);
const packetList = await openpgp.PacketList.fromBinary(raw.write(), allAllowedPackets, openpgp.config);
const secretKeyPacket2 = packetList[0];
await secretKeyPacket2.decrypt('hello');
@ -906,8 +918,7 @@ V+HOQJQxXJkVRYa3QrFUehiMzTeqqMdgC6ZqJy7+
const raw = new openpgp.PacketList();
raw.push(secretKeyPacket);
const packetList = new openpgp.PacketList();
await packetList.read(raw.write(), allAllowedPackets, undefined, openpgp.config);
const packetList = await openpgp.PacketList.fromBinary(raw.write(), allAllowedPackets, openpgp.config);
const secretKeyPacket2 = packetList[0];
await secretKeyPacket2.decrypt('hello');
});

View File

@ -43,8 +43,8 @@ async function testSubkeyTrust() {
// the victim's public key and a signed message
const { victimPubKey, attackerPrivKey, signed } = await generateTestData();
const pktPubVictim = victimPubKey.toPacketlist();
const pktPrivAttacker = attackerPrivKey.toPacketlist();
const pktPubVictim = victimPubKey.toPacketList();
const pktPrivAttacker = attackerPrivKey.toPacketList();
const dataToSign = {
key: attackerPrivKey.toPublic().keyPacket,
bind: pktPubVictim[3] // victim subkey
@ -56,13 +56,13 @@ async function testSubkeyTrust() {
fakeBindingSignature.keyFlags = [enums.keyFlags.signData];
await fakeBindingSignature.sign(attackerPrivKey.keyPacket, dataToSign);
const newList = new PacketList();
newList.push(...[
newList.push(
pktPrivAttacker[0], // attacker private key
pktPrivAttacker[1], // attacker user
pktPrivAttacker[2], // attacker self signature
pktPubVictim[3], // victim subkey
fakeBindingSignature // faked key binding
]);
);
let fakeKey = new Key(newList);
fakeKey = await readKey({ armoredKey: await fakeKey.toPublic().armor() });
const verifyAttackerIsBatman = await openpgp.verify({

View File

@ -68,7 +68,7 @@ async function makeKeyValid() {
}
const invalidkey = await getInvalidKey();
// deconstruct invalid key
const [pubkey, puser, pusersig] = invalidkey.toPacketlist().map(i => i);
const [pubkey, puser, pusersig] = invalidkey.toPacketList().map(i => i);
// create a fake signature
const fake = new SignaturePacket();
Object.assign(fake, pusersig);
@ -81,7 +81,7 @@ async function makeKeyValid() {
pusersig.readSubPackets(fake.writeHashedSubPackets(), false);
// reconstruct the modified key
const newlist = new PacketList();
newlist.push(...[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.