encrypt.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.FlattenedEncrypt = exports.unprotected = void 0;
  4. const base64url_js_1 = require("../../runtime/base64url.js");
  5. const encrypt_js_1 = require("../../runtime/encrypt.js");
  6. const zlib_js_1 = require("../../runtime/zlib.js");
  7. const iv_js_1 = require("../../lib/iv.js");
  8. const encrypt_key_management_js_1 = require("../../lib/encrypt_key_management.js");
  9. const errors_js_1 = require("../../util/errors.js");
  10. const is_disjoint_js_1 = require("../../lib/is_disjoint.js");
  11. const buffer_utils_js_1 = require("../../lib/buffer_utils.js");
  12. const validate_crit_js_1 = require("../../lib/validate_crit.js");
  13. exports.unprotected = Symbol();
  14. class FlattenedEncrypt {
  15. constructor(plaintext) {
  16. if (!(plaintext instanceof Uint8Array)) {
  17. throw new TypeError('plaintext must be an instance of Uint8Array');
  18. }
  19. this._plaintext = plaintext;
  20. }
  21. setKeyManagementParameters(parameters) {
  22. if (this._keyManagementParameters) {
  23. throw new TypeError('setKeyManagementParameters can only be called once');
  24. }
  25. this._keyManagementParameters = parameters;
  26. return this;
  27. }
  28. setProtectedHeader(protectedHeader) {
  29. if (this._protectedHeader) {
  30. throw new TypeError('setProtectedHeader can only be called once');
  31. }
  32. this._protectedHeader = protectedHeader;
  33. return this;
  34. }
  35. setSharedUnprotectedHeader(sharedUnprotectedHeader) {
  36. if (this._sharedUnprotectedHeader) {
  37. throw new TypeError('setSharedUnprotectedHeader can only be called once');
  38. }
  39. this._sharedUnprotectedHeader = sharedUnprotectedHeader;
  40. return this;
  41. }
  42. setUnprotectedHeader(unprotectedHeader) {
  43. if (this._unprotectedHeader) {
  44. throw new TypeError('setUnprotectedHeader can only be called once');
  45. }
  46. this._unprotectedHeader = unprotectedHeader;
  47. return this;
  48. }
  49. setAdditionalAuthenticatedData(aad) {
  50. this._aad = aad;
  51. return this;
  52. }
  53. setContentEncryptionKey(cek) {
  54. if (this._cek) {
  55. throw new TypeError('setContentEncryptionKey can only be called once');
  56. }
  57. this._cek = cek;
  58. return this;
  59. }
  60. setInitializationVector(iv) {
  61. if (this._iv) {
  62. throw new TypeError('setInitializationVector can only be called once');
  63. }
  64. this._iv = iv;
  65. return this;
  66. }
  67. async encrypt(key, options) {
  68. if (!this._protectedHeader && !this._unprotectedHeader && !this._sharedUnprotectedHeader) {
  69. throw new errors_js_1.JWEInvalid('either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()');
  70. }
  71. if (!(0, is_disjoint_js_1.default)(this._protectedHeader, this._unprotectedHeader, this._sharedUnprotectedHeader)) {
  72. throw new errors_js_1.JWEInvalid('JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint');
  73. }
  74. const joseHeader = {
  75. ...this._protectedHeader,
  76. ...this._unprotectedHeader,
  77. ...this._sharedUnprotectedHeader,
  78. };
  79. (0, validate_crit_js_1.default)(errors_js_1.JWEInvalid, new Map(), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader);
  80. if (joseHeader.zip !== undefined) {
  81. if (!this._protectedHeader || !this._protectedHeader.zip) {
  82. throw new errors_js_1.JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected');
  83. }
  84. if (joseHeader.zip !== 'DEF') {
  85. throw new errors_js_1.JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value');
  86. }
  87. }
  88. const { alg, enc } = joseHeader;
  89. if (typeof alg !== 'string' || !alg) {
  90. throw new errors_js_1.JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid');
  91. }
  92. if (typeof enc !== 'string' || !enc) {
  93. throw new errors_js_1.JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid');
  94. }
  95. let encryptedKey;
  96. if (alg === 'dir') {
  97. if (this._cek) {
  98. throw new TypeError('setContentEncryptionKey cannot be called when using Direct Encryption');
  99. }
  100. }
  101. else if (alg === 'ECDH-ES') {
  102. if (this._cek) {
  103. throw new TypeError('setContentEncryptionKey cannot be called when using Direct Key Agreement');
  104. }
  105. }
  106. let cek;
  107. {
  108. let parameters;
  109. ({ cek, encryptedKey, parameters } = await (0, encrypt_key_management_js_1.default)(alg, enc, key, this._cek, this._keyManagementParameters));
  110. if (parameters) {
  111. if (options && exports.unprotected in options) {
  112. if (!this._unprotectedHeader) {
  113. this.setUnprotectedHeader(parameters);
  114. }
  115. else {
  116. this._unprotectedHeader = { ...this._unprotectedHeader, ...parameters };
  117. }
  118. }
  119. else {
  120. if (!this._protectedHeader) {
  121. this.setProtectedHeader(parameters);
  122. }
  123. else {
  124. this._protectedHeader = { ...this._protectedHeader, ...parameters };
  125. }
  126. }
  127. }
  128. }
  129. this._iv || (this._iv = (0, iv_js_1.default)(enc));
  130. let additionalData;
  131. let protectedHeader;
  132. let aadMember;
  133. if (this._protectedHeader) {
  134. protectedHeader = buffer_utils_js_1.encoder.encode((0, base64url_js_1.encode)(JSON.stringify(this._protectedHeader)));
  135. }
  136. else {
  137. protectedHeader = buffer_utils_js_1.encoder.encode('');
  138. }
  139. if (this._aad) {
  140. aadMember = (0, base64url_js_1.encode)(this._aad);
  141. additionalData = (0, buffer_utils_js_1.concat)(protectedHeader, buffer_utils_js_1.encoder.encode('.'), buffer_utils_js_1.encoder.encode(aadMember));
  142. }
  143. else {
  144. additionalData = protectedHeader;
  145. }
  146. let ciphertext;
  147. let tag;
  148. if (joseHeader.zip === 'DEF') {
  149. const deflated = await ((options === null || options === void 0 ? void 0 : options.deflateRaw) || zlib_js_1.deflate)(this._plaintext);
  150. ({ ciphertext, tag } = await (0, encrypt_js_1.default)(enc, deflated, cek, this._iv, additionalData));
  151. }
  152. else {
  153. ;
  154. ({ ciphertext, tag } = await (0, encrypt_js_1.default)(enc, this._plaintext, cek, this._iv, additionalData));
  155. }
  156. const jwe = {
  157. ciphertext: (0, base64url_js_1.encode)(ciphertext),
  158. iv: (0, base64url_js_1.encode)(this._iv),
  159. tag: (0, base64url_js_1.encode)(tag),
  160. };
  161. if (encryptedKey) {
  162. jwe.encrypted_key = (0, base64url_js_1.encode)(encryptedKey);
  163. }
  164. if (aadMember) {
  165. jwe.aad = aadMember;
  166. }
  167. if (this._protectedHeader) {
  168. jwe.protected = buffer_utils_js_1.decoder.decode(protectedHeader);
  169. }
  170. if (this._sharedUnprotectedHeader) {
  171. jwe.unprotected = this._sharedUnprotectedHeader;
  172. }
  173. if (this._unprotectedHeader) {
  174. jwe.header = this._unprotectedHeader;
  175. }
  176. return jwe;
  177. }
  178. }
  179. exports.FlattenedEncrypt = FlattenedEncrypt;