Skip to content

Commit

Permalink
Merge pull request #205
Browse files Browse the repository at this point in the history
  • Loading branch information
larabr authored Dec 16, 2024
2 parents 7acf470 + 491d0b2 commit f1d6e24
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 52 deletions.
4 changes: 2 additions & 2 deletions lib/message/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,10 @@ export const getConfigForContextVerification = (config: PartialConfig) => ({
* Context verification error.
* Thrown if e.g. context information is not present in the signature, or it does not match the expected context.
*/
export class ContextError extends Error {
export class SignatureContextError extends Error {
constructor(message: string) {
super(message);

this.name = 'ContextError';
this.name = 'SignatureContextError';
}
}
12 changes: 9 additions & 3 deletions lib/message/decrypt.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,20 @@ import { DEFAULT_SIGNATURE_VERIFICATION_OFFSET } from '../constants';
export default async function decryptMessage({
date = new Date(+serverTime() + DEFAULT_SIGNATURE_VERIFICATION_OFFSET),
encryptedSignature,
context,
signatureContext,
config = {},
...options
}) {
if (signatureContext && (options.verificationKeys === undefined || options.verificationKeys.length === 0)) {
// sanity check to catch mistakes in case library users wrongly consider the `context` to be
// applied into e.g. the AEAD associated data
throw new Error('Unexpected `signatureContext` input without any `verificationKeys` provided');
}

const sanitizedOptions = {
...options,
date,
config: context ? getConfigForContextVerification(config) : config
config: signatureContext ? getConfigForContextVerification(config) : config
};

try {
Expand All @@ -30,7 +36,7 @@ export default async function decryptMessage({
}

const decryptionResult = await decrypt(sanitizedOptions);
const verificationResult = handleVerificationResult(decryptionResult, context, options.expectSigned);
const verificationResult = handleVerificationResult(decryptionResult, signatureContext, options.expectSigned);

let verified = verificationResult.then((result) => result.verified);
let verifiedSignatures = verificationResult.then((result) => result.signatures);
Expand Down
12 changes: 10 additions & 2 deletions lib/message/encrypt.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,23 @@ export default async function encryptMessage({
textData,
binaryData,
stripTrailingSpaces,
context,
signatureContext,
format = 'armored',
date = serverTime(),
detached = false,
...options
}) {
if (signatureContext && (options.signingKeys === undefined || options.signingKeys.length === 0)) {
// sanity check to catch mistakes in case library users wrongly consider the `context` to be
// applied into e.g. the AEAD associated data
throw new Error('Unexpected `signatureContext` input without any `signingKeys` provided');
}

const sanitizedOptions = {
...options,
signatureNotations: context ? getNotationForContext(context.value, context.critical) : undefined, // only applied if signingKeys are given
signatureNotations: signatureContext ?
getNotationForContext(signatureContext.value, signatureContext.critical) :
undefined,
date,
format
};
Expand Down
6 changes: 4 additions & 2 deletions lib/message/sign.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default async function signMessage({
textData,
binaryData,
stripTrailingSpaces,
context,
signatureContext,
date = serverTime(),
format = 'armored',
...options
Expand All @@ -29,7 +29,9 @@ export default async function signMessage({
date,
format,
message: await createMessage({ [dataType]: data, date }),
signatureNotations: context ? getNotationForContext(context.value, context.critical) : undefined
signatureNotations: signatureContext ?
getNotationForContext(signatureContext.value, signatureContext.critical) :
undefined
};

return sign(sanitizedOptions).catch((err) => {
Expand Down
4 changes: 2 additions & 2 deletions lib/message/verify.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface VerifyOptionsPmcrypto<T extends Data> extends Omit<VerifyOption
textData?: T extends string ? T : never;
binaryData?: T extends Uint8Array ? T : never;
stripTrailingSpaces?: T extends string ? boolean : never;
context?: ContextVerificationOptions;
signatureContext?: ContextVerificationOptions;
}

export interface VerifyMessageResult<DataType extends openpgp_VerifyMessageResult['data'] = Data> {
Expand All @@ -35,7 +35,7 @@ export function verifyMessage<DataType extends Data, FormatType extends VerifyOp
>;
export function handleVerificationResult<DataType extends Data>(
verificationResult: openpgp_VerifyMessageResult<DataType>,
context?: ContextVerificationOptions,
signatureContext?: ContextVerificationOptions,
expectSigned?: boolean
): Promise<VerifyMessageResult<DataType>>;

Expand Down
16 changes: 8 additions & 8 deletions lib/message/verify.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createMessage, verify, CleartextMessage } from '../openpgp';
import { DEFAULT_SIGNATURE_VERIFICATION_OFFSET, VERIFICATION_STATUS } from '../constants';
import { serverTime } from '../serverTime';
import { removeTrailingSpaces } from './utils';
import { ContextError, getConfigForContextVerification, isValidSignatureContext } from './context';
import { SignatureContextError, getConfigForContextVerification, isValidSignatureContext } from './context';

const { NOT_SIGNED, SIGNED_AND_VALID, SIGNED_AND_INVALID } = VERIFICATION_STATUS;

Expand All @@ -17,7 +17,7 @@ const { NOT_SIGNED, SIGNED_AND_VALID, SIGNED_AND_INVALID } = VERIFICATION_STATUS
* verified: Promise<Boolean>,
* signature: Promise<openpgp.signature.Signature>
* }
* @param {Object} context - context verification options
* @param {Object} contesignatureContextxt - signature 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,
Expand All @@ -27,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, expectSigned) {
export async function handleVerificationResult(verificationResult, signatureContext, expectSigned) {
const { data, signatures: sigsInfo } = verificationResult;
const signatures = [];
const errors = [];
Expand All @@ -50,10 +50,10 @@ export async function handleVerificationResult(verificationResult, context, expe
// signature.
const verifiedSigPacket = signature.packets[0];

if (!context || isValidSignatureContext(context, verifiedSigPacket)) {
if (!signatureContext || isValidSignatureContext(signatureContext, verifiedSigPacket)) {
verificationStatus = SIGNED_AND_VALID;
} else {
errors.push(new ContextError('context verification error'));
errors.push(new SignatureContextError('context verification error'));
}

if (!signatureTimestamp) {
Expand Down Expand Up @@ -97,7 +97,7 @@ export async function verifyMessage({
textData,
binaryData,
stripTrailingSpaces,
context,
signatureContext,
config = {},
date = new Date(+serverTime() + DEFAULT_SIGNATURE_VERIFICATION_OFFSET),
...options
Expand All @@ -108,11 +108,11 @@ export async function verifyMessage({
...options,
date,
message: await createMessage({ [dataType]: dataToVerify, date }),
config: context ? getConfigForContextVerification(config) : config
config: signatureContext ? getConfigForContextVerification(config) : config
};

const verificationResult = await verify(sanitizedOptions);
return handleVerificationResult(verificationResult, context, options.expectSigned);
return handleVerificationResult(verificationResult, signatureContext, options.expectSigned);
}

/**
Expand Down
8 changes: 4 additions & 4 deletions lib/pmcrypto.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import type { ContextSigningOptions, ContextVerificationOptions } from './messag
export function init(): void;

export { VERIFICATION_STATUS, SIGNATURE_TYPES, type PartialConfig };
export { ContextError } from './message/context';
export { SignatureContextError } from './message/context';

export type OpenPGPKey = Key;
export type OpenPGPMessage = Message<Uint8Array | string>; // TODO missing streaming support
Expand Down Expand Up @@ -70,7 +70,7 @@ export function decryptSessionKey(options: DecryptSessionKeyOptionsPmcrypto): Pr
export interface DecryptOptionsPmcrypto<T extends MaybeWebStream<Data>> extends DecryptOptions {
message: Message<T>;
encryptedSignature?: Message<MaybeWebStream<Data>>;
context?: ContextVerificationOptions
signatureContext?: ContextVerificationOptions
}

export interface DecryptResultPmcrypto<DataType extends openpgp_DecryptMessageResult['data'] = MaybeWebStream<Data>> {
Expand Down Expand Up @@ -104,7 +104,7 @@ export interface EncryptOptionsPmcrypto<T extends MaybeWebStream<Data>> extends
binaryData?: T extends MaybeWebStream<Uint8Array> ? T : never;
stripTrailingSpaces?: T extends MaybeWebStream<string> ? boolean : never;
detached?: boolean;
context?: ContextSigningOptions;
signatureContext?: ContextSigningOptions;
}

// No reuse from OpenPGP's equivalent
Expand Down Expand Up @@ -153,7 +153,7 @@ export interface SignOptionsPmcrypto<T extends MaybeWebStream<Data>> extends Omi
textData?: T extends MaybeWebStream<string> ? T : never;
binaryData?: T extends MaybeWebStream<Uint8Array> ? T : never;
stripTrailingSpaces?: T extends MaybeWebStream<string> ? boolean : never;
context?: ContextSigningOptions;
signatureContext?: ContextSigningOptions;
}

export function signMessage<
Expand Down
2 changes: 1 addition & 1 deletion lib/pmcrypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,4 @@ export { checkKeyStrength, checkKeyCompatibility } from './key/check';

export * from './constants';

export { ContextError } from './message/context';
export { SignatureContextError } from './message/context';
Loading

0 comments on commit f1d6e24

Please sign in to comment.