Files
smartssh/ts/smartssh.classes.sshkey.ts
T

154 lines
4.2 KiB
TypeScript

import * as plugins from './smartssh.plugins.js';
import * as helpers from './smartssh.classes.helpers.js';
export type TSshKeyType = 'duplex' | 'private' | 'public';
export class SshKey {
private _privKey: string;
private _pubKey: string;
private _hostVar: string;
private _authorized: boolean;
/**
* the constructor for class SshKey
*/
constructor(
optionsArg: { private?: string; public?: string; host?: string; authorized?: boolean } = {}
) {
this._privKey = optionsArg.private ?? '';
this._pubKey = optionsArg.public ?? '';
if (optionsArg.host) {
helpers.assertSafeHost(optionsArg.host);
}
this._hostVar = optionsArg.host ?? '';
this._authorized = optionsArg.authorized ?? false;
}
// this.host
get host() {
return this._hostVar;
}
set host(hostArg: string) {
if (hostArg) {
helpers.assertSafeHost(hostArg);
}
this._hostVar = hostArg;
}
// this.privKey
get privKey() {
return this._privKey;
}
set privKey(privateKeyArg: string) {
this._privKey = privateKeyArg;
}
// this.privKeyBase64
get privKeyBase64() {
return plugins.smartstring.base64.encode(this._privKey);
}
set privKeyBase64(privateKeyArg: string) {
this._privKey = plugins.smartstring.base64.decode(privateKeyArg);
}
// this.pubKey
get pubKey() {
return this._pubKey;
}
set pubKey(publicKeyArg: string) {
this._pubKey = publicKeyArg;
}
// this.pubKeyBase64
get pubKeyBase64() {
return plugins.smartstring.base64.encode(this._pubKey);
}
set pubKeyBase64(publicKeyArg: string) {
this._pubKey = plugins.smartstring.base64.decode(publicKeyArg);
}
get authorized() {
return this._authorized;
}
set authorized(authorizedArg: boolean) {
this._authorized = authorizedArg;
}
/**
* returns wether there is a private, a public or both keys
*/
get type(): TSshKeyType | undefined {
if (this._privKey && this._pubKey) {
return 'duplex';
} else if (this._privKey) {
return 'private';
} else if (this._pubKey) {
return 'public';
}
}
// methods
read(filePathArg: string) {
const resolvedPath = plugins.path.resolve(filePathArg);
const fileName = plugins.path.basename(resolvedPath);
const isPublicKey = fileName.endsWith('.pub');
const host = isPublicKey ? fileName.slice(0, -4) : fileName;
helpers.assertSafeHost(host);
this._hostVar = host;
if (isPublicKey) {
this._pubKey = plugins.fs.readFileSync(resolvedPath, 'utf8');
} else {
this._privKey = plugins.fs.readFileSync(resolvedPath, 'utf8');
}
}
static fromFile(filePathArg: string) {
const sshKey = new SshKey();
sshKey.read(filePathArg);
return sshKey;
}
static fromFiles(optionsArg: { privateKeyPath?: string; publicKeyPath?: string; host?: string }) {
const sshKey = new SshKey({ host: optionsArg.host });
if (optionsArg.privateKeyPath) {
sshKey.privKey = plugins.fs.readFileSync(plugins.path.resolve(optionsArg.privateKeyPath), 'utf8');
if (!sshKey.host) {
const fileName = plugins.path.basename(optionsArg.privateKeyPath);
helpers.assertSafeHost(fileName);
sshKey.host = fileName;
}
}
if (optionsArg.publicKeyPath) {
sshKey.pubKey = plugins.fs.readFileSync(plugins.path.resolve(optionsArg.publicKeyPath), 'utf8');
if (!sshKey.host) {
const fileName = plugins.path.basename(optionsArg.publicKeyPath).replace(/\.pub$/, '');
helpers.assertSafeHost(fileName);
sshKey.host = fileName;
}
}
return sshKey;
}
async store(dirPathArg: string) {
this.storeSync(dirPathArg);
}
storeSync(dirPathArg: string) {
helpers.assertSafeHost(this.host);
const resolvedDir = helpers.resolveSshDirPath(dirPathArg);
helpers.ensureSshDirSync(resolvedDir);
const fileNameBase = this.host;
if (this._privKey) {
const filePath = plugins.path.join(resolvedDir, fileNameBase);
plugins.fs.writeFileSync(filePath, this._privKey);
plugins.fs.chmodSync(filePath, 0o600);
}
if (this._pubKey) {
const filePath = plugins.path.join(resolvedDir, fileNameBase + '.pub');
plugins.fs.writeFileSync(filePath, this._pubKey);
plugins.fs.chmodSync(filePath, 0o644);
}
}
}