UNPKG

@microsoft/dev-tunnels-ssh-keys

Version:

SSH key import/export library for Dev Tunnels

113 lines 4.09 kB
"use strict"; // // Copyright (c) Microsoft Corporation. All rights reserved. // Object.defineProperty(exports, "__esModule", { value: true }); exports.KeyData = void 0; /** * Encapsulates formatted (serialized) key data and metadata. */ class KeyData { constructor(keyType, data) { /** * Optional headers containing key metadata. In PEM encoding, the headers appear in * plaintext before the base64-encoded key. */ this.headers = new Map(); this.keyType = keyType !== null && keyType !== void 0 ? keyType : ''; this.data = data !== null && data !== void 0 ? data : Buffer.alloc(0); } static tryDecodePem(input) { const lines = input.split('\n').map((line) => line.trimRight()); while (lines.length > 0 && lines[lines.length - 1].length === 0) { lines.splice(lines.length - 1, 1); } const beginMatch = lines[0].match(KeyData.beginRegex); const endMatch = lines[lines.length - 1].match(KeyData.endRegex); if (!beginMatch || !endMatch) { return null; } const keyType = beginMatch[1]; if (endMatch[1] !== keyType) { return null; } const headers = new Map(); let i = 1; if (lines[i].includes(':')) { for (; i < lines.length - 1 && lines[i].length > 0; i++) { const headerMatch = lines[i].match(this.headerRegex); if (headerMatch) { const name = headerMatch[1]; let value = headerMatch[2]; while (value.endsWith('\\')) { value = value.substr(0, value.length - 1); value += lines[++i]; } headers.set(name, value); } } } while (lines[i].length === 0) { i++; } const base64Data = lines.slice(i, lines.length - 1).join(''); let data; try { data = Buffer.from(base64Data, 'base64'); } catch (e) { return null; } const keyData = new KeyData(); keyData.keyType = keyType; keyData.headers = headers; keyData.data = data; return keyData; } static tryDecodePemBytes(input) { const hyphen = '-'.charCodeAt(0); if (input.length < 3 || input[0] !== hyphen || input[1] !== hyphen || input[2] !== hyphen) { return null; } let inputString; try { inputString = input.toString('utf8'); } catch (e) { return null; } return KeyData.tryDecodePem(inputString); } encodePem() { let s = `-----BEGIN ${this.keyType}-----\n`; for (const [name, value] of this.headers) { // TODO: Wrap the value with \ if it's long. s += `${name}: ${value}\n`; } if (this.headers.size > 0) { s += '\n'; } const dataBase64 = this.data.toString('base64'); const lineLength = 64; for (let offset = 0; offset < dataBase64.length; offset += lineLength) { s += dataBase64.substr(offset, Math.min(lineLength, dataBase64.length - offset)) + '\n'; } s += `-----END ${this.keyType}-----\n`; return s; } encodePemBytes() { return Buffer.from(this.encodePem(), 'utf8'); } encodeSshPublicKey() { const comment = this.headers.get('Comment'); return (this.keyType + ' ' + this.data.toString('base64') + (comment ? ' ' + comment : '') + '\n'); } encodeSshPublicKeyBytes() { return Buffer.from(this.encodeSshPublicKey(), 'utf8'); } } exports.KeyData = KeyData; KeyData.beginRegex = /^-+ *BEGIN (\w+( \w+)*) *-+$/; KeyData.endRegex = /^-+ *END (\w+( \w+)*) *-+$/; KeyData.headerRegex = /^([\w-]+): (.*)$/; //# sourceMappingURL=keyData.js.map