generate.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import crypto from './webcrypto.js';
  2. import { JOSENotSupported } from '../util/errors.js';
  3. import random from './random.js';
  4. export async function generateSecret(alg, options) {
  5. var _a;
  6. let length;
  7. let algorithm;
  8. let keyUsages;
  9. switch (alg) {
  10. case 'HS256':
  11. case 'HS384':
  12. case 'HS512':
  13. length = parseInt(alg.slice(-3), 10);
  14. algorithm = { name: 'HMAC', hash: `SHA-${length}`, length };
  15. keyUsages = ['sign', 'verify'];
  16. break;
  17. case 'A128CBC-HS256':
  18. case 'A192CBC-HS384':
  19. case 'A256CBC-HS512':
  20. length = parseInt(alg.slice(-3), 10);
  21. return random(new Uint8Array(length >> 3));
  22. case 'A128KW':
  23. case 'A192KW':
  24. case 'A256KW':
  25. length = parseInt(alg.slice(1, 4), 10);
  26. algorithm = { name: 'AES-KW', length };
  27. keyUsages = ['wrapKey', 'unwrapKey'];
  28. break;
  29. case 'A128GCMKW':
  30. case 'A192GCMKW':
  31. case 'A256GCMKW':
  32. case 'A128GCM':
  33. case 'A192GCM':
  34. case 'A256GCM':
  35. length = parseInt(alg.slice(1, 4), 10);
  36. algorithm = { name: 'AES-GCM', length };
  37. keyUsages = ['encrypt', 'decrypt'];
  38. break;
  39. default:
  40. throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
  41. }
  42. return crypto.subtle.generateKey(algorithm, (_a = options === null || options === void 0 ? void 0 : options.extractable) !== null && _a !== void 0 ? _a : false, keyUsages);
  43. }
  44. function getModulusLengthOption(options) {
  45. var _a;
  46. const modulusLength = (_a = options === null || options === void 0 ? void 0 : options.modulusLength) !== null && _a !== void 0 ? _a : 2048;
  47. if (typeof modulusLength !== 'number' || modulusLength < 2048) {
  48. throw new JOSENotSupported('Invalid or unsupported modulusLength option provided, 2048 bits or larger keys must be used');
  49. }
  50. return modulusLength;
  51. }
  52. export async function generateKeyPair(alg, options) {
  53. var _a, _b, _c;
  54. let algorithm;
  55. let keyUsages;
  56. switch (alg) {
  57. case 'PS256':
  58. case 'PS384':
  59. case 'PS512':
  60. algorithm = {
  61. name: 'RSA-PSS',
  62. hash: `SHA-${alg.slice(-3)}`,
  63. publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
  64. modulusLength: getModulusLengthOption(options),
  65. };
  66. keyUsages = ['sign', 'verify'];
  67. break;
  68. case 'RS256':
  69. case 'RS384':
  70. case 'RS512':
  71. algorithm = {
  72. name: 'RSASSA-PKCS1-v1_5',
  73. hash: `SHA-${alg.slice(-3)}`,
  74. publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
  75. modulusLength: getModulusLengthOption(options),
  76. };
  77. keyUsages = ['sign', 'verify'];
  78. break;
  79. case 'RSA-OAEP':
  80. case 'RSA-OAEP-256':
  81. case 'RSA-OAEP-384':
  82. case 'RSA-OAEP-512':
  83. algorithm = {
  84. name: 'RSA-OAEP',
  85. hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}`,
  86. publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
  87. modulusLength: getModulusLengthOption(options),
  88. };
  89. keyUsages = ['decrypt', 'unwrapKey', 'encrypt', 'wrapKey'];
  90. break;
  91. case 'ES256':
  92. algorithm = { name: 'ECDSA', namedCurve: 'P-256' };
  93. keyUsages = ['sign', 'verify'];
  94. break;
  95. case 'ES384':
  96. algorithm = { name: 'ECDSA', namedCurve: 'P-384' };
  97. keyUsages = ['sign', 'verify'];
  98. break;
  99. case 'ES512':
  100. algorithm = { name: 'ECDSA', namedCurve: 'P-521' };
  101. keyUsages = ['sign', 'verify'];
  102. break;
  103. case 'EdDSA':
  104. keyUsages = ['sign', 'verify'];
  105. const crv = (_a = options === null || options === void 0 ? void 0 : options.crv) !== null && _a !== void 0 ? _a : 'Ed25519';
  106. switch (crv) {
  107. case 'Ed25519':
  108. case 'Ed448':
  109. algorithm = { name: crv };
  110. break;
  111. default:
  112. throw new JOSENotSupported('Invalid or unsupported crv option provided');
  113. }
  114. break;
  115. case 'ECDH-ES':
  116. case 'ECDH-ES+A128KW':
  117. case 'ECDH-ES+A192KW':
  118. case 'ECDH-ES+A256KW': {
  119. keyUsages = ['deriveKey', 'deriveBits'];
  120. const crv = (_b = options === null || options === void 0 ? void 0 : options.crv) !== null && _b !== void 0 ? _b : 'P-256';
  121. switch (crv) {
  122. case 'P-256':
  123. case 'P-384':
  124. case 'P-521': {
  125. algorithm = { name: 'ECDH', namedCurve: crv };
  126. break;
  127. }
  128. case 'X25519':
  129. case 'X448':
  130. algorithm = { name: crv };
  131. break;
  132. default:
  133. throw new JOSENotSupported('Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, X25519, and X448');
  134. }
  135. break;
  136. }
  137. default:
  138. throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
  139. }
  140. return (crypto.subtle.generateKey(algorithm, (_c = options === null || options === void 0 ? void 0 : options.extractable) !== null && _c !== void 0 ? _c : false, keyUsages));
  141. }