auto.js 2.8 KB

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