Don't hang when signature packet corresponding to one-pass sig is missing
This commit is contained in:
parent
150222bee5
commit
3751731330
|
@ -545,7 +545,7 @@ Message.prototype.verify = async function(keys, date=new Date(), streaming) {
|
||||||
if (literalDataList.length !== 1) {
|
if (literalDataList.length !== 1) {
|
||||||
throw new Error('Can only verify message with one literal data packet.');
|
throw new Error('Can only verify message with one literal data packet.');
|
||||||
}
|
}
|
||||||
const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature);
|
const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature).reverse();
|
||||||
const signatureList = msg.packets.filterByTag(enums.packet.signature);
|
const signatureList = msg.packets.filterByTag(enums.packet.signature);
|
||||||
if (onePassSigList.length && !signatureList.length && msg.packets.stream) {
|
if (onePassSigList.length && !signatureList.length && msg.packets.stream) {
|
||||||
onePassSigList.forEach(onePassSig => {
|
onePassSigList.forEach(onePassSig => {
|
||||||
|
@ -555,25 +555,28 @@ Message.prototype.verify = async function(keys, date=new Date(), streaming) {
|
||||||
onePassSig.signatureData = stream.fromAsync(async () => (await onePassSig.correspondingSig).signatureData);
|
onePassSig.signatureData = stream.fromAsync(async () => (await onePassSig.correspondingSig).signatureData);
|
||||||
onePassSig.hashed = onePassSig.hash(literalDataList[0], undefined, streaming);
|
onePassSig.hashed = onePassSig.hash(literalDataList[0], undefined, streaming);
|
||||||
});
|
});
|
||||||
const verificationObjects = await createVerificationObjects(onePassSigList, literalDataList, keys, date);
|
|
||||||
msg.packets.stream = stream.transformPair(msg.packets.stream, async (readable, writable) => {
|
msg.packets.stream = stream.transformPair(msg.packets.stream, async (readable, writable) => {
|
||||||
|
const reader = stream.getReader(readable);
|
||||||
const writer = stream.getWriter(writable);
|
const writer = stream.getWriter(writable);
|
||||||
try {
|
try {
|
||||||
await stream.readToEnd(stream.transform(readable, signature => {
|
for (let i = 0; i < onePassSigList.length; i++) {
|
||||||
onePassSigList.pop().correspondingSigResolve(signature);
|
const { value: signature } = await reader.read();
|
||||||
}));
|
onePassSigList[i].correspondingSigResolve(signature);
|
||||||
|
}
|
||||||
|
await reader.readToEnd();
|
||||||
await writer.ready;
|
await writer.ready;
|
||||||
await writer.close();
|
await writer.close();
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
onePassSigList.forEach(onePassSig => {
|
onePassSigList.forEach(onePassSig => {
|
||||||
onePassSig.correspondingSigResolve({
|
onePassSig.correspondingSigResolve({
|
||||||
|
tag: enums.packet.signature,
|
||||||
verify: () => undefined
|
verify: () => undefined
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
await writer.abort(e);
|
await writer.abort(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return verificationObjects.reverse();
|
return createVerificationObjects(onePassSigList, literalDataList, keys, date);
|
||||||
}
|
}
|
||||||
return createVerificationObjects(signatureList, literalDataList, keys, date);
|
return createVerificationObjects(signatureList, literalDataList, keys, date);
|
||||||
};
|
};
|
||||||
|
|
|
@ -142,6 +142,9 @@ OnePassSignature.prototype.calculateTrailer = Signature.prototype.calculateTrail
|
||||||
|
|
||||||
OnePassSignature.prototype.verify = async function() {
|
OnePassSignature.prototype.verify = async function() {
|
||||||
const correspondingSig = await this.correspondingSig;
|
const correspondingSig = await this.correspondingSig;
|
||||||
|
if (!correspondingSig || correspondingSig.tag !== enums.packet.signature) {
|
||||||
|
throw new Error('Corresponding signature packet missing');
|
||||||
|
}
|
||||||
correspondingSig.hashed = this.hashed;
|
correspondingSig.hashed = this.hashed;
|
||||||
return correspondingSig.verify.apply(correspondingSig, arguments);
|
return correspondingSig.verify.apply(correspondingSig, arguments);
|
||||||
};
|
};
|
||||||
|
|
|
@ -600,6 +600,41 @@ yYDnCgA=
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Streaming verify signed message with missing signature packet', async function() {
|
||||||
|
const msg_armor =
|
||||||
|
`-----BEGIN PGP MESSAGE-----
|
||||||
|
Version: OpenPGP.js v3.1.3
|
||||||
|
Comment: https://openpgpjs.org
|
||||||
|
|
||||||
|
yFgBO8LLzMjE+KDlu0uOgs50xtNRJdzFBYnJqcW6JanFJVE3r9eCuVYKvFxg
|
||||||
|
hkJiXopCSWKSlQInL1devkJJUWJmTmZeugJYlpdLAagQJM0JpsCqIQZwKgAA
|
||||||
|
|
||||||
|
=D6TZ
|
||||||
|
-----END PGP MESSAGE-----`.split('');
|
||||||
|
|
||||||
|
const plaintext = 'space: \nspace and tab: \t\nno trailing space\n \ntab:\t\ntab and space:\t ';
|
||||||
|
const sMsg = await openpgp.message.readArmored(new ReadableStream({
|
||||||
|
async pull(controller) {
|
||||||
|
await new Promise(setTimeout);
|
||||||
|
controller.enqueue(msg_armor.shift());
|
||||||
|
if (!msg_armor.length) controller.close();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
const pubKey = (await openpgp.key.readArmored(pub_key_arm2)).keys[0];
|
||||||
|
|
||||||
|
const keyids = sMsg.getSigningKeyIds();
|
||||||
|
|
||||||
|
expect(pubKey.getKeys(keyids[0])).to.not.be.empty;
|
||||||
|
|
||||||
|
return openpgp.verify({ publicKeys:[pubKey], message:sMsg }).then(async function(cleartextSig) {
|
||||||
|
expect(cleartextSig).to.exist;
|
||||||
|
expect(openpgp.util.nativeEOL(openpgp.util.Uint8Array_to_str(await openpgp.stream.readToEnd(cleartextSig.data)))).to.equal(plaintext);
|
||||||
|
expect(cleartextSig.signatures).to.have.length(1);
|
||||||
|
await expect(cleartextSig.signatures[0].verified).to.be.rejectedWith('Corresponding signature packet missing');
|
||||||
|
expect((await cleartextSig.signatures[0].signature).packets.length).to.equal(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Sign text with openpgp.sign and verify with openpgp.verify leads to same string cleartext and valid signatures', async function() {
|
it('Sign text with openpgp.sign and verify with openpgp.verify leads to same string cleartext and valid signatures', async function() {
|
||||||
const plaintext = 'short message\nnext line \n한국어/조선말';
|
const plaintext = 'short message\nnext line \n한국어/조선말';
|
||||||
const pubKey = (await openpgp.key.readArmored(pub_key_arm2)).keys[0];
|
const pubKey = (await openpgp.key.readArmored(pub_key_arm2)).keys[0];
|
||||||
|
|
Loading…
Reference in New Issue
Block a user