1
0
mirror of https://github.com/bitwarden/directory-connector synced 2025-12-13 23:03:19 +00:00

Compare commits

..

2 Commits

Author SHA1 Message Date
renovate[bot]
9a719c9e4e [deps]: Update glob to v13 (#950)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-12 14:35:36 -06:00
renovate[bot]
2f49f4d5f1 [deps]: Update jest-mock-extended to v4 (#868)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-12 14:42:43 +00:00
29 changed files with 197 additions and 208 deletions

View File

@@ -1,7 +1,6 @@
dist
build
build-cli
coverage
webpack.cli.js
webpack.main.js
webpack.renderer.js

View File

@@ -1,7 +1,7 @@
import { Directive, ElementRef, Input, NgZone } from "@angular/core";
import { take } from "rxjs/operators";
import Utils from "@/jslib/common/src/misc/utils";
import { Utils } from "@/jslib/common/src/misc/utils";
@Directive({
selector: "[appAutofocus]",

View File

@@ -17,48 +17,45 @@ describe("SymmetricCryptoKey", () => {
const key = makeStaticByteArray(32);
const cryptoKey = new SymmetricCryptoKey(key);
expect(cryptoKey.encType).toBe(0);
expect(cryptoKey.keyB64).toBe("AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=");
expect(cryptoKey.encKeyB64).toBe("AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=");
expect(cryptoKey.macKey).toBeNull();
expect(cryptoKey.key).toBeInstanceOf(ArrayBuffer);
expect(cryptoKey.encKey).toBeInstanceOf(ArrayBuffer);
expect(cryptoKey.key.byteLength).toBe(32);
expect(cryptoKey.encKey.byteLength).toBe(32);
expect(cryptoKey).toEqual({
encKey: key,
encKeyB64: "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=",
encType: 0,
key: key,
keyB64: "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=",
macKey: null,
});
});
it("AesCbc128_HmacSha256_B64", () => {
const key = makeStaticByteArray(32);
const cryptoKey = new SymmetricCryptoKey(key, EncryptionType.AesCbc128_HmacSha256_B64);
// After TS 5.9 upgrade, properties are ArrayBuffer not Uint8Array
expect(cryptoKey.encType).toBe(1);
expect(cryptoKey.keyB64).toBe("AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=");
expect(cryptoKey.encKeyB64).toBe("AAECAwQFBgcICQoLDA0ODw==");
expect(cryptoKey.macKeyB64).toBe("EBESExQVFhcYGRobHB0eHw==");
expect(cryptoKey.key).toBeInstanceOf(ArrayBuffer);
expect(cryptoKey.encKey).toBeInstanceOf(ArrayBuffer);
expect(cryptoKey.macKey).toBeInstanceOf(ArrayBuffer);
expect(cryptoKey.key.byteLength).toBe(32);
expect(cryptoKey.encKey.byteLength).toBe(16);
expect(cryptoKey.macKey.byteLength).toBe(16);
expect(cryptoKey).toEqual({
encKey: key.slice(0, 16),
encKeyB64: "AAECAwQFBgcICQoLDA0ODw==",
encType: 1,
key: key,
keyB64: "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=",
macKey: key.slice(16, 32),
macKeyB64: "EBESExQVFhcYGRobHB0eHw==",
});
});
it("AesCbc256_HmacSha256_B64", () => {
const key = makeStaticByteArray(64);
const cryptoKey = new SymmetricCryptoKey(key);
// After TS 5.9 upgrade, properties are ArrayBuffer not Uint8Array
expect(cryptoKey.encType).toBe(2);
expect(cryptoKey.keyB64).toBe("AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+Pw==");
expect(cryptoKey.encKeyB64).toBe("AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=");
expect(cryptoKey.macKeyB64).toBe("ICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj8=");
expect(cryptoKey.key).toBeInstanceOf(ArrayBuffer);
expect(cryptoKey.encKey).toBeInstanceOf(ArrayBuffer);
expect(cryptoKey.macKey).toBeInstanceOf(ArrayBuffer);
expect(cryptoKey.key.byteLength).toBe(64);
expect(cryptoKey.encKey.byteLength).toBe(32);
expect(cryptoKey.macKey.byteLength).toBe(32);
expect(cryptoKey).toEqual({
encKey: key.slice(0, 32),
encKeyB64: "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=",
encType: 2,
key: key,
keyB64:
"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+Pw==",
macKey: key.slice(32, 64),
macKeyB64: "ICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj8=",
});
});
it("unknown length", () => {

View File

@@ -29,6 +29,6 @@ export class NodeUtils {
// https://stackoverflow.com/a/31394257
static bufferToArrayBuffer(buf: Buffer): ArrayBuffer {
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) as ArrayBuffer;
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
}
}

View File

@@ -1,13 +1,11 @@
/* eslint-disable no-useless-escape */
import url from "url";
import { I18nService } from "../abstractions/i18n.service";
import * as tldjs from "tldjs";
const nodeURL = typeof window === "undefined" ? url : null;
const nodeURL = typeof window === "undefined" ? require("url") : null;
class Utils {
export class Utils {
static inited = false;
static isNode = false;
static isBrowser = true;
@@ -36,11 +34,9 @@ class Utils {
Utils.global = Utils.isNode && !Utils.isBrowser ? global : window;
}
static fromB64ToArray(str: string): Uint8Array<ArrayBuffer> {
static fromB64ToArray(str: string): Uint8Array {
if (Utils.isNode) {
const buffer = Buffer.from(str, "base64");
return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength) as Uint8Array<ArrayBuffer>;
return new Uint8Array(Buffer.from(str, "base64"));
} else {
const binaryString = window.atob(str);
const bytes = new Uint8Array(binaryString.length);
@@ -51,7 +47,7 @@ class Utils {
}
}
static fromUrlB64ToArray(str: string): Uint8Array<ArrayBuffer> {
static fromUrlB64ToArray(str: string): Uint8Array {
return Utils.fromB64ToArray(Utils.fromUrlB64ToB64(str));
}
@@ -67,11 +63,9 @@ class Utils {
}
}
static fromUtf8ToArray(str: string): Uint8Array<ArrayBuffer> {
static fromUtf8ToArray(str: string): Uint8Array {
if (Utils.isNode) {
const buffer = Buffer.from(str, "utf8");
return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength) as Uint8Array<ArrayBuffer>;
return new Uint8Array(Buffer.from(str, "utf8"));
} else {
const strUtf8 = unescape(encodeURIComponent(str));
const arr = new Uint8Array(strUtf8.length);
@@ -90,16 +84,12 @@ class Utils {
return arr;
}
static fromBufferToB64(buffer: BufferSource): string {
static fromBufferToB64(buffer: ArrayBuffer): string {
if (Utils.isNode) {
if (ArrayBuffer.isView(buffer)) {
return Buffer.from(buffer.buffer, buffer.byteOffset, buffer.byteLength).toString("base64");
} else {
return Buffer.from(buffer).toString("base64");
}
return Buffer.from(buffer).toString("base64");
} else {
let binary = "";
const bytes = ArrayBuffer.isView(buffer) ? new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength) : new Uint8Array(buffer);
const bytes = new Uint8Array(buffer);
for (let i = 0; i < bytes.byteLength; i++) {
binary += String.fromCharCode(bytes[i]);
}
@@ -107,7 +97,7 @@ class Utils {
}
}
static fromBufferToUrlB64(buffer: BufferSource): string {
static fromBufferToUrlB64(buffer: ArrayBuffer): string {
return Utils.fromB64toUrlB64(Utils.fromBufferToB64(buffer));
}
@@ -257,7 +247,7 @@ class Utils {
const urlDomain =
tldjs != null && tldjs.getDomain != null ? tldjs.getDomain(url.hostname) : null;
return urlDomain != null ? urlDomain : url.hostname;
} catch {
} catch (e) {
// Invalid domain, try another approach below.
}
}
@@ -405,7 +395,7 @@ class Utils {
anchor.href = uriString;
return anchor as any;
}
} catch {
} catch (e) {
// Ignore error
}
@@ -413,6 +403,4 @@ class Utils {
}
}
export default Utils;
Utils.init();

View File

@@ -1,6 +1,6 @@
import { CryptoService } from "../../abstractions/crypto.service";
import { EncryptionType } from "../../enums/encryptionType";
import Utils from "../../misc/utils";
import { Utils } from "../../misc/utils";
import { SymmetricCryptoKey } from "./symmetricCryptoKey";
@@ -53,7 +53,7 @@ export class EncString {
try {
this.encryptionType = parseInt(headerPieces[0], null);
encPieces = headerPieces[1].split("|");
} catch {
} catch (e) {
return;
}
} else {
@@ -114,7 +114,7 @@ export class EncString {
key = await cryptoService.getOrgKey(orgId);
}
this.decryptedValue = await cryptoService.decryptToUtf8(this, key);
} catch {
} catch (e) {
this.decryptedValue = "[error: cannot decrypt]";
}
return this.decryptedValue;

View File

@@ -1,5 +1,5 @@
import { EncryptionType } from "../../enums/encryptionType";
import Utils from "../../misc/utils";
import { Utils } from "../../misc/utils";
export class SymmetricCryptoKey {
key: ArrayBuffer;
@@ -13,35 +13,33 @@ export class SymmetricCryptoKey {
meta: any;
constructor(key: BufferSource, encType?: EncryptionType) {
constructor(key: ArrayBuffer, encType?: EncryptionType) {
if (key == null) {
throw new Error("Must provide key");
}
const keyBuffer = ArrayBuffer.isView(key) ? key.buffer.slice(key.byteOffset, key.byteOffset + key.byteLength) : key;
if (encType == null) {
if (keyBuffer.byteLength === 32) {
if (key.byteLength === 32) {
encType = EncryptionType.AesCbc256_B64;
} else if (keyBuffer.byteLength === 64) {
} else if (key.byteLength === 64) {
encType = EncryptionType.AesCbc256_HmacSha256_B64;
} else {
throw new Error("Unable to determine encType.");
}
}
this.key = keyBuffer;
this.key = key;
this.encType = encType;
if (encType === EncryptionType.AesCbc256_B64 && keyBuffer.byteLength === 32) {
this.encKey = keyBuffer;
if (encType === EncryptionType.AesCbc256_B64 && key.byteLength === 32) {
this.encKey = key;
this.macKey = null;
} else if (encType === EncryptionType.AesCbc128_HmacSha256_B64 && keyBuffer.byteLength === 32) {
this.encKey = keyBuffer.slice(0, 16);
this.macKey = keyBuffer.slice(16, 32);
} else if (encType === EncryptionType.AesCbc256_HmacSha256_B64 && keyBuffer.byteLength === 64) {
this.encKey = keyBuffer.slice(0, 32);
this.macKey = keyBuffer.slice(32, 64);
} else if (encType === EncryptionType.AesCbc128_HmacSha256_B64 && key.byteLength === 32) {
this.encKey = key.slice(0, 16);
this.macKey = key.slice(16, 32);
} else if (encType === EncryptionType.AesCbc256_HmacSha256_B64 && key.byteLength === 64) {
this.encKey = key.slice(0, 32);
this.macKey = key.slice(32, 64);
} else {
throw new Error("Unsupported encType/key length.");
}

View File

@@ -1,4 +1,5 @@
import { ClientType } from "../../../enums/clientType";
import { Utils } from "../../../misc/utils";
import { CaptchaProtectedRequest } from "../captchaProtectedRequest";
import { DeviceRequest } from "../deviceRequest";

View File

@@ -1,4 +1,4 @@
import Utils from "../../misc/utils";
import { Utils } from "../../misc/utils";
import { BaseResponse } from "./baseResponse";

View File

@@ -1,4 +1,4 @@
import Utils from "../../misc/utils";
import { Utils } from "../../misc/utils";
import { BaseResponse } from "./baseResponse";

View File

@@ -7,7 +7,7 @@ import { EnvironmentService } from "../abstractions/environment.service";
import { PlatformUtilsService } from "../abstractions/platformUtils.service";
import { TokenService } from "../abstractions/token.service";
import { DeviceType } from "../enums/deviceType";
import Utils from "../misc/utils";
import { Utils } from "../misc/utils";
import { ApiTokenRequest } from "../models/request/identityToken/apiTokenRequest";
import { PasswordTokenRequest } from "../models/request/identityToken/passwordTokenRequest";
import { SsoTokenRequest } from "../models/request/identityToken/ssoTokenRequest";

View File

@@ -1,7 +1,7 @@
import { AppIdService as AppIdServiceAbstraction } from "../abstractions/appId.service";
import { StorageService } from "../abstractions/storage.service";
import { HtmlStorageLocation } from "../enums/htmlStorageLocation";
import Utils from "../misc/utils";
import { Utils } from "../misc/utils";
export class AppIdService implements AppIdServiceAbstraction {
constructor(private storageService: StorageService) {}

View File

@@ -10,7 +10,7 @@ import { HashPurpose } from "../enums/hashPurpose";
import { KdfType } from "../enums/kdfType";
import { KeySuffixOptions } from "../enums/keySuffixOptions";
import { sequentialize } from "../misc/sequentialize";
import Utils from "../misc/utils";
import { Utils } from "../misc/utils";
import { EEFLongWordList } from "../misc/wordlist";
import { EncArrayBuffer } from "../models/domain/encArrayBuffer";
import { EncString } from "../models/domain/encString";
@@ -109,7 +109,7 @@ export class CryptoService implements CryptoServiceAbstraction {
): Promise<SymmetricCryptoKey> {
const key = await this.retrieveKeyFromStorage(keySuffix, userId);
if (key != null) {
const symmetricKey = new SymmetricCryptoKey(Utils.fromB64ToArray(key));
const symmetricKey = new SymmetricCryptoKey(Utils.fromB64ToArray(key).buffer);
if (!(await this.validateKey(symmetricKey))) {
this.logService.warning("Wrong key, throwing away stored key");
@@ -335,11 +335,9 @@ export class CryptoService implements CryptoServiceAbstraction {
}
async clearStoredKey(keySuffix: KeySuffixOptions) {
if (keySuffix === KeySuffixOptions.Auto) {
await this.stateService.setCryptoMasterKeyAuto(null);
} else {
await this.stateService.setCryptoMasterKeyBiometric(null);
}
keySuffix === KeySuffixOptions.Auto
? await this.stateService.setCryptoMasterKeyAuto(null)
: await this.stateService.setCryptoMasterKeyBiometric(null);
}
async clearKeyHash(userId?: string): Promise<any> {
@@ -510,9 +508,9 @@ export class CryptoService implements CryptoServiceAbstraction {
return Promise.resolve(null);
}
let plainBuf: BufferSource;
let plainBuf: ArrayBuffer;
if (typeof plainValue === "string") {
plainBuf = Utils.fromUtf8ToArray(plainValue);
plainBuf = Utils.fromUtf8ToArray(plainValue).buffer;
} else {
plainBuf = plainValue;
}
@@ -585,8 +583,7 @@ export class CryptoService implements CryptoServiceAbstraction {
throw new Error("encPieces unavailable.");
}
const dataArray = Utils.fromB64ToArray(encPieces[0]);
const data = dataArray.buffer as ArrayBuffer;
const data = Utils.fromB64ToArray(encPieces[0]).buffer;
const privateKey = privateKeyValue ?? (await this.getPrivateKey());
if (privateKey == null) {
throw new Error("No private key.");
@@ -609,12 +606,9 @@ export class CryptoService implements CryptoServiceAbstraction {
}
async decryptToBytes(encString: EncString, key?: SymmetricCryptoKey): Promise<ArrayBuffer> {
const ivArray = Utils.fromB64ToArray(encString.iv);
const iv = ivArray.buffer as ArrayBuffer;
const dataArray = Utils.fromB64ToArray(encString.data);
const data = dataArray.buffer as ArrayBuffer;
const macArray = encString.mac ? Utils.fromB64ToArray(encString.mac) : null;
const mac = macArray ? (macArray.buffer as ArrayBuffer) : null;
const iv = Utils.fromB64ToArray(encString.iv).buffer;
const data = Utils.fromB64ToArray(encString.data).buffer;
const mac = encString.mac ? Utils.fromB64ToArray(encString.mac).buffer : null;
const decipher = await this.aesDecryptToBytes(encString.encryptionType, data, iv, mac, key);
if (decipher == null) {
return null;
@@ -671,9 +665,9 @@ export class CryptoService implements CryptoServiceAbstraction {
return await this.aesDecryptToBytes(
encType,
ctBytes.buffer as ArrayBuffer,
ivBytes.buffer as ArrayBuffer,
macBytes != null ? (macBytes.buffer as ArrayBuffer) : null,
ctBytes.buffer,
ivBytes.buffer,
macBytes != null ? macBytes.buffer : null,
key,
);
}
@@ -723,7 +717,7 @@ export class CryptoService implements CryptoServiceAbstraction {
const privateKey = await this.decryptToBytes(new EncString(encPrivateKey), encKey);
await this.cryptoFunctionService.rsaExtractPublicKey(privateKey);
} catch {
} catch (e) {
return false;
}
@@ -760,24 +754,17 @@ export class CryptoService implements CryptoServiceAbstraction {
: await this.stateService.getCryptoMasterKeyBiometric({ userId: userId });
}
private async aesEncrypt(data: BufferSource, key: SymmetricCryptoKey): Promise<EncryptedObject> {
private async aesEncrypt(data: ArrayBuffer, key: SymmetricCryptoKey): Promise<EncryptedObject> {
const obj = new EncryptedObject();
obj.key = await this.getKeyForEncryption(key);
obj.iv = await this.cryptoFunctionService.randomBytes(16);
const dataBuffer = ArrayBuffer.isView(data)
? (data.byteOffset === 0 && data.byteLength === data.buffer.byteLength
? data.buffer as ArrayBuffer
: data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength) as ArrayBuffer)
: data;
obj.data = await this.cryptoFunctionService.aesEncrypt(dataBuffer, obj.iv, obj.key.encKey);
obj.data = await this.cryptoFunctionService.aesEncrypt(data, obj.iv, obj.key.encKey);
if (obj.key.macKey != null) {
const macData = new Uint8Array(obj.iv.byteLength + obj.data.byteLength);
macData.set(new Uint8Array(obj.iv), 0);
macData.set(new Uint8Array(obj.data), obj.iv.byteLength);
obj.mac = await this.cryptoFunctionService.hmac(macData.buffer as ArrayBuffer, obj.key.macKey, "sha256");
obj.mac = await this.cryptoFunctionService.hmac(macData.buffer, obj.key.macKey, "sha256");
}
return obj;
@@ -843,7 +830,7 @@ export class CryptoService implements CryptoServiceAbstraction {
macData.set(new Uint8Array(iv), 0);
macData.set(new Uint8Array(data), iv.byteLength);
const computedMac = await this.cryptoFunctionService.hmac(
macData.buffer as ArrayBuffer,
macData.buffer,
theKey.macKey,
"sha256",
);

View File

@@ -1,6 +1,6 @@
import { StateService } from "../abstractions/state.service";
import { TokenService as TokenServiceAbstraction } from "../abstractions/token.service";
import Utils from "../misc/utils";
import { Utils } from "../misc/utils";
import { IdentityTokenResponse } from "../models/response/identityTokenResponse";
export class TokenService implements TokenServiceAbstraction {

View File

@@ -1,4 +1,4 @@
import Utils from "@/jslib/common/src/misc/utils";
import { Utils } from "@/jslib/common/src/misc/utils";
import { SymmetricCryptoKey } from "@/jslib/common/src/models/domain/symmetricCryptoKey";
import { NodeCryptoFunctionService } from "@/jslib/node/src/services/nodeCryptoFunction.service";
@@ -93,9 +93,8 @@ describe("NodeCrypto Function Service", () => {
it("should fail with prk too small", async () => {
const cryptoFunctionService = new NodeCryptoFunctionService();
const prk = Utils.fromB64ToArray(prk16Byte);
const f = cryptoFunctionService.hkdfExpand(
prk.buffer,
Utils.fromB64ToArray(prk16Byte),
"info",
32,
"sha256",
@@ -105,9 +104,8 @@ describe("NodeCrypto Function Service", () => {
it("should fail with outputByteSize is too large", async () => {
const cryptoFunctionService = new NodeCryptoFunctionService();
const prk = Utils.fromB64ToArray(prk32Byte);
const f = cryptoFunctionService.hkdfExpand(
prk.buffer,
Utils.fromB64ToArray(prk32Byte),
"info",
8161,
"sha256",
@@ -181,16 +179,16 @@ describe("NodeCrypto Function Service", () => {
it("should successfully encrypt and then decrypt data", async () => {
const nodeCryptoFunctionService = new NodeCryptoFunctionService();
const iv = makeStaticByteArray(16).buffer;
const key = makeStaticByteArray(32).buffer;
const iv = makeStaticByteArray(16);
const key = makeStaticByteArray(32);
const value = "EncryptMe!";
const data = Utils.fromUtf8ToArray(value).buffer;
const data = Utils.fromUtf8ToArray(value);
const encValue = await nodeCryptoFunctionService.aesEncrypt(
data,
iv,
key
data.buffer,
iv.buffer,
key.buffer,
);
const decValue = await nodeCryptoFunctionService.aesDecrypt(encValue, iv, key);
const decValue = await nodeCryptoFunctionService.aesDecrypt(encValue, iv.buffer, key.buffer);
expect(Utils.fromBufferToUtf8(decValue)).toBe(value);
});
});
@@ -198,9 +196,8 @@ describe("NodeCrypto Function Service", () => {
describe("aesDecryptFast", () => {
it("should successfully decrypt data", async () => {
const nodeCryptoFunctionService = new NodeCryptoFunctionService();
const ivArray = makeStaticByteArray(16);
const iv = Utils.fromBufferToB64(ivArray);
const symKey = new SymmetricCryptoKey(makeStaticByteArray(32));
const iv = Utils.fromBufferToB64(makeStaticByteArray(16).buffer);
const symKey = new SymmetricCryptoKey(makeStaticByteArray(32).buffer);
const data = "ByUF8vhyX4ddU9gcooznwA==";
const params = nodeCryptoFunctionService.aesDecryptFastParameters(data, iv, null, symKey);
const decValue = await nodeCryptoFunctionService.aesDecryptFast(params);
@@ -211,13 +208,13 @@ describe("NodeCrypto Function Service", () => {
describe("aesDecrypt", () => {
it("should successfully decrypt data", async () => {
const nodeCryptoFunctionService = new NodeCryptoFunctionService();
const iv = makeStaticByteArray(16).buffer;
const key = makeStaticByteArray(32).buffer;
const data = Utils.fromB64ToArray("ByUF8vhyX4ddU9gcooznwA==").buffer;
const iv = makeStaticByteArray(16);
const key = makeStaticByteArray(32);
const data = Utils.fromB64ToArray("ByUF8vhyX4ddU9gcooznwA==");
const decValue = await nodeCryptoFunctionService.aesDecrypt(
data,
iv,
key,
data.buffer,
iv.buffer,
key.buffer,
);
expect(Utils.fromBufferToUtf8(decValue)).toBe("EncryptMe!");
});
@@ -227,7 +224,7 @@ describe("NodeCrypto Function Service", () => {
it("should successfully encrypt and then decrypt data", async () => {
const nodeCryptoFunctionService = new NodeCryptoFunctionService();
const pubKey = Utils.fromB64ToArray(RsaPublicKey);
const privKey = Utils.fromB64ToArray(RsaPrivateKey).buffer;
const privKey = Utils.fromB64ToArray(RsaPrivateKey);
const value = "EncryptMe!";
const data = Utils.fromUtf8ToArray(value);
const encValue = await nodeCryptoFunctionService.rsaEncrypt(
@@ -235,7 +232,7 @@ describe("NodeCrypto Function Service", () => {
pubKey.buffer,
"sha1",
);
const decValue = await nodeCryptoFunctionService.rsaDecrypt(encValue, privKey, "sha1");
const decValue = await nodeCryptoFunctionService.rsaDecrypt(encValue, privKey.buffer, "sha1");
expect(Utils.fromBufferToUtf8(decValue)).toBe(value);
});
});
@@ -262,8 +259,8 @@ describe("NodeCrypto Function Service", () => {
describe("rsaExtractPublicKey", () => {
it("should successfully extract key", async () => {
const nodeCryptoFunctionService = new NodeCryptoFunctionService();
const privKey = Utils.fromB64ToArray(RsaPrivateKey).buffer;
const publicKey = await nodeCryptoFunctionService.rsaExtractPublicKey(privKey);
const privKey = Utils.fromB64ToArray(RsaPrivateKey);
const publicKey = await nodeCryptoFunctionService.rsaExtractPublicKey(privKey.buffer);
expect(Utils.fromBufferToB64(publicKey)).toBe(RsaPublicKey);
});
});
@@ -356,26 +353,26 @@ function testHkdf(
it("should create valid " + algorithm + " key from regular input", async () => {
const cryptoFunctionService = new NodeCryptoFunctionService();
const key = await cryptoFunctionService.hkdf(ikm.buffer, regularSalt, regularInfo, 32, algorithm);
const key = await cryptoFunctionService.hkdf(ikm, regularSalt, regularInfo, 32, algorithm);
expect(Utils.fromBufferToB64(key)).toBe(regularKey);
});
it("should create valid " + algorithm + " key from utf8 input", async () => {
const cryptoFunctionService = new NodeCryptoFunctionService();
const key = await cryptoFunctionService.hkdf(ikm.buffer, utf8Salt, utf8Info, 32, algorithm);
const key = await cryptoFunctionService.hkdf(ikm, utf8Salt, utf8Info, 32, algorithm);
expect(Utils.fromBufferToB64(key)).toBe(utf8Key);
});
it("should create valid " + algorithm + " key from unicode input", async () => {
const cryptoFunctionService = new NodeCryptoFunctionService();
const key = await cryptoFunctionService.hkdf(ikm.buffer, unicodeSalt, unicodeInfo, 32, algorithm);
const key = await cryptoFunctionService.hkdf(ikm, unicodeSalt, unicodeInfo, 32, algorithm);
expect(Utils.fromBufferToB64(key)).toBe(unicodeKey);
});
it("should create valid " + algorithm + " key from array buffer input", async () => {
const cryptoFunctionService = new NodeCryptoFunctionService();
const key = await cryptoFunctionService.hkdf(
ikm.buffer,
ikm,
Utils.fromUtf8ToArray(regularSalt).buffer,
Utils.fromUtf8ToArray(regularInfo).buffer,
32,
@@ -395,9 +392,8 @@ function testHkdfExpand(
it("should create valid " + algorithm + " " + outputByteSize + " byte okm", async () => {
const cryptoFunctionService = new NodeCryptoFunctionService();
const prk = Utils.fromB64ToArray(b64prk);
const okm = await cryptoFunctionService.hkdfExpand(
prk.buffer,
Utils.fromB64ToArray(b64prk),
info,
outputByteSize,
algorithm,

View File

@@ -8,7 +8,7 @@ import { LogService } from "@/jslib/common/src/abstractions/log.service";
import { StorageService } from "@/jslib/common/src/abstractions/storage.service";
import { NodeUtils } from "@/jslib/common/src/misc/nodeUtils";
import { sequentialize } from "@/jslib/common/src/misc/sequentialize";
import Utils from "@/jslib/common/src/misc/utils";
import { Utils } from "@/jslib/common/src/misc/utils";
export class LowdbStorageService implements StorageService {
protected dataFilePath: string;

View File

@@ -3,7 +3,7 @@ import * as crypto from "crypto";
import * as forge from "node-forge";
import { CryptoFunctionService } from "@/jslib/common/src/abstractions/cryptoFunction.service";
import Utils from "@/jslib/common/src/misc/utils";
import { Utils } from "@/jslib/common/src/misc/utils";
import { DecryptParameters } from "@/jslib/common/src/models/domain/decryptParameters";
import { SymmetricCryptoKey } from "@/jslib/common/src/models/domain/symmetricCryptoKey";
@@ -147,22 +147,19 @@ export class NodeCryptoFunctionService implements CryptoFunctionService {
): DecryptParameters<ArrayBuffer> {
const p = new DecryptParameters<ArrayBuffer>();
p.encKey = key.encKey;
const dataArr = Utils.fromB64ToArray(data);
p.data = dataArr.buffer.slice(dataArr.byteOffset, dataArr.byteOffset + dataArr.byteLength) as ArrayBuffer;
const ivArr = Utils.fromB64ToArray(iv);
p.iv = ivArr.buffer.slice(ivArr.byteOffset, ivArr.byteOffset + ivArr.byteLength) as ArrayBuffer;
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.slice(macData.byteOffset, macData.byteOffset + macData.byteLength) as ArrayBuffer;
p.macData = macData.buffer;
if (key.macKey != null) {
p.macKey = key.macKey;
}
if (mac != null) {
const macArr = Utils.fromB64ToArray(mac);
p.mac = macArr.buffer.slice(macArr.byteOffset, macArr.byteOffset + macArr.byteLength) as ArrayBuffer;
p.mac = Utils.fromB64ToArray(mac).buffer;
}
return p;
@@ -218,8 +215,7 @@ export class NodeCryptoFunctionService implements CryptoFunctionService {
const publicKeyAsn1 = forge.pki.publicKeyToAsn1(forgePublicKey);
const publicKeyByteString = forge.asn1.toDer(publicKeyAsn1).data;
const publicKeyArray = Utils.fromByteStringToArray(publicKeyByteString);
return Promise.resolve(publicKeyArray.buffer as ArrayBuffer);
return Promise.resolve(publicKeyArray.buffer);
}
async rsaGenerateKeyPair(length: 1024 | 2048 | 4096): Promise<[ArrayBuffer, ArrayBuffer]> {
@@ -245,7 +241,7 @@ export class NodeCryptoFunctionService implements CryptoFunctionService {
const privateKeyByteString = forge.asn1.toDer(privateKeyPkcs8).getBytes();
const privateKey = Utils.fromByteStringToArray(privateKeyByteString);
resolve([publicKey.buffer as ArrayBuffer, privateKey.buffer as ArrayBuffer]);
resolve([publicKey.buffer, privateKey.buffer]);
},
);
});
@@ -280,12 +276,9 @@ export class NodeCryptoFunctionService implements CryptoFunctionService {
private toArrayBuffer(value: Buffer | string | ArrayBuffer): ArrayBuffer {
let buf: ArrayBuffer;
if (typeof value === "string") {
const arr = Utils.fromUtf8ToArray(value);
buf = arr.buffer.slice(arr.byteOffset, arr.byteOffset + arr.byteLength) as ArrayBuffer;
} else if (Buffer.isBuffer(value)) {
buf = value.buffer.slice(value.byteOffset, value.byteOffset + value.byteLength) as ArrayBuffer;
buf = Utils.fromUtf8ToArray(value).buffer;
} else {
buf = value;
buf = new Uint8Array(value).buffer;
}
return buf;
}

75
package-lock.json generated
View File

@@ -82,13 +82,13 @@
"eslint-plugin-rxjs": "5.0.3",
"eslint-plugin-rxjs-angular": "2.0.1",
"form-data": "4.0.4",
"glob": "11.1.0",
"glob": "13.0.0",
"html-loader": "5.1.0",
"html-webpack-plugin": "5.6.3",
"husky": "9.1.7",
"jest": "29.7.0",
"jest-junit": "16.0.0",
"jest-mock-extended": "3.0.7",
"jest-mock-extended": "4.0.0",
"jest-preset-angular": "14.6.0",
"lint-staged": "16.2.6",
"mini-css-extract-plugin": "2.9.2",
@@ -104,7 +104,7 @@
"ts-loader": "9.5.2",
"tsconfig-paths-webpack-plugin": "4.2.0",
"type-fest": "5.3.0",
"typescript": "5.9.3",
"typescript": "5.8.3",
"webpack": "5.103.0",
"webpack-cli": "6.0.1",
"webpack-merge": "6.0.1",
@@ -15398,22 +15398,16 @@
"license": "MIT"
},
"node_modules/glob": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz",
"integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==",
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz",
"integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==",
"dev": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"foreground-child": "^3.3.1",
"jackspeak": "^4.1.1",
"minimatch": "^10.1.1",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^2.0.0"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"engines": {
"node": "20 || >=22"
},
@@ -17963,16 +17957,17 @@
}
},
"node_modules/jest-mock-extended": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/jest-mock-extended/-/jest-mock-extended-3.0.7.tgz",
"integrity": "sha512-7lsKdLFcW9B9l5NzZ66S/yTQ9k8rFtnwYdCNuRU/81fqDWicNDVhitTSPnrGmNeNm0xyw0JHexEOShrIKRCIRQ==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jest-mock-extended/-/jest-mock-extended-4.0.0.tgz",
"integrity": "sha512-7BZpfuvLam+/HC+NxifIi9b+5VXj/utUDMPUqrDJehGWVuXPtLS9Jqlob2mJLrI/pg2k1S8DMfKDvEB88QNjaQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"ts-essentials": "^10.0.0"
"ts-essentials": "^10.0.2"
},
"peerDependencies": {
"jest": "^24.0.0 || ^25.0.0 || ^26.0.0 || ^27.0.0 || ^28.0.0 || ^29.0.0",
"@jest/globals": "^28.0.0 || ^29.0.0 || ^30.0.0",
"jest": "^24.0.0 || ^25.0.0 || ^26.0.0 || ^27.0.0 || ^28.0.0 || ^29.0.0 || ^30.0.0",
"typescript": "^3.0.0 || ^4.0.0 || ^5.0.0"
}
},
@@ -23108,6 +23103,46 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/rimraf/node_modules/glob": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz",
"integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==",
"dev": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"foreground-child": "^3.3.1",
"jackspeak": "^4.1.1",
"minimatch": "^10.1.1",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^2.0.0"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/rimraf/node_modules/minimatch": {
"version": "10.1.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz",
"integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==",
"dev": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/brace-expansion": "^5.0.0"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/roarr": {
"version": "2.15.4",
"resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz",
@@ -25703,9 +25738,9 @@
"license": "MIT"
},
"node_modules/typescript": {
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {

View File

@@ -112,13 +112,13 @@
"eslint-plugin-rxjs": "5.0.3",
"eslint-plugin-rxjs-angular": "2.0.1",
"form-data": "4.0.4",
"glob": "11.1.0",
"glob": "13.0.0",
"html-loader": "5.1.0",
"html-webpack-plugin": "5.6.3",
"husky": "9.1.7",
"jest": "29.7.0",
"jest-junit": "16.0.0",
"jest-mock-extended": "3.0.7",
"jest-mock-extended": "4.0.0",
"jest-preset-angular": "14.6.0",
"lint-staged": "16.2.6",
"mini-css-extract-plugin": "2.9.2",
@@ -134,7 +134,7 @@
"ts-loader": "9.5.2",
"tsconfig-paths-webpack-plugin": "4.2.0",
"type-fest": "5.3.0",
"typescript": "5.9.3",
"typescript": "5.8.3",
"webpack": "5.103.0",
"webpack-cli": "6.0.1",
"webpack-merge": "6.0.1",

View File

@@ -1,9 +1,8 @@
import { notarize } from "@electron/notarize";
import { config } from "dotenv";
/* eslint-disable @typescript-eslint/no-var-requires */
require("dotenv").config();
const { notarize } = require("@electron/notarize");
config();
export default async function notarizing(context) {
exports.default = async function notarizing(context) {
const { electronPlatformName, appOutDir } = context;
if (electronPlatformName !== "darwin") {
return;
@@ -34,4 +33,4 @@ export default async function notarizing(context) {
appleIdPassword: appleIdPassword,
});
}
}
};

View File

@@ -1,13 +1,8 @@
/* eslint-disable no-console */
import { execSync } from "child_process";
export default async function (configuration) {
if (
parseInt(process.env.ELECTRON_BUILDER_SIGN) === 1 &&
configuration.path.slice(-4) === ".exe"
) {
/* eslint-disable @typescript-eslint/no-var-requires, no-console */
exports.default = async function (configuration) {
if (parseInt(process.env.ELECTRON_BUILDER_SIGN) === 1 && configuration.path.slice(-4) == ".exe") {
console.log(`[*] Signing file: ${configuration.path}`);
execSync(
require("child_process").execSync(
`azuresigntool sign ` +
`-kvu ${process.env.SIGNING_VAULT_URL} ` +
`-kvi ${process.env.SIGNING_CLIENT_ID} ` +
@@ -23,4 +18,4 @@ export default async function (configuration) {
},
);
}
}
};

View File

@@ -6,7 +6,7 @@ import { ModalService } from "@/jslib/angular/src/services/modal.service";
import { I18nService } from "@/jslib/common/src/abstractions/i18n.service";
import { LogService } from "@/jslib/common/src/abstractions/log.service";
import { PlatformUtilsService } from "@/jslib/common/src/abstractions/platformUtils.service";
import Utils from "@/jslib/common/src/misc/utils";
import { Utils } from "@/jslib/common/src/misc/utils";
import { AuthService } from "../../abstractions/auth.service";
import { StateService } from "../../abstractions/state.service";

View File

@@ -3,7 +3,8 @@ import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
import { isDev } from "@/jslib/electron/src/utils";
import "../scss/styles.scss";
// tslint:disable-next-line
require("../scss/styles.scss");
import { AppModule } from "./app.module";

View File

@@ -3,7 +3,7 @@ import * as inquirer from "inquirer";
import { Response } from "@/jslib/node/src/cli/models/response";
import { MessageResponse } from "@/jslib/node/src/cli/models/response/messageResponse";
import Utils from "../../jslib/common/src/misc/utils";
import { Utils } from "../../jslib/common/src/misc/utils";
import { AuthService } from "../abstractions/auth.service";
export class LoginCommand {

View File

@@ -3,7 +3,7 @@ import * as path from "path";
import * as chalk from "chalk";
import { Command, OptionValues } from "commander";
import Utils from "@/jslib/common/src/misc/utils";
import { Utils } from "@/jslib/common/src/misc/utils";
import { BaseProgram } from "@/jslib/node/src/cli/baseProgram";
import { UpdateCommand } from "@/jslib/node/src/cli/commands/update.command";
import { Response } from "@/jslib/node/src/cli/models/response";

View File

@@ -3,7 +3,7 @@ import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute";
import { ApiService } from "@/jslib/common/src/abstractions/api.service";
import { AppIdService } from "@/jslib/common/src/abstractions/appId.service";
import { PlatformUtilsService } from "@/jslib/common/src/abstractions/platformUtils.service";
import Utils from "@/jslib/common/src/misc/utils";
import { Utils } from "@/jslib/common/src/misc/utils";
import {
AccountKeys,
AccountProfile,

View File

@@ -5,7 +5,7 @@ import * as ldapts from "ldapts";
import { I18nService } from "@/jslib/common/src/abstractions/i18n.service";
import { LogService } from "@/jslib/common/src/abstractions/log.service";
import Utils from "@/jslib/common/src/misc/utils";
import { Utils } from "@/jslib/common/src/misc/utils";
import { StateService } from "../../abstractions/state.service";
import { DirectoryType } from "../../enums/directoryType";

View File

@@ -1,7 +1,7 @@
import * as lock from "proper-lockfile";
import { LogService } from "@/jslib/common/src/abstractions/log.service";
import Utils from "@/jslib/common/src/misc/utils";
import { Utils } from "@/jslib/common/src/misc/utils";
import { LowdbStorageService as LowdbStorageServiceBase } from "@/jslib/node/src/services/lowdbStorage.service";
export class LowdbStorageService extends LowdbStorageServiceBase {

View File

@@ -3,7 +3,7 @@ import { CryptoFunctionService } from "@/jslib/common/src/abstractions/cryptoFun
import { EnvironmentService } from "@/jslib/common/src/abstractions/environment.service";
import { I18nService } from "@/jslib/common/src/abstractions/i18n.service";
import { MessagingService } from "@/jslib/common/src/abstractions/messaging.service";
import Utils from "@/jslib/common/src/misc/utils";
import { Utils } from "@/jslib/common/src/misc/utils";
import { OrganizationImportRequest } from "@/jslib/common/src/models/request/organizationImportRequest";
import { DirectoryFactoryService } from "../abstractions/directory-factory.service";