Skip to content

Commit

Permalink
Throw on decryption of messages that don't contain any encrypted data…
Browse files Browse the repository at this point in the history
… packet (#1529)

Calling `openpgp.decrypt` with a message that contains encrypted session keys
followed by a non-encrypted packet (e.g. Literal or Compressed Data packet)
used to succeed, even if a wrong passphrase/key was provided.
With this change, the operation will always fail, and the user is warned that
the data was not encrypted.

NB: a message that did not contain any encrypted session key packet would fail
to decrypt even prior to this change.
  • Loading branch information
larabr committed Jun 7, 2022
1 parent ef06618 commit 6c32b62
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 41 deletions.
2 changes: 1 addition & 1 deletion src/message.js
Expand Up @@ -116,7 +116,7 @@ export class Message {
);

if (symEncryptedPacketlist.length === 0) {
return this;
throw new Error('No encrypted data found');
}

const symEncryptedPacket = symEncryptedPacketlist[0];
Expand Down
98 changes: 58 additions & 40 deletions test/general/openpgp.js
Expand Up @@ -3825,22 +3825,27 @@ amnR6g==
});
});

describe('Sign and verify with each curve', function() {
const curves = ['secp256k1' , 'p256', 'p384', 'p521', 'curve25519', 'brainpoolP256r1', 'brainpoolP384r1', 'brainpoolP512r1'];
curves.forEach(curve => {
it(`sign/verify with ${curve}`, async function() {
const config = { rejectCurves: new Set() };
const plaintext = 'short message';
const { privateKey: key } = await openpgp.generateKey({ curve, userIDs: { name: 'Alice', email: 'info@alice.com' }, format: 'object', config });
const signed = await openpgp.sign({ signingKeys:[key], message: await openpgp.createCleartextMessage({ text: plaintext }), config });
const verified = await openpgp.verify({ verificationKeys:[key], message: await openpgp.readCleartextMessage({ cleartextMessage: signed }), config });
expect(await verified.signatures[0].verified).to.be.true;
});
});
it('should fail to decrypt a message containing a literal packet (and no session key)', async function() {
const message = await openpgp.createMessage({ text: 'plaintext' });
await expect(openpgp.decrypt({ message, passwords: 'password' })).to.be.rejectedWith(/Error decrypting message/);
});

it('should fail to decrypt a message containing a literal packet (and a session key)', async function() {
const skeskPlusLiteralData = `-----BEGIN PGP MESSAGE-----
wy4ECQMIjvrInhvTxJwAbkqXp+KWFdBcjoPn03jCdyspVi9qXBDbyGaP1lrM
habAyxd1AGKaNp1wbGFpbnRleHQgbWVzc2FnZQ==
=XoUx
-----END PGP MESSAGE-----
`;

it('should fail to decrypt non-integrity-protected message by default', async function() {
const key = await openpgp.readKey({
armoredKey: `-----BEGIN PGP PRIVATE KEY BLOCK-----
const message = await openpgp.readMessage({ armoredMessage: skeskPlusLiteralData });
await expect(openpgp.decrypt({ message, passwords: 'password' })).to.be.rejectedWith(/No encrypted data found/);
});

it('should fail to decrypt non-integrity-protected message by default', async function() {
const key = await openpgp.readKey({
armoredKey: `-----BEGIN PGP PRIVATE KEY BLOCK-----
xVgEYD9r8xYJKwYBBAHaRw8BAQdApTaQJ6R/uooTqAuscoxYwbLrtoKndnsX
ydhqMybJqh0AAQCxNwi9Pezy03OQE0XOooBWaHiuhBtKA1eAuqjJFuuLuQ/+
Expand All @@ -3855,9 +3860,9 @@ ESqhlK5rrbc62SmfAQDVf5l1B6IDASBCKtC0VPPpYiK6AUcEISpaSXOa+pNI
Bw==
=3Fja
-----END PGP PRIVATE KEY BLOCK-----`
});
const message = await openpgp.readMessage({
armoredMessage: `-----BEGIN PGP MESSAGE-----
});
const message = await openpgp.readMessage({
armoredMessage: `-----BEGIN PGP MESSAGE-----
wV4D+3VwOibHmagSAQdATlMJlvrkaq46zMkbIuKBOJO5X3ugVwZpEyAterQC
/RUw0OPWeO+4swh/U7ZurV8cRr/fPnyGUUKI7rI+va3kWUZv4RRpUs7eYE57
Expand All @@ -3867,15 +3872,15 @@ rWwIiEQEBPt+tXOuVF4Peumovp3WgziudrJa5Jxt2Dz+8nicBglbZLXTsZNu
bsZgJWVlAa5eil6J9ePX2xbo1vVAkLQdzE9+1jL+l7PRIZuVBQ==
=T4iR
-----END PGP MESSAGE-----`
});
await expect(
openpgp.decrypt({ message, decryptionKeys: key, verificationKeys: key })
).to.be.rejectedWith('Error decrypting message: Message is not authenticated.');
});
await expect(
openpgp.decrypt({ message, decryptionKeys: key, verificationKeys: key })
).to.be.rejectedWith('Error decrypting message: Message is not authenticated.');
});

it('should allow decrypting non-integrity-protected message when enabled', async function() {
const key = await openpgp.readKey({
armoredKey: `-----BEGIN PGP PRIVATE KEY BLOCK-----
it('should allow decrypting non-integrity-protected message when enabled', async function() {
const key = await openpgp.readKey({
armoredKey: `-----BEGIN PGP PRIVATE KEY BLOCK-----
xVgEYD9r8xYJKwYBBAHaRw8BAQdApTaQJ6R/uooTqAuscoxYwbLrtoKndnsX
ydhqMybJqh0AAQCxNwi9Pezy03OQE0XOooBWaHiuhBtKA1eAuqjJFuuLuQ/+
Expand All @@ -3890,9 +3895,9 @@ ESqhlK5rrbc62SmfAQDVf5l1B6IDASBCKtC0VPPpYiK6AUcEISpaSXOa+pNI
Bw==
=3Fja
-----END PGP PRIVATE KEY BLOCK-----`
});
const message = await openpgp.readMessage({
armoredMessage: `-----BEGIN PGP MESSAGE-----
});
const message = await openpgp.readMessage({
armoredMessage: `-----BEGIN PGP MESSAGE-----
wV4D+3VwOibHmagSAQdATlMJlvrkaq46zMkbIuKBOJO5X3ugVwZpEyAterQC
/RUw0OPWeO+4swh/U7ZurV8cRr/fPnyGUUKI7rI+va3kWUZv4RRpUs7eYE57
Expand All @@ -3902,14 +3907,14 @@ rWwIiEQEBPt+tXOuVF4Peumovp3WgziudrJa5Jxt2Dz+8nicBglbZLXTsZNu
bsZgJWVlAa5eil6J9ePX2xbo1vVAkLQdzE9+1jL+l7PRIZuVBQ==
=T4iR
-----END PGP MESSAGE-----`
});
const decrypted = await openpgp.decrypt({ message, decryptionKeys: key, verificationKeys: key, config: { allowUnauthenticatedMessages: true } });
expect(decrypted.data).to.equal('test');
});
const decrypted = await openpgp.decrypt({ message, decryptionKeys: key, verificationKeys: key, config: { allowUnauthenticatedMessages: true } });
expect(decrypted.data).to.equal('test');
});

