| // Copyright 2018 Joyent, Inc. |
| |
| module.exports = { |
| read: read, |
| write: write |
| }; |
| |
| var assert = require('assert-plus'); |
| var Buffer = require('safer-buffer').Buffer; |
| var rfc4253 = require('./rfc4253'); |
| var Key = require('../key'); |
| |
| var errors = require('../errors'); |
| |
| function read(buf, options) { |
| var lines = buf.toString('ascii').split(/[\r\n]+/); |
| var found = false; |
| var parts; |
| var si = 0; |
| while (si < lines.length) { |
| parts = splitHeader(lines[si++]); |
| if (parts && |
| parts[0].toLowerCase() === 'putty-user-key-file-2') { |
| found = true; |
| break; |
| } |
| } |
| if (!found) { |
| throw (new Error('No PuTTY format first line found')); |
| } |
| var alg = parts[1]; |
| |
| parts = splitHeader(lines[si++]); |
| assert.equal(parts[0].toLowerCase(), 'encryption'); |
| |
| parts = splitHeader(lines[si++]); |
| assert.equal(parts[0].toLowerCase(), 'comment'); |
| var comment = parts[1]; |
| |
| parts = splitHeader(lines[si++]); |
| assert.equal(parts[0].toLowerCase(), 'public-lines'); |
| var publicLines = parseInt(parts[1], 10); |
| if (!isFinite(publicLines) || publicLines < 0 || |
| publicLines > lines.length) { |
| throw (new Error('Invalid public-lines count')); |
| } |
| |
| var publicBuf = Buffer.from( |
| lines.slice(si, si + publicLines).join(''), 'base64'); |
| var keyType = rfc4253.algToKeyType(alg); |
| var key = rfc4253.read(publicBuf); |
| if (key.type !== keyType) { |
| throw (new Error('Outer key algorithm mismatch')); |
| } |
| key.comment = comment; |
| return (key); |
| } |
| |
| function splitHeader(line) { |
| var idx = line.indexOf(':'); |
| if (idx === -1) |
| return (null); |
| var header = line.slice(0, idx); |
| ++idx; |
| while (line[idx] === ' ') |
| ++idx; |
| var rest = line.slice(idx); |
| return ([header, rest]); |
| } |
| |
| function write(key, options) { |
| assert.object(key); |
| if (!Key.isKey(key)) |
| throw (new Error('Must be a public key')); |
| |
| var alg = rfc4253.keyTypeToAlg(key); |
| var buf = rfc4253.write(key); |
| var comment = key.comment || ''; |
| |
| var b64 = buf.toString('base64'); |
| var lines = wrap(b64, 64); |
| |
| lines.unshift('Public-Lines: ' + lines.length); |
| lines.unshift('Comment: ' + comment); |
| lines.unshift('Encryption: none'); |
| lines.unshift('PuTTY-User-Key-File-2: ' + alg); |
| |
| return (Buffer.from(lines.join('\n') + '\n')); |
| } |
| |
| function wrap(txt, len) { |
| var lines = []; |
| var pos = 0; |
| while (pos < txt.length) { |
| lines.push(txt.slice(pos, pos + 64)); |
| pos += 64; |
| } |
| return (lines); |
| } |