encrypt_key_management.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import { wrap as aesKw } from '../runtime/aeskw.js';
  2. import * as ECDH from '../runtime/ecdhes.js';
  3. import { encrypt as pbes2Kw } from '../runtime/pbes2kw.js';
  4. import { encrypt as rsaEs } from '../runtime/rsaes.js';
  5. import { encode as base64url } from '../runtime/base64url.js';
  6. import generateCek, { bitLength as cekLength } from '../lib/cek.js';
  7. import { JOSENotSupported } from '../util/errors.js';
  8. import { exportJWK } from '../key/export.js';
  9. import checkKeyType from './check_key_type.js';
  10. import { wrap as aesGcmKw } from './aesgcmkw.js';
  11. async function encryptKeyManagement(alg, enc, key, providedCek, providedParameters = {}) {
  12. let encryptedKey;
  13. let parameters;
  14. let cek;
  15. checkKeyType(alg, key, 'encrypt');
  16. switch (alg) {
  17. case 'dir': {
  18. cek = key;
  19. break;
  20. }
  21. case 'ECDH-ES':
  22. case 'ECDH-ES+A128KW':
  23. case 'ECDH-ES+A192KW':
  24. case 'ECDH-ES+A256KW': {
  25. if (!ECDH.ecdhAllowed(key)) {
  26. throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime');
  27. }
  28. const { apu, apv } = providedParameters;
  29. let { epk: ephemeralKey } = providedParameters;
  30. ephemeralKey || (ephemeralKey = (await ECDH.generateEpk(key)).privateKey);
  31. const { x, y, crv, kty } = await exportJWK(ephemeralKey);
  32. const sharedSecret = await ECDH.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, alg === 'ECDH-ES' ? cekLength(enc) : parseInt(alg.slice(-5, -2), 10), apu, apv);
  33. parameters = { epk: { x, crv, kty } };
  34. if (kty === 'EC')
  35. parameters.epk.y = y;
  36. if (apu)
  37. parameters.apu = base64url(apu);
  38. if (apv)
  39. parameters.apv = base64url(apv);
  40. if (alg === 'ECDH-ES') {
  41. cek = sharedSecret;
  42. break;
  43. }
  44. cek = providedCek || generateCek(enc);
  45. const kwAlg = alg.slice(-6);
  46. encryptedKey = await aesKw(kwAlg, sharedSecret, cek);
  47. break;
  48. }
  49. case 'RSA1_5':
  50. case 'RSA-OAEP':
  51. case 'RSA-OAEP-256':
  52. case 'RSA-OAEP-384':
  53. case 'RSA-OAEP-512': {
  54. cek = providedCek || generateCek(enc);
  55. encryptedKey = await rsaEs(alg, key, cek);
  56. break;
  57. }
  58. case 'PBES2-HS256+A128KW':
  59. case 'PBES2-HS384+A192KW':
  60. case 'PBES2-HS512+A256KW': {
  61. cek = providedCek || generateCek(enc);
  62. const { p2c, p2s } = providedParameters;
  63. ({ encryptedKey, ...parameters } = await pbes2Kw(alg, key, cek, p2c, p2s));
  64. break;
  65. }
  66. case 'A128KW':
  67. case 'A192KW':
  68. case 'A256KW': {
  69. cek = providedCek || generateCek(enc);
  70. encryptedKey = await aesKw(alg, key, cek);
  71. break;
  72. }
  73. case 'A128GCMKW':
  74. case 'A192GCMKW':
  75. case 'A256GCMKW': {
  76. cek = providedCek || generateCek(enc);
  77. const { iv } = providedParameters;
  78. ({ encryptedKey, ...parameters } = await aesGcmKw(alg, key, cek, iv));
  79. break;
  80. }
  81. default: {
  82. throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value');
  83. }
  84. }
  85. return { cek, encryptedKey, parameters };
  86. }
  87. export default encryptKeyManagement;