diff --git a/lib/message/decrypt.js b/lib/message/decrypt.js index a45b0c5c..1073bb25 100644 --- a/lib/message/decrypt.js +++ b/lib/message/decrypt.js @@ -30,7 +30,7 @@ export default async function decryptMessage({ } const decryptionResult = await decrypt(sanitizedOptions); - const verificationResult = handleVerificationResult(decryptionResult, context); + const verificationResult = handleVerificationResult(decryptionResult, context, options.expectSigned); let verified = verificationResult.then((result) => result.verified); let verifiedSignatures = verificationResult.then((result) => result.signatures); diff --git a/lib/message/verify.d.ts b/lib/message/verify.d.ts index 3fb0f957..d3cb9015 100644 --- a/lib/message/verify.d.ts +++ b/lib/message/verify.d.ts @@ -35,7 +35,8 @@ export function verifyMessage; export function handleVerificationResult( verificationResult: openpgp_VerifyMessageResult, - context: ContextVerificationOptions + context?: ContextVerificationOptions, + expectSigned?: boolean ): Promise>; export interface VerifyCleartextOptionsPmcrypto extends Omit { diff --git a/lib/message/verify.js b/lib/message/verify.js index 85689754..1f120dfd 100644 --- a/lib/message/verify.js +++ b/lib/message/verify.js @@ -18,6 +18,7 @@ const { NOT_SIGNED, SIGNED_AND_VALID, SIGNED_AND_INVALID } = VERIFICATION_STATUS * signature: Promise * } * @param {Object} context - context verification options + * @param {Boolean} expectSigned - whether a valid signature is expected; it causes the function to throw otherwise * @returns {{ * data: Uint8Array|string|ReadableStream|NodeStream - message data, * verified: constants.VERIFICATION_STATUS - message verification status, @@ -26,7 +27,7 @@ const { NOT_SIGNED, SIGNED_AND_VALID, SIGNED_AND_INVALID } = VERIFICATION_STATUS * errors: Error[]|undefined - verification errors if all signatures are invalid * }} */ -export async function handleVerificationResult(verificationResult, context) { +export async function handleVerificationResult(verificationResult, context, expectSigned) { const { data, signatures: sigsInfo } = verificationResult; const signatures = []; const errors = []; @@ -52,7 +53,7 @@ export async function handleVerificationResult(verificationResult, context) { if (!context || isValidSignatureContext(context, verifiedSigPacket)) { verificationStatus = SIGNED_AND_VALID; } else { - errors.push(new ContextError()); + errors.push(new ContextError('context verification error')); } if (!signatureTimestamp) { @@ -63,6 +64,11 @@ export async function handleVerificationResult(verificationResult, context) { } } + if (expectSigned && verificationStatus !== SIGNED_AND_VALID) { + // this is primarily intended to throw context error, which isn't checked by OpenPGP.js + throw errors[0]; + } + return { data, verified: verificationStatus, @@ -106,7 +112,7 @@ export async function verifyMessage({ }; const verificationResult = await verify(sanitizedOptions); - return handleVerificationResult(verificationResult, context); + return handleVerificationResult(verificationResult, context, options.expectSigned); } /** @@ -131,5 +137,5 @@ export async function verifyCleartextMessage({ cleartextMessage, date = serverTi const sanitizedOptions = { ...options, date, message: cleartextMessage }; const verificationResult = await verify(sanitizedOptions); - return handleVerificationResult(verificationResult); + return handleVerificationResult(verificationResult, undefined, options.expectSigned); } diff --git a/test/message/context.spec.ts b/test/message/context.spec.ts index 5968ae1d..60e3516a 100644 --- a/test/message/context.spec.ts +++ b/test/message/context.spec.ts @@ -34,6 +34,15 @@ describe('context', () => { context: { value: 'unexpected-context', required: true } }); + // verificationWrongContext with `expectSigned` + await expect(verifyMessage({ + textData, + signature: await readSignature({ armoredSignature }), + verificationKeys: [publicKey], + context: { value: 'unexpected-context', required: true }, + expectSigned: true + })).to.be.rejectedWith(ContextError); + const verificationMissingContext = await verifyMessage({ textData, signature: await readSignature({ armoredSignature }),