2025-12-03 20:54:35 +01:00

74 lines
2.2 KiB
JavaScript

import { FlattenedSign } from '../flattened/sign.js';
import { JWSInvalid } from '../../util/errors.js';
class IndividualSignature {
#parent;
protectedHeader;
unprotectedHeader;
options;
key;
constructor(sig, key, options) {
this.#parent = sig;
this.key = key;
this.options = options;
}
setProtectedHeader(protectedHeader) {
if (this.protectedHeader) {
throw new TypeError('setProtectedHeader can only be called once');
}
this.protectedHeader = protectedHeader;
return this;
}
setUnprotectedHeader(unprotectedHeader) {
if (this.unprotectedHeader) {
throw new TypeError('setUnprotectedHeader can only be called once');
}
this.unprotectedHeader = unprotectedHeader;
return this;
}
addSignature(...args) {
return this.#parent.addSignature(...args);
}
sign(...args) {
return this.#parent.sign(...args);
}
done() {
return this.#parent;
}
}
export class GeneralSign {
#payload;
#signatures = [];
constructor(payload) {
this.#payload = payload;
}
addSignature(key, options) {
const signature = new IndividualSignature(this, key, options);
this.#signatures.push(signature);
return signature;
}
async sign() {
if (!this.#signatures.length) {
throw new JWSInvalid('at least one signature must be added');
}
const jws = {
signatures: [],
payload: '',
};
for (let i = 0; i < this.#signatures.length; i++) {
const signature = this.#signatures[i];
const flattened = new FlattenedSign(this.#payload);
flattened.setProtectedHeader(signature.protectedHeader);
flattened.setUnprotectedHeader(signature.unprotectedHeader);
const { payload, ...rest } = await flattened.sign(signature.key, signature.options);
if (i === 0) {
jws.payload = payload;
}
else if (jws.payload !== payload) {
throw new JWSInvalid('inconsistent use of JWS Unencoded Payload (RFC7797)');
}
jws.signatures.push(rest);
}
return jws;
}
}