sign.js 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. import { FlattenedSign } from '../flattened/sign.js';
  2. import { JWSInvalid } from '../../util/errors.js';
  3. class IndividualSignature {
  4. constructor(sig, key, options) {
  5. this.parent = sig;
  6. this.key = key;
  7. this.options = options;
  8. }
  9. setProtectedHeader(protectedHeader) {
  10. if (this.protectedHeader) {
  11. throw new TypeError('setProtectedHeader can only be called once');
  12. }
  13. this.protectedHeader = protectedHeader;
  14. return this;
  15. }
  16. setUnprotectedHeader(unprotectedHeader) {
  17. if (this.unprotectedHeader) {
  18. throw new TypeError('setUnprotectedHeader can only be called once');
  19. }
  20. this.unprotectedHeader = unprotectedHeader;
  21. return this;
  22. }
  23. addSignature(...args) {
  24. return this.parent.addSignature(...args);
  25. }
  26. sign(...args) {
  27. return this.parent.sign(...args);
  28. }
  29. done() {
  30. return this.parent;
  31. }
  32. }
  33. export class GeneralSign {
  34. constructor(payload) {
  35. this._signatures = [];
  36. this._payload = payload;
  37. }
  38. addSignature(key, options) {
  39. const signature = new IndividualSignature(this, key, options);
  40. this._signatures.push(signature);
  41. return signature;
  42. }
  43. async sign() {
  44. if (!this._signatures.length) {
  45. throw new JWSInvalid('at least one signature must be added');
  46. }
  47. const jws = {
  48. signatures: [],
  49. payload: '',
  50. };
  51. for (let i = 0; i < this._signatures.length; i++) {
  52. const signature = this._signatures[i];
  53. const flattened = new FlattenedSign(this._payload);
  54. flattened.setProtectedHeader(signature.protectedHeader);
  55. flattened.setUnprotectedHeader(signature.unprotectedHeader);
  56. const { payload, ...rest } = await flattened.sign(signature.key, signature.options);
  57. if (i === 0) {
  58. jws.payload = payload;
  59. }
  60. else if (jws.payload !== payload) {
  61. throw new JWSInvalid('inconsistent use of JWS Unencoded Payload (RFC7797)');
  62. }
  63. jws.signatures.push(rest);
  64. }
  65. return jws;
  66. }
  67. }