it('should allow stream-decrypting non-integrity-protected message when enabled', async function() {
const key = await openpgp.readKey({
armoredKey: `-----BEGIN PGP PRIVATE KEY BLOCK-----
it('should allow stream-decrypting non-integrity-protected message when enabled', async function() {
const key = await openpgp.readKey({
armoredKey: `-----BEGIN PGP PRIVATE KEY BLOCK-----
xVgEYD9r8xYJKwYBBAHaRw8BAQdApTaQJ6R/uooTqAuscoxYwbLrtoKndnsX
ydhqMybJqh0AAQCxNwi9Pezy03OQE0XOooBWaHiuhBtKA1eAuqjJFuuLuQ/+
Expand All @@ -3924,9 +3929,9 @@ ESqhlK5rrbc62SmfAQDVf5l1B6IDASBCKtC0VPPpYiK6AUcEISpaSXOa+pNI
Bw==
=3Fja
-----END PGP PRIVATE KEY BLOCK-----`
});
const message = await openpgp.readMessage({
armoredMessage: stream.toStream(`-----BEGIN PGP MESSAGE-----
});
const message = await openpgp.readMessage({
armoredMessage: stream.toStream(`-----BEGIN PGP MESSAGE-----
wV4D+3VwOibHmagSAQdATlMJlvrkaq46zMkbIuKBOJO5X3ugVwZpEyAterQC
/RUw0OPWeO+4swh/U7ZurV8cRr/fPnyGUUKI7rI+va3kWUZv4RRpUs7eYE57
Expand All @@ -3936,10 +3941,23 @@ rWwIiEQEBPt+tXOuVF4Peumovp3WgziudrJa5Jxt2Dz+8nicBglbZLXTsZNu
bsZgJWVlAa5eil6J9ePX2xbo1vVAkLQdzE9+1jL+l7PRIZuVBQ==
=T4iR
-----END PGP MESSAGE-----`)
});
const decrypted = await openpgp.decrypt({ message, decryptionKeys: key, verificationKeys: key, config: { allowUnauthenticatedMessages: true } });
const data = await stream.readToEnd(decrypted.data);
expect(data).to.equal('test');
});

describe('Sign and verify with each curve', function() {
const curves = ['secp256k1' , 'p256', 'p384', 'p521', 'curve25519', 'brainpoolP256r1', 'brainpoolP384r1', 'brainpoolP512r1'];
curves.forEach(curve => {
it(`sign/verify with ${curve}`, async function() {
const config = { rejectCurves: new Set() };
const plaintext = 'short message';
const { privateKey: key } = await openpgp.generateKey({ curve, userIDs: { name: 'Alice', email: 'info@alice.com' }, format: 'object', config });
const signed = await openpgp.sign({ signingKeys:[key], message: await openpgp.createCleartextMessage({ text: plaintext }), config });
const verified = await openpgp.verify({ verificationKeys:[key], message: await openpgp.readCleartextMessage({ cleartextMessage: signed }), config });
expect(await verified.signatures[0].verified).to.be.true;
});
const decrypted = await openpgp.decrypt({ message, decryptionKeys: key, verificationKeys: key, config: { allowUnauthenticatedMessages: true } });
const data = await stream.readToEnd(decrypted.data);
expect(data).to.equal('test');
});
});

Expand Down

0 comments on commit 6c32b62

Please sign in to comment.