key.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. exports.getPublicKey = getPublicKey;
  7. const crypto_1 = __importDefault(require("crypto"));
  8. const error_1 = require("../error");
  9. const oid_1 = require("./oid");
  10. const ASN1_TAG_SEQUENCE = 0x30;
  11. const ANS1_TAG_BIT_STRING = 0x03;
  12. const NULL_BYTE = 0x00;
  13. const OID_EDDSA = '1.3.101.112';
  14. const OID_EC_PUBLIC_KEY = '1.2.840.10045.2.1';
  15. const OID_EC_CURVE_P256V1 = '1.2.840.10045.3.1.7';
  16. const PEM_HEADER = '-----BEGIN PUBLIC KEY-----';
  17. function getPublicKey(keyInfo) {
  18. switch (keyInfo.keyType) {
  19. case 'rsa':
  20. return getRSAPublicKey(keyInfo);
  21. case 'ed25519':
  22. return getED25519PublicKey(keyInfo);
  23. case 'ecdsa':
  24. case 'ecdsa-sha2-nistp256':
  25. case 'ecdsa-sha2-nistp384':
  26. return getECDCSAPublicKey(keyInfo);
  27. default:
  28. throw new error_1.UnsupportedAlgorithmError(`Unsupported key type: ${keyInfo.keyType}`);
  29. }
  30. }
  31. function getRSAPublicKey(keyInfo) {
  32. // Only support PEM-encoded RSA keys
  33. if (!keyInfo.keyVal.startsWith(PEM_HEADER)) {
  34. throw new error_1.CryptoError('Invalid key format');
  35. }
  36. const key = crypto_1.default.createPublicKey(keyInfo.keyVal);
  37. switch (keyInfo.scheme) {
  38. case 'rsassa-pss-sha256':
  39. return {
  40. key: key,
  41. padding: crypto_1.default.constants.RSA_PKCS1_PSS_PADDING,
  42. };
  43. default:
  44. throw new error_1.UnsupportedAlgorithmError(`Unsupported RSA scheme: ${keyInfo.scheme}`);
  45. }
  46. }
  47. function getED25519PublicKey(keyInfo) {
  48. let key;
  49. // If key is already PEM-encoded we can just parse it
  50. if (keyInfo.keyVal.startsWith(PEM_HEADER)) {
  51. key = crypto_1.default.createPublicKey(keyInfo.keyVal);
  52. }
  53. else {
  54. // If key is not PEM-encoded it had better be hex
  55. if (!isHex(keyInfo.keyVal)) {
  56. throw new error_1.CryptoError('Invalid key format');
  57. }
  58. key = crypto_1.default.createPublicKey({
  59. key: ed25519.hexToDER(keyInfo.keyVal),
  60. format: 'der',
  61. type: 'spki',
  62. });
  63. }
  64. return { key };
  65. }
  66. function getECDCSAPublicKey(keyInfo) {
  67. let key;
  68. // If key is already PEM-encoded we can just parse it
  69. if (keyInfo.keyVal.startsWith(PEM_HEADER)) {
  70. key = crypto_1.default.createPublicKey(keyInfo.keyVal);
  71. }
  72. else {
  73. // If key is not PEM-encoded it had better be hex
  74. if (!isHex(keyInfo.keyVal)) {
  75. throw new error_1.CryptoError('Invalid key format');
  76. }
  77. key = crypto_1.default.createPublicKey({
  78. key: ecdsa.hexToDER(keyInfo.keyVal),
  79. format: 'der',
  80. type: 'spki',
  81. });
  82. }
  83. return { key };
  84. }
  85. const ed25519 = {
  86. // Translates a hex key into a crypto KeyObject
  87. // https://keygen.sh/blog/how-to-use-hexadecimal-ed25519-keys-in-node/
  88. hexToDER: (hex) => {
  89. const key = Buffer.from(hex, 'hex');
  90. const oid = (0, oid_1.encodeOIDString)(OID_EDDSA);
  91. // Create a byte sequence containing the OID and key
  92. const elements = Buffer.concat([
  93. Buffer.concat([
  94. Buffer.from([ASN1_TAG_SEQUENCE]),
  95. Buffer.from([oid.length]),
  96. oid,
  97. ]),
  98. Buffer.concat([
  99. Buffer.from([ANS1_TAG_BIT_STRING]),
  100. Buffer.from([key.length + 1]),
  101. Buffer.from([NULL_BYTE]),
  102. key,
  103. ]),
  104. ]);
  105. // Wrap up by creating a sequence of elements
  106. const der = Buffer.concat([
  107. Buffer.from([ASN1_TAG_SEQUENCE]),
  108. Buffer.from([elements.length]),
  109. elements,
  110. ]);
  111. return der;
  112. },
  113. };
  114. const ecdsa = {
  115. hexToDER: (hex) => {
  116. const key = Buffer.from(hex, 'hex');
  117. const bitString = Buffer.concat([
  118. Buffer.from([ANS1_TAG_BIT_STRING]),
  119. Buffer.from([key.length + 1]),
  120. Buffer.from([NULL_BYTE]),
  121. key,
  122. ]);
  123. const oids = Buffer.concat([
  124. (0, oid_1.encodeOIDString)(OID_EC_PUBLIC_KEY),
  125. (0, oid_1.encodeOIDString)(OID_EC_CURVE_P256V1),
  126. ]);
  127. const oidSequence = Buffer.concat([
  128. Buffer.from([ASN1_TAG_SEQUENCE]),
  129. Buffer.from([oids.length]),
  130. oids,
  131. ]);
  132. // Wrap up by creating a sequence of elements
  133. const der = Buffer.concat([
  134. Buffer.from([ASN1_TAG_SEQUENCE]),
  135. Buffer.from([oidSequence.length + bitString.length]),
  136. oidSequence,
  137. bitString,
  138. ]);
  139. return der;
  140. },
  141. };
  142. const isHex = (key) => /^[0-9a-fA-F]+$/.test(key);