auto.js 2.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // Copyright 2015 Joyent, Inc.
  2. module.exports = {
  3. read: read,
  4. write: write
  5. };
  6. var assert = require('assert-plus');
  7. var Buffer = require('safer-buffer').Buffer;
  8. var utils = require('../utils');
  9. var Key = require('../key');
  10. var PrivateKey = require('../private-key');
  11. var pem = require('./pem');
  12. var ssh = require('./ssh');
  13. var rfc4253 = require('./rfc4253');
  14. var dnssec = require('./dnssec');
  15. var DNSSEC_PRIVKEY_HEADER_PREFIX = 'Private-key-format: v1';
  16. function read(buf, options) {
  17. if (typeof (buf) === 'string') {
  18. if (buf.trim().match(/^[-]+[ ]*BEGIN/))
  19. return (pem.read(buf, options));
  20. if (buf.match(/^\s*ssh-[a-z]/))
  21. return (ssh.read(buf, options));
  22. if (buf.match(/^\s*ecdsa-/))
  23. return (ssh.read(buf, options));
  24. if (findDNSSECHeader(buf))
  25. return (dnssec.read(buf, options));
  26. buf = Buffer.from(buf, 'binary');
  27. } else {
  28. assert.buffer(buf);
  29. if (findPEMHeader(buf))
  30. return (pem.read(buf, options));
  31. if (findSSHHeader(buf))
  32. return (ssh.read(buf, options));
  33. if (findDNSSECHeader(buf))
  34. return (dnssec.read(buf, options));
  35. }
  36. if (buf.readUInt32BE(0) < buf.length)
  37. return (rfc4253.read(buf, options));
  38. throw (new Error('Failed to auto-detect format of key'));
  39. }
  40. function findSSHHeader(buf) {
  41. var offset = 0;
  42. while (offset < buf.length &&
  43. (buf[offset] === 32 || buf[offset] === 10 || buf[offset] === 9))
  44. ++offset;
  45. if (offset + 4 <= buf.length &&
  46. buf.slice(offset, offset + 4).toString('ascii') === 'ssh-')
  47. return (true);
  48. if (offset + 6 <= buf.length &&
  49. buf.slice(offset, offset + 6).toString('ascii') === 'ecdsa-')
  50. return (true);
  51. return (false);
  52. }
  53. function findPEMHeader(buf) {
  54. var offset = 0;
  55. while (offset < buf.length &&
  56. (buf[offset] === 32 || buf[offset] === 10))
  57. ++offset;
  58. if (buf[offset] !== 45)
  59. return (false);
  60. while (offset < buf.length &&
  61. (buf[offset] === 45))
  62. ++offset;
  63. while (offset < buf.length &&
  64. (buf[offset] === 32))
  65. ++offset;
  66. if (offset + 5 > buf.length ||
  67. buf.slice(offset, offset + 5).toString('ascii') !== 'BEGIN')
  68. return (false);
  69. return (true);
  70. }
  71. function findDNSSECHeader(buf) {
  72. // private case first
  73. if (buf.length <= DNSSEC_PRIVKEY_HEADER_PREFIX.length)
  74. return (false);
  75. var headerCheck = buf.slice(0, DNSSEC_PRIVKEY_HEADER_PREFIX.length);
  76. if (headerCheck.toString('ascii') === DNSSEC_PRIVKEY_HEADER_PREFIX)
  77. return (true);
  78. // public-key RFC3110 ?
  79. // 'domain.com. IN KEY ...' or 'domain.com. IN DNSKEY ...'
  80. // skip any comment-lines
  81. if (typeof (buf) !== 'string') {
  82. buf = buf.toString('ascii');
  83. }
  84. var lines = buf.split('\n');
  85. var line = 0;
  86. /* JSSTYLED */
  87. while (lines[line].match(/^\;/))
  88. line++;
  89. if (lines[line].toString('ascii').match(/\. IN KEY /))
  90. return (true);
  91. if (lines[line].toString('ascii').match(/\. IN DNSKEY /))
  92. return (true);
  93. return (false);
  94. }
  95. function write(key, options) {
  96. throw (new Error('"auto" format cannot be used for writing'));
  97. }