mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 07:43:35 +00:00
Apply Prettier (#581)
This commit is contained in:
@@ -1,108 +1,113 @@
|
||||
import * as chalk from 'chalk';
|
||||
import * as chalk from "chalk";
|
||||
|
||||
import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
|
||||
import { Response } from './models/response';
|
||||
import { ListResponse } from './models/response/listResponse';
|
||||
import { MessageResponse } from './models/response/messageResponse';
|
||||
import { StringResponse } from './models/response/stringResponse';
|
||||
import { Response } from "./models/response";
|
||||
import { ListResponse } from "./models/response/listResponse";
|
||||
import { MessageResponse } from "./models/response/messageResponse";
|
||||
import { StringResponse } from "./models/response/stringResponse";
|
||||
|
||||
export abstract class BaseProgram {
|
||||
constructor(
|
||||
private stateService: StateService,
|
||||
private writeLn: (s: string, finalLine: boolean, error: boolean) => void) { }
|
||||
constructor(
|
||||
private stateService: StateService,
|
||||
private writeLn: (s: string, finalLine: boolean, error: boolean) => void
|
||||
) {}
|
||||
|
||||
protected processResponse(response: Response, exitImmediately = false, dataProcessor: () => string = null) {
|
||||
if (!response.success) {
|
||||
if (process.env.BW_QUIET !== 'true') {
|
||||
if (process.env.BW_RESPONSE === 'true') {
|
||||
this.writeLn(this.getJson(response), true, false);
|
||||
} else {
|
||||
this.writeLn(chalk.redBright(response.message), true, true);
|
||||
}
|
||||
}
|
||||
const exitCode = process.env.BW_CLEANEXIT ? 0 : 1;
|
||||
if (exitImmediately) {
|
||||
process.exit(exitCode);
|
||||
} else {
|
||||
process.exitCode = exitCode;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (process.env.BW_RESPONSE === 'true') {
|
||||
this.writeLn(this.getJson(response), true, false);
|
||||
} else if (response.data != null) {
|
||||
let out: string = dataProcessor != null ? dataProcessor() : null;
|
||||
if (out == null) {
|
||||
if (response.data.object === 'string') {
|
||||
const data = (response.data as StringResponse).data;
|
||||
if (data != null) {
|
||||
out = data;
|
||||
}
|
||||
} else if (response.data.object === 'list') {
|
||||
out = this.getJson((response.data as ListResponse).data);
|
||||
} else if (response.data.object === 'message') {
|
||||
out = this.getMessage(response);
|
||||
} else {
|
||||
out = this.getJson(response.data);
|
||||
}
|
||||
}
|
||||
|
||||
if (out != null && process.env.BW_QUIET !== 'true') {
|
||||
this.writeLn(out, true, false);
|
||||
}
|
||||
}
|
||||
if (exitImmediately) {
|
||||
process.exit(0);
|
||||
protected processResponse(
|
||||
response: Response,
|
||||
exitImmediately = false,
|
||||
dataProcessor: () => string = null
|
||||
) {
|
||||
if (!response.success) {
|
||||
if (process.env.BW_QUIET !== "true") {
|
||||
if (process.env.BW_RESPONSE === "true") {
|
||||
this.writeLn(this.getJson(response), true, false);
|
||||
} else {
|
||||
process.exitCode = 0;
|
||||
this.writeLn(chalk.redBright(response.message), true, true);
|
||||
}
|
||||
}
|
||||
const exitCode = process.env.BW_CLEANEXIT ? 0 : 1;
|
||||
if (exitImmediately) {
|
||||
process.exit(exitCode);
|
||||
} else {
|
||||
process.exitCode = exitCode;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
protected getJson(obj: any): string {
|
||||
if (process.env.BW_PRETTY === 'true') {
|
||||
return JSON.stringify(obj, null, ' ');
|
||||
if (process.env.BW_RESPONSE === "true") {
|
||||
this.writeLn(this.getJson(response), true, false);
|
||||
} else if (response.data != null) {
|
||||
let out: string = dataProcessor != null ? dataProcessor() : null;
|
||||
if (out == null) {
|
||||
if (response.data.object === "string") {
|
||||
const data = (response.data as StringResponse).data;
|
||||
if (data != null) {
|
||||
out = data;
|
||||
}
|
||||
} else if (response.data.object === "list") {
|
||||
out = this.getJson((response.data as ListResponse).data);
|
||||
} else if (response.data.object === "message") {
|
||||
out = this.getMessage(response);
|
||||
} else {
|
||||
return JSON.stringify(obj);
|
||||
out = this.getJson(response.data);
|
||||
}
|
||||
}
|
||||
|
||||
if (out != null && process.env.BW_QUIET !== "true") {
|
||||
this.writeLn(out, true, false);
|
||||
}
|
||||
}
|
||||
if (exitImmediately) {
|
||||
process.exit(0);
|
||||
} else {
|
||||
process.exitCode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected getJson(obj: any): string {
|
||||
if (process.env.BW_PRETTY === "true") {
|
||||
return JSON.stringify(obj, null, " ");
|
||||
} else {
|
||||
return JSON.stringify(obj);
|
||||
}
|
||||
}
|
||||
|
||||
protected getMessage(response: Response): string {
|
||||
const message = response.data as MessageResponse;
|
||||
if (process.env.BW_RAW === "true") {
|
||||
return message.raw;
|
||||
}
|
||||
|
||||
protected getMessage(response: Response): string {
|
||||
const message = (response.data as MessageResponse);
|
||||
if (process.env.BW_RAW === 'true') {
|
||||
return message.raw;
|
||||
}
|
||||
|
||||
let out: string = '';
|
||||
if (message.title != null) {
|
||||
if (message.noColor) {
|
||||
out = message.title;
|
||||
} else {
|
||||
out = chalk.greenBright(message.title);
|
||||
}
|
||||
}
|
||||
if (message.message != null) {
|
||||
if (message.title != null) {
|
||||
out += '\n';
|
||||
}
|
||||
out += message.message;
|
||||
}
|
||||
return out.trim() === '' ? null : out;
|
||||
let out: string = "";
|
||||
if (message.title != null) {
|
||||
if (message.noColor) {
|
||||
out = message.title;
|
||||
} else {
|
||||
out = chalk.greenBright(message.title);
|
||||
}
|
||||
}
|
||||
|
||||
protected async exitIfAuthed() {
|
||||
const authed = await this.stateService.getIsAuthenticated();
|
||||
if (authed) {
|
||||
const email = await this.stateService.getEmail();
|
||||
this.processResponse(Response.error('You are already logged in as ' + email + '.'), true);
|
||||
}
|
||||
if (message.message != null) {
|
||||
if (message.title != null) {
|
||||
out += "\n";
|
||||
}
|
||||
out += message.message;
|
||||
}
|
||||
return out.trim() === "" ? null : out;
|
||||
}
|
||||
|
||||
protected async exitIfNotAuthed() {
|
||||
const authed = await this.stateService.getIsAuthenticated();
|
||||
if (!authed) {
|
||||
this.processResponse(Response.error('You are not logged in.'), true);
|
||||
}
|
||||
protected async exitIfAuthed() {
|
||||
const authed = await this.stateService.getIsAuthenticated();
|
||||
if (authed) {
|
||||
const email = await this.stateService.getEmail();
|
||||
this.processResponse(Response.error("You are already logged in as " + email + "."), true);
|
||||
}
|
||||
}
|
||||
|
||||
protected async exitIfNotAuthed() {
|
||||
const authed = await this.stateService.getIsAuthenticated();
|
||||
if (!authed) {
|
||||
this.processResponse(Response.error("You are not logged in."), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,19 +1,24 @@
|
||||
import * as program from 'commander';
|
||||
import * as program from "commander";
|
||||
|
||||
import { AuthService } from 'jslib-common/abstractions/auth.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { AuthService } from "jslib-common/abstractions/auth.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
|
||||
import { Response } from '../models/response';
|
||||
import { MessageResponse } from '../models/response/messageResponse';
|
||||
import { Response } from "../models/response";
|
||||
import { MessageResponse } from "../models/response/messageResponse";
|
||||
|
||||
export class LogoutCommand {
|
||||
constructor(private authService: AuthService, private i18nService: I18nService,
|
||||
private logoutCallback: () => Promise<void>) { }
|
||||
constructor(
|
||||
private authService: AuthService,
|
||||
private i18nService: I18nService,
|
||||
private logoutCallback: () => Promise<void>
|
||||
) {}
|
||||
|
||||
async run() {
|
||||
await this.logoutCallback();
|
||||
this.authService.logOut(() => { /* Do nothing */ });
|
||||
const res = new MessageResponse('You have logged out.', null);
|
||||
return Response.success(res);
|
||||
}
|
||||
async run() {
|
||||
await this.logoutCallback();
|
||||
this.authService.logOut(() => {
|
||||
/* Do nothing */
|
||||
});
|
||||
const res = new MessageResponse("You have logged out.", null);
|
||||
return Response.success(res);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,86 +1,105 @@
|
||||
import * as program from 'commander';
|
||||
import * as fetch from 'node-fetch';
|
||||
import * as program from "commander";
|
||||
import * as fetch from "node-fetch";
|
||||
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
|
||||
import { Response } from '../models/response';
|
||||
import { MessageResponse } from '../models/response/messageResponse';
|
||||
import { Response } from "../models/response";
|
||||
import { MessageResponse } from "../models/response/messageResponse";
|
||||
|
||||
export class UpdateCommand {
|
||||
inPkg: boolean = false;
|
||||
inPkg: boolean = false;
|
||||
|
||||
constructor(private platformUtilsService: PlatformUtilsService, private i18nService: I18nService,
|
||||
private repoName: string, private executableName: string, private showExtendedMessage: boolean) {
|
||||
this.inPkg = !!(process as any).pkg;
|
||||
}
|
||||
constructor(
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private repoName: string,
|
||||
private executableName: string,
|
||||
private showExtendedMessage: boolean
|
||||
) {
|
||||
this.inPkg = !!(process as any).pkg;
|
||||
}
|
||||
|
||||
async run(): Promise<Response> {
|
||||
const currentVersion = await this.platformUtilsService.getApplicationVersion();
|
||||
async run(): Promise<Response> {
|
||||
const currentVersion = await this.platformUtilsService.getApplicationVersion();
|
||||
|
||||
const response = await fetch.default('https://api.github.com/repos/bitwarden/' +
|
||||
this.repoName + '/releases/latest');
|
||||
if (response.status === 200) {
|
||||
const responseJson = await response.json();
|
||||
const res = new MessageResponse(null, null);
|
||||
const response = await fetch.default(
|
||||
"https://api.github.com/repos/bitwarden/" + this.repoName + "/releases/latest"
|
||||
);
|
||||
if (response.status === 200) {
|
||||
const responseJson = await response.json();
|
||||
const res = new MessageResponse(null, null);
|
||||
|
||||
const tagName: string = responseJson.tag_name;
|
||||
if (tagName === ('v' + currentVersion)) {
|
||||
res.title = 'No update available.';
|
||||
res.noColor = true;
|
||||
return Response.success(res);
|
||||
}
|
||||
const tagName: string = responseJson.tag_name;
|
||||
if (tagName === "v" + currentVersion) {
|
||||
res.title = "No update available.";
|
||||
res.noColor = true;
|
||||
return Response.success(res);
|
||||
}
|
||||
|
||||
let downloadUrl: string = null;
|
||||
if (responseJson.assets != null) {
|
||||
for (const a of responseJson.assets) {
|
||||
const download: string = a.browser_download_url;
|
||||
if (download == null) {
|
||||
continue;
|
||||
}
|
||||
let downloadUrl: string = null;
|
||||
if (responseJson.assets != null) {
|
||||
for (const a of responseJson.assets) {
|
||||
const download: string = a.browser_download_url;
|
||||
if (download == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (download.indexOf('.zip') === -1) {
|
||||
continue;
|
||||
}
|
||||
if (download.indexOf(".zip") === -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (process.platform === 'win32' && download.indexOf(this.executableName + '-windows') > -1) {
|
||||
downloadUrl = download;
|
||||
break;
|
||||
} else if (process.platform === 'darwin' && download.indexOf(this.executableName + '-macos') > -1) {
|
||||
downloadUrl = download;
|
||||
break;
|
||||
} else if (process.platform === 'linux' && download.indexOf(this.executableName + '-linux') > -1) {
|
||||
downloadUrl = download;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res.title = 'A new version is available: ' + tagName;
|
||||
if (downloadUrl == null) {
|
||||
downloadUrl = 'https://github.com/bitwarden/' + this.repoName + '/releases';
|
||||
} else {
|
||||
res.raw = downloadUrl;
|
||||
}
|
||||
res.message = '';
|
||||
if (responseJson.body != null && responseJson.body !== '') {
|
||||
res.message = responseJson.body + '\n\n';
|
||||
}
|
||||
|
||||
res.message += 'You can download this update at ' + downloadUrl;
|
||||
|
||||
if (this.showExtendedMessage) {
|
||||
if (this.inPkg) {
|
||||
res.message += '\n\nIf you installed this CLI through a package manager ' +
|
||||
'you should probably update using its update command instead.';
|
||||
} else {
|
||||
res.message += '\n\nIf you installed this CLI through NPM ' +
|
||||
'you should update using `npm install -g @bitwarden/' + this.repoName + '`';
|
||||
}
|
||||
}
|
||||
return Response.success(res);
|
||||
} else {
|
||||
return Response.error('Error contacting update API: ' + response.status);
|
||||
if (
|
||||
process.platform === "win32" &&
|
||||
download.indexOf(this.executableName + "-windows") > -1
|
||||
) {
|
||||
downloadUrl = download;
|
||||
break;
|
||||
} else if (
|
||||
process.platform === "darwin" &&
|
||||
download.indexOf(this.executableName + "-macos") > -1
|
||||
) {
|
||||
downloadUrl = download;
|
||||
break;
|
||||
} else if (
|
||||
process.platform === "linux" &&
|
||||
download.indexOf(this.executableName + "-linux") > -1
|
||||
) {
|
||||
downloadUrl = download;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res.title = "A new version is available: " + tagName;
|
||||
if (downloadUrl == null) {
|
||||
downloadUrl = "https://github.com/bitwarden/" + this.repoName + "/releases";
|
||||
} else {
|
||||
res.raw = downloadUrl;
|
||||
}
|
||||
res.message = "";
|
||||
if (responseJson.body != null && responseJson.body !== "") {
|
||||
res.message = responseJson.body + "\n\n";
|
||||
}
|
||||
|
||||
res.message += "You can download this update at " + downloadUrl;
|
||||
|
||||
if (this.showExtendedMessage) {
|
||||
if (this.inPkg) {
|
||||
res.message +=
|
||||
"\n\nIf you installed this CLI through a package manager " +
|
||||
"you should probably update using its update command instead.";
|
||||
} else {
|
||||
res.message +=
|
||||
"\n\nIf you installed this CLI through NPM " +
|
||||
"you should update using `npm install -g @bitwarden/" +
|
||||
this.repoName +
|
||||
"`";
|
||||
}
|
||||
}
|
||||
return Response.success(res);
|
||||
} else {
|
||||
return Response.error("Error contacting update API: " + response.status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +1,50 @@
|
||||
import { BaseResponse } from './response/baseResponse';
|
||||
import { BaseResponse } from "./response/baseResponse";
|
||||
|
||||
export class Response {
|
||||
static error(error: any, data?: any): Response {
|
||||
const res = new Response();
|
||||
res.success = false;
|
||||
if (typeof (error) === 'string') {
|
||||
res.message = error;
|
||||
} else {
|
||||
res.message = error.message != null ? error.message :
|
||||
error.toString() === '[object Object]' ? JSON.stringify(error) : error.toString();
|
||||
}
|
||||
res.data = data;
|
||||
return res;
|
||||
static error(error: any, data?: any): Response {
|
||||
const res = new Response();
|
||||
res.success = false;
|
||||
if (typeof error === "string") {
|
||||
res.message = error;
|
||||
} else {
|
||||
res.message =
|
||||
error.message != null
|
||||
? error.message
|
||||
: error.toString() === "[object Object]"
|
||||
? JSON.stringify(error)
|
||||
: error.toString();
|
||||
}
|
||||
res.data = data;
|
||||
return res;
|
||||
}
|
||||
|
||||
static notFound(): Response {
|
||||
return Response.error('Not found.');
|
||||
}
|
||||
static notFound(): Response {
|
||||
return Response.error("Not found.");
|
||||
}
|
||||
|
||||
static badRequest(message: string): Response {
|
||||
return Response.error(message);
|
||||
}
|
||||
static badRequest(message: string): Response {
|
||||
return Response.error(message);
|
||||
}
|
||||
|
||||
static multipleResults(ids: string[]): Response {
|
||||
let msg = 'More than one result was found. Try getting a specific object by `id` instead. ' +
|
||||
'The following objects were found:';
|
||||
ids.forEach(id => {
|
||||
msg += '\n' + id;
|
||||
});
|
||||
return Response.error(msg, ids);
|
||||
}
|
||||
static multipleResults(ids: string[]): Response {
|
||||
let msg =
|
||||
"More than one result was found. Try getting a specific object by `id` instead. " +
|
||||
"The following objects were found:";
|
||||
ids.forEach((id) => {
|
||||
msg += "\n" + id;
|
||||
});
|
||||
return Response.error(msg, ids);
|
||||
}
|
||||
|
||||
static success(data?: BaseResponse): Response {
|
||||
const res = new Response();
|
||||
res.success = true;
|
||||
res.data = data;
|
||||
return res;
|
||||
}
|
||||
static success(data?: BaseResponse): Response {
|
||||
const res = new Response();
|
||||
res.success = true;
|
||||
res.data = data;
|
||||
return res;
|
||||
}
|
||||
|
||||
success: boolean;
|
||||
message: string;
|
||||
errorCode: number;
|
||||
data: BaseResponse;
|
||||
success: boolean;
|
||||
message: string;
|
||||
errorCode: number;
|
||||
data: BaseResponse;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export interface BaseResponse {
|
||||
object: string;
|
||||
object: string;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { BaseResponse } from './baseResponse';
|
||||
import { BaseResponse } from "./baseResponse";
|
||||
|
||||
export class FileResponse implements BaseResponse {
|
||||
object: string;
|
||||
data: Buffer;
|
||||
fileName: string;
|
||||
object: string;
|
||||
data: Buffer;
|
||||
fileName: string;
|
||||
|
||||
constructor(data: Buffer, fileName: string) {
|
||||
this.object = 'file';
|
||||
this.data = data;
|
||||
this.fileName = fileName;
|
||||
}
|
||||
constructor(data: Buffer, fileName: string) {
|
||||
this.object = "file";
|
||||
this.data = data;
|
||||
this.fileName = fileName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { BaseResponse } from './baseResponse';
|
||||
import { BaseResponse } from "./baseResponse";
|
||||
|
||||
export class ListResponse implements BaseResponse {
|
||||
object: string;
|
||||
data: BaseResponse[];
|
||||
object: string;
|
||||
data: BaseResponse[];
|
||||
|
||||
constructor(data: BaseResponse[]) {
|
||||
this.object = 'list';
|
||||
this.data = data;
|
||||
}
|
||||
constructor(data: BaseResponse[]) {
|
||||
this.object = "list";
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { BaseResponse } from './baseResponse';
|
||||
import { BaseResponse } from "./baseResponse";
|
||||
|
||||
export class MessageResponse implements BaseResponse {
|
||||
object: string;
|
||||
title: string;
|
||||
message: string;
|
||||
raw: string;
|
||||
noColor = false;
|
||||
object: string;
|
||||
title: string;
|
||||
message: string;
|
||||
raw: string;
|
||||
noColor = false;
|
||||
|
||||
constructor(title: string, message: string) {
|
||||
this.object = 'message';
|
||||
this.title = title;
|
||||
this.message = message;
|
||||
}
|
||||
constructor(title: string, message: string) {
|
||||
this.object = "message";
|
||||
this.title = title;
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { BaseResponse } from './baseResponse';
|
||||
import { BaseResponse } from "./baseResponse";
|
||||
|
||||
export class StringResponse implements BaseResponse {
|
||||
object: string;
|
||||
data: string;
|
||||
object: string;
|
||||
data: string;
|
||||
|
||||
constructor(data: string) {
|
||||
this.object = 'string';
|
||||
this.data = data;
|
||||
}
|
||||
constructor(data: string) {
|
||||
this.object = "string";
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,157 +1,166 @@
|
||||
import * as child_process from 'child_process';
|
||||
import * as child_process from "child_process";
|
||||
|
||||
import { DeviceType } from 'jslib-common/enums/deviceType';
|
||||
import { ThemeType } from 'jslib-common/enums/themeType';
|
||||
import { DeviceType } from "jslib-common/enums/deviceType";
|
||||
import { ThemeType } from "jslib-common/enums/themeType";
|
||||
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
|
||||
// tslint:disable-next-line
|
||||
const open = require('open');
|
||||
const open = require("open");
|
||||
|
||||
export class CliPlatformUtilsService implements PlatformUtilsService {
|
||||
identityClientId: string;
|
||||
identityClientId: string;
|
||||
|
||||
private deviceCache: DeviceType = null;
|
||||
private deviceCache: DeviceType = null;
|
||||
|
||||
constructor(identityClientId: string, private packageJson: any) {
|
||||
this.identityClientId = identityClientId;
|
||||
constructor(identityClientId: string, private packageJson: any) {
|
||||
this.identityClientId = identityClientId;
|
||||
}
|
||||
|
||||
getDevice(): DeviceType {
|
||||
if (!this.deviceCache) {
|
||||
switch (process.platform) {
|
||||
case "win32":
|
||||
this.deviceCache = DeviceType.WindowsDesktop;
|
||||
break;
|
||||
case "darwin":
|
||||
this.deviceCache = DeviceType.MacOsDesktop;
|
||||
break;
|
||||
case "linux":
|
||||
default:
|
||||
this.deviceCache = DeviceType.LinuxDesktop;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
getDevice(): DeviceType {
|
||||
if (!this.deviceCache) {
|
||||
switch (process.platform) {
|
||||
case 'win32':
|
||||
this.deviceCache = DeviceType.WindowsDesktop;
|
||||
break;
|
||||
case 'darwin':
|
||||
this.deviceCache = DeviceType.MacOsDesktop;
|
||||
break;
|
||||
case 'linux':
|
||||
default:
|
||||
this.deviceCache = DeviceType.LinuxDesktop;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return this.deviceCache;
|
||||
}
|
||||
|
||||
return this.deviceCache;
|
||||
}
|
||||
getDeviceString(): string {
|
||||
const device = DeviceType[this.getDevice()].toLowerCase();
|
||||
return device.replace("desktop", "");
|
||||
}
|
||||
|
||||
getDeviceString(): string {
|
||||
const device = DeviceType[this.getDevice()].toLowerCase();
|
||||
return device.replace('desktop', '');
|
||||
}
|
||||
isFirefox() {
|
||||
return false;
|
||||
}
|
||||
|
||||
isFirefox() {
|
||||
return false;
|
||||
}
|
||||
isChrome() {
|
||||
return false;
|
||||
}
|
||||
|
||||
isChrome() {
|
||||
return false;
|
||||
}
|
||||
isEdge() {
|
||||
return false;
|
||||
}
|
||||
|
||||
isEdge() {
|
||||
return false;
|
||||
}
|
||||
isOpera() {
|
||||
return false;
|
||||
}
|
||||
|
||||
isOpera() {
|
||||
return false;
|
||||
}
|
||||
isVivaldi() {
|
||||
return false;
|
||||
}
|
||||
|
||||
isVivaldi() {
|
||||
return false;
|
||||
}
|
||||
isSafari() {
|
||||
return false;
|
||||
}
|
||||
|
||||
isSafari() {
|
||||
return false;
|
||||
}
|
||||
isIE() {
|
||||
return false;
|
||||
}
|
||||
|
||||
isIE() {
|
||||
return false;
|
||||
}
|
||||
isMacAppStore() {
|
||||
return false;
|
||||
}
|
||||
|
||||
isMacAppStore() {
|
||||
return false;
|
||||
}
|
||||
isViewOpen() {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
isViewOpen() {
|
||||
return Promise.resolve(false);
|
||||
launchUri(uri: string, options?: any): void {
|
||||
if (process.platform === "linux") {
|
||||
child_process.spawnSync("xdg-open", [uri]);
|
||||
} else {
|
||||
open(uri);
|
||||
}
|
||||
}
|
||||
|
||||
launchUri(uri: string, options?: any): void {
|
||||
if (process.platform === 'linux') {
|
||||
child_process.spawnSync('xdg-open', [uri]);
|
||||
} else {
|
||||
open(uri);
|
||||
}
|
||||
}
|
||||
saveFile(win: Window, blobData: any, blobOptions: any, fileName: string): void {
|
||||
throw new Error("Not implemented.");
|
||||
}
|
||||
|
||||
saveFile(win: Window, blobData: any, blobOptions: any, fileName: string): void {
|
||||
throw new Error('Not implemented.');
|
||||
}
|
||||
getApplicationVersion(): Promise<string> {
|
||||
return Promise.resolve(this.packageJson.version);
|
||||
}
|
||||
|
||||
getApplicationVersion(): Promise<string> {
|
||||
return Promise.resolve(this.packageJson.version);
|
||||
}
|
||||
getApplicationVersionSync(): string {
|
||||
return this.packageJson.version;
|
||||
}
|
||||
|
||||
getApplicationVersionSync(): string {
|
||||
return this.packageJson.version;
|
||||
}
|
||||
supportsWebAuthn(win: Window) {
|
||||
return false;
|
||||
}
|
||||
|
||||
supportsWebAuthn(win: Window) {
|
||||
return false;
|
||||
}
|
||||
supportsDuo(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
supportsDuo(): boolean {
|
||||
return false;
|
||||
}
|
||||
showToast(
|
||||
type: "error" | "success" | "warning" | "info",
|
||||
title: string,
|
||||
text: string | string[],
|
||||
options?: any
|
||||
): void {
|
||||
throw new Error("Not implemented.");
|
||||
}
|
||||
|
||||
showToast(type: 'error' | 'success' | 'warning' | 'info', title: string, text: string | string[],
|
||||
options?: any): void {
|
||||
throw new Error('Not implemented.');
|
||||
}
|
||||
showDialog(
|
||||
text: string,
|
||||
title?: string,
|
||||
confirmText?: string,
|
||||
cancelText?: string,
|
||||
type?: string
|
||||
): Promise<boolean> {
|
||||
throw new Error("Not implemented.");
|
||||
}
|
||||
|
||||
showDialog(text: string, title?: string, confirmText?: string, cancelText?: string, type?: string):
|
||||
Promise<boolean> {
|
||||
throw new Error('Not implemented.');
|
||||
}
|
||||
isDev(): boolean {
|
||||
return process.env.BWCLI_ENV === "development";
|
||||
}
|
||||
|
||||
isDev(): boolean {
|
||||
return process.env.BWCLI_ENV === 'development';
|
||||
}
|
||||
isSelfHost(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
isSelfHost(): boolean {
|
||||
return false;
|
||||
}
|
||||
copyToClipboard(text: string, options?: any): void {
|
||||
throw new Error("Not implemented.");
|
||||
}
|
||||
|
||||
copyToClipboard(text: string, options?: any): void {
|
||||
throw new Error('Not implemented.');
|
||||
}
|
||||
readFromClipboard(options?: any): Promise<string> {
|
||||
throw new Error("Not implemented.");
|
||||
}
|
||||
|
||||
readFromClipboard(options?: any): Promise<string> {
|
||||
throw new Error('Not implemented.');
|
||||
}
|
||||
supportsBiometric(): Promise<boolean> {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
supportsBiometric(): Promise<boolean> {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
authenticateBiometric(): Promise<boolean> {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
authenticateBiometric(): Promise<boolean> {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
getDefaultSystemTheme() {
|
||||
return Promise.resolve(ThemeType.Light as ThemeType.Light | ThemeType.Dark);
|
||||
}
|
||||
|
||||
getDefaultSystemTheme() {
|
||||
return Promise.resolve(ThemeType.Light as ThemeType.Light | ThemeType.Dark);
|
||||
}
|
||||
onDefaultSystemThemeChange() {
|
||||
/* noop */
|
||||
}
|
||||
|
||||
onDefaultSystemThemeChange() {
|
||||
/* noop */
|
||||
}
|
||||
getEffectiveTheme() {
|
||||
return Promise.resolve(ThemeType.Light);
|
||||
}
|
||||
|
||||
getEffectiveTheme() {
|
||||
return Promise.resolve(ThemeType.Light);
|
||||
}
|
||||
|
||||
supportsSecureStorage(): boolean {
|
||||
return false;
|
||||
}
|
||||
supportsSecureStorage(): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
import { LogLevelType } from 'jslib-common/enums/logLevelType';
|
||||
import { LogLevelType } from "jslib-common/enums/logLevelType";
|
||||
|
||||
import { ConsoleLogService as BaseConsoleLogService } from 'jslib-common/services/consoleLog.service';
|
||||
import { ConsoleLogService as BaseConsoleLogService } from "jslib-common/services/consoleLog.service";
|
||||
|
||||
export class ConsoleLogService extends BaseConsoleLogService {
|
||||
constructor(isDev: boolean, filter: (level: LogLevelType) => boolean = null) {
|
||||
super(isDev, filter);
|
||||
constructor(isDev: boolean, filter: (level: LogLevelType) => boolean = null) {
|
||||
super(isDev, filter);
|
||||
}
|
||||
|
||||
write(level: LogLevelType, message: string) {
|
||||
if (this.filter != null && this.filter(level)) {
|
||||
return;
|
||||
}
|
||||
|
||||
write(level: LogLevelType, message: string) {
|
||||
if (this.filter != null && this.filter(level)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (process.env.BW_RESPONSE === 'true') {
|
||||
// tslint:disable-next-line
|
||||
console.error(message);
|
||||
return;
|
||||
}
|
||||
|
||||
super.write(level, message);
|
||||
if (process.env.BW_RESPONSE === "true") {
|
||||
// tslint:disable-next-line
|
||||
console.error(message);
|
||||
return;
|
||||
}
|
||||
|
||||
super.write(level, message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,119 +1,130 @@
|
||||
import * as fs from 'fs';
|
||||
import * as lowdb from 'lowdb';
|
||||
import * as FileSync from 'lowdb/adapters/FileSync';
|
||||
import * as path from 'path';
|
||||
import * as fs from "fs";
|
||||
import * as lowdb from "lowdb";
|
||||
import * as FileSync from "lowdb/adapters/FileSync";
|
||||
import * as path from "path";
|
||||
|
||||
import { LogService } from 'jslib-common/abstractions/log.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
import { LogService } from "jslib-common/abstractions/log.service";
|
||||
import { StorageService } from "jslib-common/abstractions/storage.service";
|
||||
|
||||
import { NodeUtils } from 'jslib-common/misc/nodeUtils';
|
||||
import { Utils } from 'jslib-common/misc/utils';
|
||||
import { NodeUtils } from "jslib-common/misc/nodeUtils";
|
||||
import { Utils } from "jslib-common/misc/utils";
|
||||
|
||||
export class LowdbStorageService implements StorageService {
|
||||
protected dataFilePath: string;
|
||||
private db: lowdb.LowdbSync<any>;
|
||||
private defaults: any;
|
||||
protected dataFilePath: string;
|
||||
private db: lowdb.LowdbSync<any>;
|
||||
private defaults: any;
|
||||
|
||||
constructor(protected logService: LogService, defaults?: any, private dir?: string, private allowCache = false) {
|
||||
this.defaults = defaults;
|
||||
constructor(
|
||||
protected logService: LogService,
|
||||
defaults?: any,
|
||||
private dir?: string,
|
||||
private allowCache = false
|
||||
) {
|
||||
this.defaults = defaults;
|
||||
}
|
||||
|
||||
async init() {
|
||||
this.logService.info("Initializing lowdb storage service.");
|
||||
let adapter: lowdb.AdapterSync<any>;
|
||||
if (Utils.isNode && this.dir != null) {
|
||||
if (!fs.existsSync(this.dir)) {
|
||||
this.logService.warning(`Could not find dir, "${this.dir}"; creating it instead.`);
|
||||
NodeUtils.mkdirpSync(this.dir, "700");
|
||||
this.logService.info(`Created dir "${this.dir}".`);
|
||||
}
|
||||
this.dataFilePath = path.join(this.dir, "data.json");
|
||||
if (!fs.existsSync(this.dataFilePath)) {
|
||||
this.logService.warning(
|
||||
`Could not find data file, "${this.dataFilePath}"; creating it instead.`
|
||||
);
|
||||
fs.writeFileSync(this.dataFilePath, "", { mode: 0o600 });
|
||||
fs.chmodSync(this.dataFilePath, 0o600);
|
||||
this.logService.info(`Created data file "${this.dataFilePath}" with chmod 600.`);
|
||||
} else {
|
||||
this.logService.info(`db file "${this.dataFilePath} already exists"; using existing db`);
|
||||
}
|
||||
await this.lockDbFile(() => {
|
||||
adapter = new FileSync(this.dataFilePath);
|
||||
});
|
||||
}
|
||||
|
||||
async init() {
|
||||
this.logService.info('Initializing lowdb storage service.');
|
||||
let adapter: lowdb.AdapterSync<any>;
|
||||
if (Utils.isNode && this.dir != null) {
|
||||
if (!fs.existsSync(this.dir)) {
|
||||
this.logService.warning(`Could not find dir, "${this.dir}"; creating it instead.`);
|
||||
NodeUtils.mkdirpSync(this.dir, '700');
|
||||
this.logService.info(`Created dir "${this.dir}".`);
|
||||
}
|
||||
this.dataFilePath = path.join(this.dir, 'data.json');
|
||||
if (!fs.existsSync(this.dataFilePath)) {
|
||||
this.logService.warning(`Could not find data file, "${this.dataFilePath}"; creating it instead.`);
|
||||
fs.writeFileSync(this.dataFilePath, '', { mode: 0o600 });
|
||||
fs.chmodSync(this.dataFilePath, 0o600);
|
||||
this.logService.info(`Created data file "${this.dataFilePath}" with chmod 600.`);
|
||||
} else {
|
||||
this.logService.info(`db file "${this.dataFilePath} already exists"; using existing db`);
|
||||
}
|
||||
await this.lockDbFile(() => {
|
||||
adapter = new FileSync(this.dataFilePath);
|
||||
});
|
||||
}
|
||||
try {
|
||||
this.logService.info('Attempting to create lowdb storage adapter.');
|
||||
this.db = lowdb(adapter);
|
||||
this.logService.info('Successfully created lowdb storage adapter.');
|
||||
} catch (e) {
|
||||
if (e instanceof SyntaxError) {
|
||||
this.logService.warning(`Error creating lowdb storage adapter, "${e.message}"; emptying data file.`);
|
||||
if (fs.existsSync(this.dataFilePath)) {
|
||||
const backupPath = this.dataFilePath + '.bak';
|
||||
this.logService.warning(`Writing backup of data file to ${backupPath}`);
|
||||
await fs.copyFile(this.dataFilePath, backupPath, err => {
|
||||
this.logService.warning(`Error while creating data file backup, "${e.message}". No backup may have been created.`);
|
||||
});
|
||||
}
|
||||
adapter.write({});
|
||||
this.db = lowdb(adapter);
|
||||
} else {
|
||||
this.logService.error(`Error creating lowdb storage adapter, "${e.message}".`);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.defaults != null) {
|
||||
this.lockDbFile(() => {
|
||||
this.logService.info('Writing defaults.');
|
||||
this.readForNoCache();
|
||||
this.db.defaults(this.defaults).write();
|
||||
this.logService.info('Successfully wrote defaults to db.');
|
||||
});
|
||||
try {
|
||||
this.logService.info("Attempting to create lowdb storage adapter.");
|
||||
this.db = lowdb(adapter);
|
||||
this.logService.info("Successfully created lowdb storage adapter.");
|
||||
} catch (e) {
|
||||
if (e instanceof SyntaxError) {
|
||||
this.logService.warning(
|
||||
`Error creating lowdb storage adapter, "${e.message}"; emptying data file.`
|
||||
);
|
||||
if (fs.existsSync(this.dataFilePath)) {
|
||||
const backupPath = this.dataFilePath + ".bak";
|
||||
this.logService.warning(`Writing backup of data file to ${backupPath}`);
|
||||
await fs.copyFile(this.dataFilePath, backupPath, (err) => {
|
||||
this.logService.warning(
|
||||
`Error while creating data file backup, "${e.message}". No backup may have been created.`
|
||||
);
|
||||
});
|
||||
}
|
||||
adapter.write({});
|
||||
this.db = lowdb(adapter);
|
||||
} else {
|
||||
this.logService.error(`Error creating lowdb storage adapter, "${e.message}".`);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
get<T>(key: string): Promise<T> {
|
||||
return this.lockDbFile(() => {
|
||||
this.readForNoCache();
|
||||
const val = this.db.get(key).value();
|
||||
this.logService.debug(`Successfully read ${key} from db`);
|
||||
if (val == null) {
|
||||
return null;
|
||||
}
|
||||
return val as T;
|
||||
});
|
||||
if (this.defaults != null) {
|
||||
this.lockDbFile(() => {
|
||||
this.logService.info("Writing defaults.");
|
||||
this.readForNoCache();
|
||||
this.db.defaults(this.defaults).write();
|
||||
this.logService.info("Successfully wrote defaults to db.");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
has(key: string): Promise<boolean> {
|
||||
return this.get(key).then(v => v != null);
|
||||
}
|
||||
get<T>(key: string): Promise<T> {
|
||||
return this.lockDbFile(() => {
|
||||
this.readForNoCache();
|
||||
const val = this.db.get(key).value();
|
||||
this.logService.debug(`Successfully read ${key} from db`);
|
||||
if (val == null) {
|
||||
return null;
|
||||
}
|
||||
return val as T;
|
||||
});
|
||||
}
|
||||
|
||||
save(key: string, obj: any): Promise<any> {
|
||||
return this.lockDbFile(() => {
|
||||
this.readForNoCache();
|
||||
this.db.set(key, obj).write();
|
||||
this.logService.debug(`Successfully wrote ${key} to db`);
|
||||
return;
|
||||
});
|
||||
}
|
||||
has(key: string): Promise<boolean> {
|
||||
return this.get(key).then((v) => v != null);
|
||||
}
|
||||
|
||||
remove(key: string): Promise<any> {
|
||||
return this.lockDbFile(() => {
|
||||
this.readForNoCache();
|
||||
this.db.unset(key).write();
|
||||
this.logService.debug(`Successfully removed ${key} from db`);
|
||||
return;
|
||||
});
|
||||
}
|
||||
save(key: string, obj: any): Promise<any> {
|
||||
return this.lockDbFile(() => {
|
||||
this.readForNoCache();
|
||||
this.db.set(key, obj).write();
|
||||
this.logService.debug(`Successfully wrote ${key} to db`);
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
protected async lockDbFile<T>(action: () => T): Promise<T> {
|
||||
// Lock methods implemented in clients
|
||||
return Promise.resolve(action());
|
||||
}
|
||||
remove(key: string): Promise<any> {
|
||||
return this.lockDbFile(() => {
|
||||
this.readForNoCache();
|
||||
this.db.unset(key).write();
|
||||
this.logService.debug(`Successfully removed ${key} from db`);
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
private readForNoCache() {
|
||||
if (!this.allowCache) {
|
||||
this.db.read();
|
||||
}
|
||||
protected async lockDbFile<T>(action: () => T): Promise<T> {
|
||||
// Lock methods implemented in clients
|
||||
return Promise.resolve(action());
|
||||
}
|
||||
|
||||
private readForNoCache() {
|
||||
if (!this.allowCache) {
|
||||
this.db.read();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import * as FormData from 'form-data';
|
||||
import { HttpsProxyAgent } from 'https-proxy-agent';
|
||||
import * as fe from 'node-fetch';
|
||||
import * as FormData from "form-data";
|
||||
import { HttpsProxyAgent } from "https-proxy-agent";
|
||||
import * as fe from "node-fetch";
|
||||
|
||||
import { ApiService } from 'jslib-common/services/api.service';
|
||||
import { ApiService } from "jslib-common/services/api.service";
|
||||
|
||||
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { TokenService } from 'jslib-common/abstractions/token.service';
|
||||
import { EnvironmentService } from "jslib-common/abstractions/environment.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
import { TokenService } from "jslib-common/abstractions/token.service";
|
||||
|
||||
(global as any).fetch = fe.default;
|
||||
(global as any).Request = fe.Request;
|
||||
@@ -15,18 +15,23 @@ import { TokenService } from 'jslib-common/abstractions/token.service';
|
||||
(global as any).FormData = FormData;
|
||||
|
||||
export class NodeApiService extends ApiService {
|
||||
constructor(tokenService: TokenService, platformUtilsService: PlatformUtilsService,
|
||||
environmentService: EnvironmentService, logoutCallback: (expired: boolean) => Promise<void>,
|
||||
customUserAgent: string = null, apiKeyRefresh: (clientId: string, clientSecret: string) => Promise<any>) {
|
||||
super(tokenService, platformUtilsService, environmentService, logoutCallback, customUserAgent);
|
||||
this.apiKeyRefresh = apiKeyRefresh;
|
||||
}
|
||||
constructor(
|
||||
tokenService: TokenService,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
environmentService: EnvironmentService,
|
||||
logoutCallback: (expired: boolean) => Promise<void>,
|
||||
customUserAgent: string = null,
|
||||
apiKeyRefresh: (clientId: string, clientSecret: string) => Promise<any>
|
||||
) {
|
||||
super(tokenService, platformUtilsService, environmentService, logoutCallback, customUserAgent);
|
||||
this.apiKeyRefresh = apiKeyRefresh;
|
||||
}
|
||||
|
||||
nativeFetch(request: Request): Promise<Response> {
|
||||
const proxy = process.env.http_proxy || process.env.https_proxy;
|
||||
if (proxy) {
|
||||
(request as any).agent = new HttpsProxyAgent(proxy);
|
||||
}
|
||||
return fetch(request);
|
||||
nativeFetch(request: Request): Promise<Response> {
|
||||
const proxy = process.env.http_proxy || process.env.https_proxy;
|
||||
if (proxy) {
|
||||
(request as any).agent = new HttpsProxyAgent(proxy);
|
||||
}
|
||||
return fetch(request);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,263 +1,302 @@
|
||||
import * as crypto from 'crypto';
|
||||
import * as forge from 'node-forge';
|
||||
import * as crypto from "crypto";
|
||||
import * as forge from "node-forge";
|
||||
|
||||
import { CryptoFunctionService } from 'jslib-common/abstractions/cryptoFunction.service';
|
||||
import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service";
|
||||
|
||||
import { DecryptParameters } from 'jslib-common/models/domain/decryptParameters';
|
||||
import { SymmetricCryptoKey } from 'jslib-common/models/domain/symmetricCryptoKey';
|
||||
import { DecryptParameters } from "jslib-common/models/domain/decryptParameters";
|
||||
import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey";
|
||||
|
||||
import { Utils } from 'jslib-common/misc/utils';
|
||||
import { Utils } from "jslib-common/misc/utils";
|
||||
|
||||
export class NodeCryptoFunctionService implements CryptoFunctionService {
|
||||
pbkdf2(password: string | ArrayBuffer, salt: string | ArrayBuffer, algorithm: 'sha256' | 'sha512',
|
||||
iterations: number): Promise<ArrayBuffer> {
|
||||
const len = algorithm === 'sha256' ? 32 : 64;
|
||||
const nodePassword = this.toNodeValue(password);
|
||||
const nodeSalt = this.toNodeValue(salt);
|
||||
return new Promise<ArrayBuffer>((resolve, reject) => {
|
||||
crypto.pbkdf2(nodePassword, nodeSalt, iterations, len, algorithm, (error, key) => {
|
||||
if (error != null) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(this.toArrayBuffer(key));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ref: https://tools.ietf.org/html/rfc5869
|
||||
async hkdf(ikm: ArrayBuffer, salt: string | ArrayBuffer, info: string | ArrayBuffer,
|
||||
outputByteSize: number, algorithm: 'sha256' | 'sha512'): Promise<ArrayBuffer> {
|
||||
const saltBuf = this.toArrayBuffer(salt);
|
||||
const prk = await this.hmac(ikm, saltBuf, algorithm);
|
||||
return this.hkdfExpand(prk, info, outputByteSize, algorithm);
|
||||
}
|
||||
|
||||
// ref: https://tools.ietf.org/html/rfc5869
|
||||
async hkdfExpand(prk: ArrayBuffer, info: string | ArrayBuffer, outputByteSize: number,
|
||||
algorithm: 'sha256' | 'sha512'): Promise<ArrayBuffer> {
|
||||
const hashLen = algorithm === 'sha256' ? 32 : 64;
|
||||
if (outputByteSize > 255 * hashLen) {
|
||||
throw new Error('outputByteSize is too large.');
|
||||
}
|
||||
const prkArr = new Uint8Array(prk);
|
||||
if (prkArr.length < hashLen) {
|
||||
throw new Error('prk is too small.');
|
||||
}
|
||||
const infoBuf = this.toArrayBuffer(info);
|
||||
const infoArr = new Uint8Array(infoBuf);
|
||||
let runningOkmLength = 0;
|
||||
let previousT = new Uint8Array(0);
|
||||
const n = Math.ceil(outputByteSize / hashLen);
|
||||
const okm = new Uint8Array(n * hashLen);
|
||||
for (let i = 0; i < n; i++) {
|
||||
const t = new Uint8Array(previousT.length + infoArr.length + 1);
|
||||
t.set(previousT);
|
||||
t.set(infoArr, previousT.length);
|
||||
t.set([i + 1], t.length - 1);
|
||||
previousT = new Uint8Array(await this.hmac(t.buffer, prk, algorithm));
|
||||
okm.set(previousT, runningOkmLength);
|
||||
runningOkmLength += previousT.length;
|
||||
if (runningOkmLength >= outputByteSize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return okm.slice(0, outputByteSize).buffer;
|
||||
}
|
||||
|
||||
hash(value: string | ArrayBuffer, algorithm: 'sha1' | 'sha256' | 'sha512' | 'md5'): Promise<ArrayBuffer> {
|
||||
const nodeValue = this.toNodeValue(value);
|
||||
const hash = crypto.createHash(algorithm);
|
||||
hash.update(nodeValue);
|
||||
return Promise.resolve(this.toArrayBuffer(hash.digest()));
|
||||
}
|
||||
|
||||
hmac(value: ArrayBuffer, key: ArrayBuffer, algorithm: 'sha1' | 'sha256' | 'sha512'): Promise<ArrayBuffer> {
|
||||
const nodeValue = this.toNodeBuffer(value);
|
||||
const nodeKey = this.toNodeBuffer(key);
|
||||
const hmac = crypto.createHmac(algorithm, nodeKey);
|
||||
hmac.update(nodeValue);
|
||||
return Promise.resolve(this.toArrayBuffer(hmac.digest()));
|
||||
}
|
||||
|
||||
async compare(a: ArrayBuffer, b: ArrayBuffer): Promise<boolean> {
|
||||
const key = await this.randomBytes(32);
|
||||
const mac1 = await this.hmac(a, key, 'sha256');
|
||||
const mac2 = await this.hmac(b, key, 'sha256');
|
||||
if (mac1.byteLength !== mac2.byteLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const arr1 = new Uint8Array(mac1);
|
||||
const arr2 = new Uint8Array(mac2);
|
||||
for (let i = 0; i < arr2.length; i++) {
|
||||
if (arr1[i] !== arr2[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
hmacFast(value: ArrayBuffer, key: ArrayBuffer, algorithm: 'sha1' | 'sha256' | 'sha512'): Promise<ArrayBuffer> {
|
||||
return this.hmac(value, key, algorithm);
|
||||
}
|
||||
|
||||
compareFast(a: ArrayBuffer, b: ArrayBuffer): Promise<boolean> {
|
||||
return this.compare(a, b);
|
||||
}
|
||||
|
||||
aesEncrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise<ArrayBuffer> {
|
||||
const nodeData = this.toNodeBuffer(data);
|
||||
const nodeIv = this.toNodeBuffer(iv);
|
||||
const nodeKey = this.toNodeBuffer(key);
|
||||
const cipher = crypto.createCipheriv('aes-256-cbc', nodeKey, nodeIv);
|
||||
const encBuf = Buffer.concat([cipher.update(nodeData), cipher.final()]);
|
||||
return Promise.resolve(this.toArrayBuffer(encBuf));
|
||||
}
|
||||
|
||||
aesDecryptFastParameters(data: string, iv: string, mac: string, key: SymmetricCryptoKey):
|
||||
DecryptParameters<ArrayBuffer> {
|
||||
const p = new DecryptParameters<ArrayBuffer>();
|
||||
p.encKey = key.encKey;
|
||||
p.data = Utils.fromB64ToArray(data).buffer;
|
||||
p.iv = Utils.fromB64ToArray(iv).buffer;
|
||||
|
||||
const macData = new Uint8Array(p.iv.byteLength + p.data.byteLength);
|
||||
macData.set(new Uint8Array(p.iv), 0);
|
||||
macData.set(new Uint8Array(p.data), p.iv.byteLength);
|
||||
p.macData = macData.buffer;
|
||||
|
||||
if (key.macKey != null) {
|
||||
p.macKey = key.macKey;
|
||||
}
|
||||
if (mac != null) {
|
||||
p.mac = Utils.fromB64ToArray(mac).buffer;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
async aesDecryptFast(parameters: DecryptParameters<ArrayBuffer>): Promise<string> {
|
||||
const decBuf = await this.aesDecrypt(parameters.data, parameters.iv, parameters.encKey);
|
||||
return Utils.fromBufferToUtf8(decBuf);
|
||||
}
|
||||
|
||||
aesDecrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise<ArrayBuffer> {
|
||||
const nodeData = this.toNodeBuffer(data);
|
||||
const nodeIv = this.toNodeBuffer(iv);
|
||||
const nodeKey = this.toNodeBuffer(key);
|
||||
const decipher = crypto.createDecipheriv('aes-256-cbc', nodeKey, nodeIv);
|
||||
const decBuf = Buffer.concat([decipher.update(nodeData), decipher.final()]);
|
||||
return Promise.resolve(this.toArrayBuffer(decBuf));
|
||||
}
|
||||
|
||||
rsaEncrypt(data: ArrayBuffer, publicKey: ArrayBuffer, algorithm: 'sha1' | 'sha256'): Promise<ArrayBuffer> {
|
||||
if (algorithm === 'sha256') {
|
||||
throw new Error('Node crypto does not support RSA-OAEP SHA-256');
|
||||
}
|
||||
|
||||
const pem = this.toPemPublicKey(publicKey);
|
||||
const decipher = crypto.publicEncrypt(pem, this.toNodeBuffer(data));
|
||||
return Promise.resolve(this.toArrayBuffer(decipher));
|
||||
}
|
||||
|
||||
rsaDecrypt(data: ArrayBuffer, privateKey: ArrayBuffer, algorithm: 'sha1' | 'sha256'): Promise<ArrayBuffer> {
|
||||
if (algorithm === 'sha256') {
|
||||
throw new Error('Node crypto does not support RSA-OAEP SHA-256');
|
||||
}
|
||||
|
||||
const pem = this.toPemPrivateKey(privateKey);
|
||||
const decipher = crypto.privateDecrypt(pem, this.toNodeBuffer(data));
|
||||
return Promise.resolve(this.toArrayBuffer(decipher));
|
||||
}
|
||||
|
||||
rsaExtractPublicKey(privateKey: ArrayBuffer): Promise<ArrayBuffer> {
|
||||
const privateKeyByteString = Utils.fromBufferToByteString(privateKey);
|
||||
const privateKeyAsn1 = forge.asn1.fromDer(privateKeyByteString);
|
||||
const forgePrivateKey = (forge as any).pki.privateKeyFromAsn1(privateKeyAsn1);
|
||||
const forgePublicKey = (forge.pki as any).setRsaPublicKey(forgePrivateKey.n, forgePrivateKey.e);
|
||||
const publicKeyAsn1 = (forge.pki as any).publicKeyToAsn1(forgePublicKey);
|
||||
const publicKeyByteString = forge.asn1.toDer(publicKeyAsn1).data;
|
||||
const publicKeyArray = Utils.fromByteStringToArray(publicKeyByteString);
|
||||
return Promise.resolve(publicKeyArray.buffer);
|
||||
}
|
||||
|
||||
async rsaGenerateKeyPair(length: 1024 | 2048 | 4096): Promise<[ArrayBuffer, ArrayBuffer]> {
|
||||
return new Promise<[ArrayBuffer, ArrayBuffer]>((resolve, reject) => {
|
||||
forge.pki.rsa.generateKeyPair({
|
||||
bits: length,
|
||||
workers: -1,
|
||||
e: 0x10001, // 65537
|
||||
}, (error, keyPair) => {
|
||||
if (error != null) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
const publicKeyAsn1 = (forge.pki as any).publicKeyToAsn1(keyPair.publicKey);
|
||||
const publicKeyByteString = forge.asn1.toDer(publicKeyAsn1).getBytes();
|
||||
const publicKey = Utils.fromByteStringToArray(publicKeyByteString);
|
||||
|
||||
const privateKeyAsn1 = (forge.pki as any).privateKeyToAsn1(keyPair.privateKey);
|
||||
const privateKeyPkcs8 = (forge.pki as any).wrapRsaPrivateKey(privateKeyAsn1);
|
||||
const privateKeyByteString = forge.asn1.toDer(privateKeyPkcs8).getBytes();
|
||||
const privateKey = Utils.fromByteStringToArray(privateKeyByteString);
|
||||
|
||||
resolve([publicKey.buffer, privateKey.buffer]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
randomBytes(length: number): Promise<ArrayBuffer> {
|
||||
return new Promise<ArrayBuffer>((resolve, reject) => {
|
||||
crypto.randomBytes(length, (error, bytes) => {
|
||||
if (error != null) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(this.toArrayBuffer(bytes));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private toNodeValue(value: string | ArrayBuffer): string | Buffer {
|
||||
let nodeValue: string | Buffer;
|
||||
if (typeof (value) === 'string') {
|
||||
nodeValue = value;
|
||||
pbkdf2(
|
||||
password: string | ArrayBuffer,
|
||||
salt: string | ArrayBuffer,
|
||||
algorithm: "sha256" | "sha512",
|
||||
iterations: number
|
||||
): Promise<ArrayBuffer> {
|
||||
const len = algorithm === "sha256" ? 32 : 64;
|
||||
const nodePassword = this.toNodeValue(password);
|
||||
const nodeSalt = this.toNodeValue(salt);
|
||||
return new Promise<ArrayBuffer>((resolve, reject) => {
|
||||
crypto.pbkdf2(nodePassword, nodeSalt, iterations, len, algorithm, (error, key) => {
|
||||
if (error != null) {
|
||||
reject(error);
|
||||
} else {
|
||||
nodeValue = this.toNodeBuffer(value);
|
||||
resolve(this.toArrayBuffer(key));
|
||||
}
|
||||
return nodeValue;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ref: https://tools.ietf.org/html/rfc5869
|
||||
async hkdf(
|
||||
ikm: ArrayBuffer,
|
||||
salt: string | ArrayBuffer,
|
||||
info: string | ArrayBuffer,
|
||||
outputByteSize: number,
|
||||
algorithm: "sha256" | "sha512"
|
||||
): Promise<ArrayBuffer> {
|
||||
const saltBuf = this.toArrayBuffer(salt);
|
||||
const prk = await this.hmac(ikm, saltBuf, algorithm);
|
||||
return this.hkdfExpand(prk, info, outputByteSize, algorithm);
|
||||
}
|
||||
|
||||
// ref: https://tools.ietf.org/html/rfc5869
|
||||
async hkdfExpand(
|
||||
prk: ArrayBuffer,
|
||||
info: string | ArrayBuffer,
|
||||
outputByteSize: number,
|
||||
algorithm: "sha256" | "sha512"
|
||||
): Promise<ArrayBuffer> {
|
||||
const hashLen = algorithm === "sha256" ? 32 : 64;
|
||||
if (outputByteSize > 255 * hashLen) {
|
||||
throw new Error("outputByteSize is too large.");
|
||||
}
|
||||
const prkArr = new Uint8Array(prk);
|
||||
if (prkArr.length < hashLen) {
|
||||
throw new Error("prk is too small.");
|
||||
}
|
||||
const infoBuf = this.toArrayBuffer(info);
|
||||
const infoArr = new Uint8Array(infoBuf);
|
||||
let runningOkmLength = 0;
|
||||
let previousT = new Uint8Array(0);
|
||||
const n = Math.ceil(outputByteSize / hashLen);
|
||||
const okm = new Uint8Array(n * hashLen);
|
||||
for (let i = 0; i < n; i++) {
|
||||
const t = new Uint8Array(previousT.length + infoArr.length + 1);
|
||||
t.set(previousT);
|
||||
t.set(infoArr, previousT.length);
|
||||
t.set([i + 1], t.length - 1);
|
||||
previousT = new Uint8Array(await this.hmac(t.buffer, prk, algorithm));
|
||||
okm.set(previousT, runningOkmLength);
|
||||
runningOkmLength += previousT.length;
|
||||
if (runningOkmLength >= outputByteSize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return okm.slice(0, outputByteSize).buffer;
|
||||
}
|
||||
|
||||
hash(
|
||||
value: string | ArrayBuffer,
|
||||
algorithm: "sha1" | "sha256" | "sha512" | "md5"
|
||||
): Promise<ArrayBuffer> {
|
||||
const nodeValue = this.toNodeValue(value);
|
||||
const hash = crypto.createHash(algorithm);
|
||||
hash.update(nodeValue);
|
||||
return Promise.resolve(this.toArrayBuffer(hash.digest()));
|
||||
}
|
||||
|
||||
hmac(
|
||||
value: ArrayBuffer,
|
||||
key: ArrayBuffer,
|
||||
algorithm: "sha1" | "sha256" | "sha512"
|
||||
): Promise<ArrayBuffer> {
|
||||
const nodeValue = this.toNodeBuffer(value);
|
||||
const nodeKey = this.toNodeBuffer(key);
|
||||
const hmac = crypto.createHmac(algorithm, nodeKey);
|
||||
hmac.update(nodeValue);
|
||||
return Promise.resolve(this.toArrayBuffer(hmac.digest()));
|
||||
}
|
||||
|
||||
async compare(a: ArrayBuffer, b: ArrayBuffer): Promise<boolean> {
|
||||
const key = await this.randomBytes(32);
|
||||
const mac1 = await this.hmac(a, key, "sha256");
|
||||
const mac2 = await this.hmac(b, key, "sha256");
|
||||
if (mac1.byteLength !== mac2.byteLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private toNodeBuffer(value: ArrayBuffer): Buffer {
|
||||
return Buffer.from(new Uint8Array(value) as any);
|
||||
const arr1 = new Uint8Array(mac1);
|
||||
const arr2 = new Uint8Array(mac2);
|
||||
for (let i = 0; i < arr2.length; i++) {
|
||||
if (arr1[i] !== arr2[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private toArrayBuffer(value: Buffer | string | ArrayBuffer): ArrayBuffer {
|
||||
let buf: ArrayBuffer;
|
||||
if (typeof (value) === 'string') {
|
||||
buf = Utils.fromUtf8ToArray(value).buffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
hmacFast(
|
||||
value: ArrayBuffer,
|
||||
key: ArrayBuffer,
|
||||
algorithm: "sha1" | "sha256" | "sha512"
|
||||
): Promise<ArrayBuffer> {
|
||||
return this.hmac(value, key, algorithm);
|
||||
}
|
||||
|
||||
compareFast(a: ArrayBuffer, b: ArrayBuffer): Promise<boolean> {
|
||||
return this.compare(a, b);
|
||||
}
|
||||
|
||||
aesEncrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise<ArrayBuffer> {
|
||||
const nodeData = this.toNodeBuffer(data);
|
||||
const nodeIv = this.toNodeBuffer(iv);
|
||||
const nodeKey = this.toNodeBuffer(key);
|
||||
const cipher = crypto.createCipheriv("aes-256-cbc", nodeKey, nodeIv);
|
||||
const encBuf = Buffer.concat([cipher.update(nodeData), cipher.final()]);
|
||||
return Promise.resolve(this.toArrayBuffer(encBuf));
|
||||
}
|
||||
|
||||
aesDecryptFastParameters(
|
||||
data: string,
|
||||
iv: string,
|
||||
mac: string,
|
||||
key: SymmetricCryptoKey
|
||||
): DecryptParameters<ArrayBuffer> {
|
||||
const p = new DecryptParameters<ArrayBuffer>();
|
||||
p.encKey = key.encKey;
|
||||
p.data = Utils.fromB64ToArray(data).buffer;
|
||||
p.iv = Utils.fromB64ToArray(iv).buffer;
|
||||
|
||||
const macData = new Uint8Array(p.iv.byteLength + p.data.byteLength);
|
||||
macData.set(new Uint8Array(p.iv), 0);
|
||||
macData.set(new Uint8Array(p.data), p.iv.byteLength);
|
||||
p.macData = macData.buffer;
|
||||
|
||||
if (key.macKey != null) {
|
||||
p.macKey = key.macKey;
|
||||
}
|
||||
if (mac != null) {
|
||||
p.mac = Utils.fromB64ToArray(mac).buffer;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
async aesDecryptFast(parameters: DecryptParameters<ArrayBuffer>): Promise<string> {
|
||||
const decBuf = await this.aesDecrypt(parameters.data, parameters.iv, parameters.encKey);
|
||||
return Utils.fromBufferToUtf8(decBuf);
|
||||
}
|
||||
|
||||
aesDecrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise<ArrayBuffer> {
|
||||
const nodeData = this.toNodeBuffer(data);
|
||||
const nodeIv = this.toNodeBuffer(iv);
|
||||
const nodeKey = this.toNodeBuffer(key);
|
||||
const decipher = crypto.createDecipheriv("aes-256-cbc", nodeKey, nodeIv);
|
||||
const decBuf = Buffer.concat([decipher.update(nodeData), decipher.final()]);
|
||||
return Promise.resolve(this.toArrayBuffer(decBuf));
|
||||
}
|
||||
|
||||
rsaEncrypt(
|
||||
data: ArrayBuffer,
|
||||
publicKey: ArrayBuffer,
|
||||
algorithm: "sha1" | "sha256"
|
||||
): Promise<ArrayBuffer> {
|
||||
if (algorithm === "sha256") {
|
||||
throw new Error("Node crypto does not support RSA-OAEP SHA-256");
|
||||
}
|
||||
|
||||
const pem = this.toPemPublicKey(publicKey);
|
||||
const decipher = crypto.publicEncrypt(pem, this.toNodeBuffer(data));
|
||||
return Promise.resolve(this.toArrayBuffer(decipher));
|
||||
}
|
||||
|
||||
rsaDecrypt(
|
||||
data: ArrayBuffer,
|
||||
privateKey: ArrayBuffer,
|
||||
algorithm: "sha1" | "sha256"
|
||||
): Promise<ArrayBuffer> {
|
||||
if (algorithm === "sha256") {
|
||||
throw new Error("Node crypto does not support RSA-OAEP SHA-256");
|
||||
}
|
||||
|
||||
const pem = this.toPemPrivateKey(privateKey);
|
||||
const decipher = crypto.privateDecrypt(pem, this.toNodeBuffer(data));
|
||||
return Promise.resolve(this.toArrayBuffer(decipher));
|
||||
}
|
||||
|
||||
rsaExtractPublicKey(privateKey: ArrayBuffer): Promise<ArrayBuffer> {
|
||||
const privateKeyByteString = Utils.fromBufferToByteString(privateKey);
|
||||
const privateKeyAsn1 = forge.asn1.fromDer(privateKeyByteString);
|
||||
const forgePrivateKey = (forge as any).pki.privateKeyFromAsn1(privateKeyAsn1);
|
||||
const forgePublicKey = (forge.pki as any).setRsaPublicKey(forgePrivateKey.n, forgePrivateKey.e);
|
||||
const publicKeyAsn1 = (forge.pki as any).publicKeyToAsn1(forgePublicKey);
|
||||
const publicKeyByteString = forge.asn1.toDer(publicKeyAsn1).data;
|
||||
const publicKeyArray = Utils.fromByteStringToArray(publicKeyByteString);
|
||||
return Promise.resolve(publicKeyArray.buffer);
|
||||
}
|
||||
|
||||
async rsaGenerateKeyPair(length: 1024 | 2048 | 4096): Promise<[ArrayBuffer, ArrayBuffer]> {
|
||||
return new Promise<[ArrayBuffer, ArrayBuffer]>((resolve, reject) => {
|
||||
forge.pki.rsa.generateKeyPair(
|
||||
{
|
||||
bits: length,
|
||||
workers: -1,
|
||||
e: 0x10001, // 65537
|
||||
},
|
||||
(error, keyPair) => {
|
||||
if (error != null) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
const publicKeyAsn1 = (forge.pki as any).publicKeyToAsn1(keyPair.publicKey);
|
||||
const publicKeyByteString = forge.asn1.toDer(publicKeyAsn1).getBytes();
|
||||
const publicKey = Utils.fromByteStringToArray(publicKeyByteString);
|
||||
|
||||
const privateKeyAsn1 = (forge.pki as any).privateKeyToAsn1(keyPair.privateKey);
|
||||
const privateKeyPkcs8 = (forge.pki as any).wrapRsaPrivateKey(privateKeyAsn1);
|
||||
const privateKeyByteString = forge.asn1.toDer(privateKeyPkcs8).getBytes();
|
||||
const privateKey = Utils.fromByteStringToArray(privateKeyByteString);
|
||||
|
||||
resolve([publicKey.buffer, privateKey.buffer]);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
randomBytes(length: number): Promise<ArrayBuffer> {
|
||||
return new Promise<ArrayBuffer>((resolve, reject) => {
|
||||
crypto.randomBytes(length, (error, bytes) => {
|
||||
if (error != null) {
|
||||
reject(error);
|
||||
} else {
|
||||
buf = new Uint8Array(value).buffer;
|
||||
resolve(this.toArrayBuffer(bytes));
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private toPemPrivateKey(key: ArrayBuffer): string {
|
||||
const byteString = Utils.fromBufferToByteString(key);
|
||||
const asn1 = forge.asn1.fromDer(byteString);
|
||||
const privateKey = (forge as any).pki.privateKeyFromAsn1(asn1);
|
||||
const rsaPrivateKey = (forge.pki as any).privateKeyToAsn1(privateKey);
|
||||
const privateKeyInfo = (forge.pki as any).wrapRsaPrivateKey(rsaPrivateKey);
|
||||
return (forge.pki as any).privateKeyInfoToPem(privateKeyInfo);
|
||||
private toNodeValue(value: string | ArrayBuffer): string | Buffer {
|
||||
let nodeValue: string | Buffer;
|
||||
if (typeof value === "string") {
|
||||
nodeValue = value;
|
||||
} else {
|
||||
nodeValue = this.toNodeBuffer(value);
|
||||
}
|
||||
return nodeValue;
|
||||
}
|
||||
|
||||
private toPemPublicKey(key: ArrayBuffer): string {
|
||||
const byteString = Utils.fromBufferToByteString(key);
|
||||
const asn1 = forge.asn1.fromDer(byteString);
|
||||
const publicKey = (forge as any).pki.publicKeyFromAsn1(asn1);
|
||||
return (forge.pki as any).publicKeyToPem(publicKey);
|
||||
private toNodeBuffer(value: ArrayBuffer): Buffer {
|
||||
return Buffer.from(new Uint8Array(value) as any);
|
||||
}
|
||||
|
||||
private toArrayBuffer(value: Buffer | string | ArrayBuffer): ArrayBuffer {
|
||||
let buf: ArrayBuffer;
|
||||
if (typeof value === "string") {
|
||||
buf = Utils.fromUtf8ToArray(value).buffer;
|
||||
} else {
|
||||
buf = new Uint8Array(value).buffer;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
private toPemPrivateKey(key: ArrayBuffer): string {
|
||||
const byteString = Utils.fromBufferToByteString(key);
|
||||
const asn1 = forge.asn1.fromDer(byteString);
|
||||
const privateKey = (forge as any).pki.privateKeyFromAsn1(asn1);
|
||||
const rsaPrivateKey = (forge.pki as any).privateKeyToAsn1(privateKey);
|
||||
const privateKeyInfo = (forge.pki as any).wrapRsaPrivateKey(rsaPrivateKey);
|
||||
return (forge.pki as any).privateKeyInfoToPem(privateKeyInfo);
|
||||
}
|
||||
|
||||
private toPemPublicKey(key: ArrayBuffer): string {
|
||||
const byteString = Utils.fromBufferToByteString(key);
|
||||
const asn1 = forge.asn1.fromDer(byteString);
|
||||
const publicKey = (forge as any).pki.publicKeyFromAsn1(asn1);
|
||||
return (forge.pki as any).publicKeyToPem(publicKey);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,17 +15,9 @@
|
||||
"outDir": "dist",
|
||||
"types": [],
|
||||
"paths": {
|
||||
"jslib-common/*": [
|
||||
"../common/src/*"
|
||||
]
|
||||
"jslib-common/*": ["../common/src/*"]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"src",
|
||||
"spec"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist"
|
||||
]
|
||||
"include": ["src", "spec"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user