mirror of
https://github.com/bitwarden/browser
synced 2025-12-10 05:13:29 +00:00
[PM-22271] Switch to SDK argon2 implementation, and drop other impls (#15401)
* Switch to SDK argon2 implementation * Cleanup and update to the latest sdk * Update package lock * Remove copy patch * Fix builds * Fix test build * Remove error * Fix tests * Fix build * Run prettier * Remove argon2 references * Regenerate index.d.ts for desktop_native napi * Replace mocked crypto function service type
This commit is contained in:
12
.github/renovate.json5
vendored
12
.github/renovate.json5
vendored
@@ -398,17 +398,7 @@
|
||||
reviewers: ["team:team-vault-dev"],
|
||||
},
|
||||
{
|
||||
matchPackageNames: [
|
||||
"@types/argon2-browser",
|
||||
"aes",
|
||||
"argon2",
|
||||
"argon2-browser",
|
||||
"big-integer",
|
||||
"cbc",
|
||||
"rsa",
|
||||
"russh-cryptovec",
|
||||
"sha2",
|
||||
],
|
||||
matchPackageNames: ["aes", "big-integer", "cbc", "rsa", "russh-cryptovec", "sha2"],
|
||||
description: "Key Management owned dependencies",
|
||||
commitMessagePrefix: "[deps] KM:",
|
||||
reviewers: ["team:team-key-management-dev"],
|
||||
|
||||
4
.github/workflows/build-browser.yml
vendored
4
.github/workflows/build-browser.yml
vendored
@@ -163,10 +163,6 @@ jobs:
|
||||
FILES=$(find . -maxdepth 1 -type f)
|
||||
for FILE in $FILES; do cp "$FILE" browser-source/; done
|
||||
|
||||
# Copy patches to the Browser source directory
|
||||
mkdir -p browser-source/patches
|
||||
cp -r patches/* browser-source/patches
|
||||
|
||||
# Copy apps/browser to the Browser source directory
|
||||
mkdir -p browser-source/apps/browser
|
||||
cp -r apps/browser/* browser-source/apps/browser
|
||||
|
||||
@@ -92,11 +92,6 @@ const moduleRules = [
|
||||
test: /\.[jt]sx?$/,
|
||||
loader: "@ngtools/webpack",
|
||||
},
|
||||
{
|
||||
test: /argon2(-simd)?\.wasm$/,
|
||||
loader: "base64-loader",
|
||||
type: "javascript/auto",
|
||||
},
|
||||
];
|
||||
|
||||
const requiredPlugins = [
|
||||
@@ -290,7 +285,6 @@ const mainConfig = {
|
||||
clean: true,
|
||||
},
|
||||
module: {
|
||||
noParse: /argon2(-simd)?\.wasm$/,
|
||||
rules: moduleRules,
|
||||
},
|
||||
experiments: {
|
||||
@@ -365,13 +359,7 @@ if (manifestVersion == 2) {
|
||||
test: /\.tsx?$/,
|
||||
loader: "ts-loader",
|
||||
},
|
||||
{
|
||||
test: /argon2(-simd)?\.wasm$/,
|
||||
loader: "base64-loader",
|
||||
type: "javascript/auto",
|
||||
},
|
||||
],
|
||||
noParse: /argon2(-simd)?\.wasm$/,
|
||||
},
|
||||
cache:
|
||||
ENV !== "development"
|
||||
|
||||
@@ -59,14 +59,12 @@
|
||||
},
|
||||
"pkg": {
|
||||
"assets": [
|
||||
"./build/**/*",
|
||||
"../../node_modules/argon2/**/*"
|
||||
"./build/**/*"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@koa/multer": "4.0.0",
|
||||
"@koa/router": "13.1.0",
|
||||
"argon2": "0.41.1",
|
||||
"big-integer": "1.6.52",
|
||||
"browser-hrtime": "1.1.8",
|
||||
"chalk": "4.1.2",
|
||||
|
||||
34
apps/desktop/desktop_native/Cargo.lock
generated
34
apps/desktop/desktop_native/Cargo.lock
generated
@@ -135,19 +135,6 @@ dependencies = [
|
||||
"x11rb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "argon2"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"blake2",
|
||||
"cpufeatures",
|
||||
"password-hash",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ashpd"
|
||||
version = "0.11.0"
|
||||
@@ -452,15 +439,6 @@ dependencies = [
|
||||
"tokio-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blake2"
|
||||
version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
|
||||
dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
@@ -887,7 +865,6 @@ dependencies = [
|
||||
"aes",
|
||||
"anyhow",
|
||||
"arboard",
|
||||
"argon2",
|
||||
"ashpd",
|
||||
"base64",
|
||||
"bitwarden-russh",
|
||||
@@ -2264,17 +2241,6 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "password-hash"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.15"
|
||||
|
||||
@@ -12,7 +12,6 @@ publish = false
|
||||
aes = "=0.8.4"
|
||||
anyhow = "=1.0.94"
|
||||
arboard = { version = "=3.6.0", default-features = false }
|
||||
argon2 = "=0.5.3"
|
||||
ashpd = "=0.11.0"
|
||||
base64 = "=0.22.1"
|
||||
bindgen = "=0.72.0"
|
||||
|
||||
@@ -23,7 +23,6 @@ anyhow = { workspace = true }
|
||||
arboard = { workspace = true, features = [
|
||||
"wayland-data-control",
|
||||
] }
|
||||
argon2 = { workspace = true, features = ["zeroize"] }
|
||||
base64 = { workspace = true }
|
||||
byteorder = { workspace = true }
|
||||
cbc = { workspace = true, features = ["alloc"] }
|
||||
|
||||
@@ -5,7 +5,7 @@ use aes::cipher::{
|
||||
BlockEncryptMut, KeyIvInit,
|
||||
};
|
||||
|
||||
use crate::error::{CryptoError, KdfParamError, Result};
|
||||
use crate::error::{CryptoError, Result};
|
||||
|
||||
use super::CipherString;
|
||||
|
||||
@@ -33,53 +33,3 @@ pub fn encrypt_aes256(
|
||||
|
||||
Ok(CipherString::AesCbc256_B64 { iv, data })
|
||||
}
|
||||
|
||||
pub fn argon2(
|
||||
secret: &[u8],
|
||||
salt: &[u8],
|
||||
iterations: u32,
|
||||
memory: u32,
|
||||
parallelism: u32,
|
||||
) -> Result<[u8; 32]> {
|
||||
use argon2::*;
|
||||
|
||||
let params = Params::new(memory, iterations, parallelism, Some(32)).map_err(|e| {
|
||||
KdfParamError::InvalidParams(format!("Argon2 parameters are invalid: {e}",))
|
||||
})?;
|
||||
let argon = Argon2::new(Algorithm::Argon2id, Version::V0x13, params);
|
||||
|
||||
let mut hash = [0u8; 32];
|
||||
argon
|
||||
.hash_password_into(secret, salt, &mut hash)
|
||||
.map_err(|e| KdfParamError::InvalidParams(format!("Argon2 hashing failed: {e}",)))?;
|
||||
|
||||
// Argon2 is using some stack memory that is not zeroed. Eventually some function will
|
||||
// overwrite the stack, but we use this trick to force the used stack to be zeroed.
|
||||
#[inline(never)]
|
||||
fn clear_stack() {
|
||||
std::hint::black_box([0u8; 4096]);
|
||||
}
|
||||
clear_stack();
|
||||
Ok(hash)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_argon2() {
|
||||
let test_hash: [u8; 32] = [
|
||||
112, 200, 85, 209, 100, 4, 246, 146, 117, 180, 152, 44, 103, 198, 75, 14, 166, 77, 201,
|
||||
22, 62, 178, 87, 224, 95, 209, 253, 68, 166, 209, 47, 218,
|
||||
];
|
||||
let secret = b"supersecurepassword";
|
||||
let salt = b"mail@example.com";
|
||||
let iterations = 3;
|
||||
let memory = 1024 * 64;
|
||||
let parallelism = 4;
|
||||
|
||||
let hash = argon2(secret, salt, iterations, memory, parallelism).unwrap();
|
||||
assert_eq!(hash, test_hash,);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@ pub enum Error {
|
||||
|
||||
#[error("Cryptography Error, {0}")]
|
||||
Crypto(#[from] CryptoError),
|
||||
#[error("KDF Parameter Error, {0}")]
|
||||
KdfParam(#[from] KdfParamError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
|
||||
3
apps/desktop/desktop_native/napi/index.d.ts
vendored
3
apps/desktop/desktop_native/napi/index.d.ts
vendored
@@ -195,9 +195,6 @@ export declare namespace autofill {
|
||||
completeError(clientId: number, sequenceNumber: number, error: string): number
|
||||
}
|
||||
}
|
||||
export declare namespace crypto {
|
||||
export function argon2(secret: Buffer, salt: Buffer, iterations: number, memory: number, parallelism: number): Promise<Buffer>
|
||||
}
|
||||
export declare namespace passkey_authenticator {
|
||||
export function register(): void
|
||||
}
|
||||
|
||||
@@ -798,25 +798,6 @@ pub mod autofill {
|
||||
}
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub mod crypto {
|
||||
use napi::bindgen_prelude::Buffer;
|
||||
|
||||
#[napi]
|
||||
pub async fn argon2(
|
||||
secret: Buffer,
|
||||
salt: Buffer,
|
||||
iterations: u32,
|
||||
memory: u32,
|
||||
parallelism: u32,
|
||||
) -> napi::Result<Buffer> {
|
||||
desktop_core::crypto::argon2(&secret, &salt, iterations, memory, parallelism)
|
||||
.map_err(|e| napi::Error::from_reason(e.to_string()))
|
||||
.map(|v| v.to_vec())
|
||||
.map(Buffer::from)
|
||||
}
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub mod passkey_authenticator {
|
||||
#[napi]
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
import { CryptoFunctionService } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service";
|
||||
import { WebCryptoFunctionService } from "@bitwarden/common/key-management/crypto/services/web-crypto-function.service";
|
||||
|
||||
export class RendererCryptoFunctionService
|
||||
extends WebCryptoFunctionService
|
||||
implements CryptoFunctionService
|
||||
{
|
||||
constructor(win: Window | typeof global) {
|
||||
super(win);
|
||||
}
|
||||
|
||||
// We can't use the `argon2-browser` implementation because it loads WASM and the Content Security Policy doesn't allow it.
|
||||
// Rather than trying to weaken the policy, we'll just use the Node.js implementation though the IPC channel.
|
||||
// Note that the rest of the functions on this service will be inherited from the WebCryptoFunctionService, as those work just fine.
|
||||
async argon2(
|
||||
password: string | Uint8Array,
|
||||
salt: string | Uint8Array,
|
||||
iterations: number,
|
||||
memory: number,
|
||||
parallelism: number,
|
||||
): Promise<Uint8Array> {
|
||||
if (typeof password === "string") {
|
||||
password = new TextEncoder().encode(password);
|
||||
}
|
||||
if (typeof salt === "string") {
|
||||
salt = new TextEncoder().encode(salt);
|
||||
}
|
||||
|
||||
return await ipc.platform.crypto.argon2(password, salt, iterations, memory, parallelism);
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,7 @@ import { ClientType } from "@bitwarden/common/enums";
|
||||
import { ProcessReloadServiceAbstraction } from "@bitwarden/common/key-management/abstractions/process-reload.service";
|
||||
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service";
|
||||
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
|
||||
import { WebCryptoFunctionService } from "@bitwarden/common/key-management/crypto/services/web-crypto-function.service";
|
||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
||||
import { DefaultProcessReloadService } from "@bitwarden/common/key-management/services/default-process-reload.service";
|
||||
import {
|
||||
@@ -140,7 +141,6 @@ import { DesktopFileDownloadService } from "./desktop-file-download.service";
|
||||
import { DesktopSetPasswordJitService } from "./desktop-set-password-jit.service";
|
||||
import { InitService } from "./init.service";
|
||||
import { NativeMessagingManifestService } from "./native-messaging-manifest.service";
|
||||
import { RendererCryptoFunctionService } from "./renderer-crypto-function.service";
|
||||
import { DesktopSetInitialPasswordService } from "./set-initial-password/desktop-set-initial-password.service";
|
||||
|
||||
const RELOAD_CALLBACK = new SafeInjectionToken<() => any>("RELOAD_CALLBACK");
|
||||
@@ -296,7 +296,7 @@ const safeProviders: SafeProvider[] = [
|
||||
}),
|
||||
safeProvider({
|
||||
provide: CryptoFunctionServiceAbstraction,
|
||||
useClass: RendererCryptoFunctionService,
|
||||
useClass: WebCryptoFunctionService,
|
||||
deps: [WINDOW],
|
||||
}),
|
||||
safeProvider({
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { mock, MockProxy } from "jest-mock-extended";
|
||||
|
||||
import { CryptoFunctionService } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service";
|
||||
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
@@ -13,7 +14,6 @@ import {
|
||||
} from "@bitwarden/key-management";
|
||||
|
||||
import { WindowMain } from "../../main/window.main";
|
||||
import { MainCryptoFunctionService } from "../../platform/main/main-crypto-function.service";
|
||||
|
||||
import { MainBiometricsService } from "./main-biometrics.service";
|
||||
import OsBiometricsServiceLinux from "./os-biometrics-linux.service";
|
||||
@@ -35,7 +35,7 @@ describe("MainBiometricsService", function () {
|
||||
const windowMain = mock<WindowMain>();
|
||||
const logService = mock<LogService>();
|
||||
const biometricStateService = mock<BiometricStateService>();
|
||||
const cryptoFunctionService = mock<MainCryptoFunctionService>();
|
||||
const cryptoFunctionService = mock<CryptoFunctionService>();
|
||||
const encryptService = mock<EncryptService>();
|
||||
|
||||
it("Should call the platformspecific methods", async () => {
|
||||
|
||||
@@ -28,8 +28,9 @@ import { DefaultSingleUserStateProvider } from "@bitwarden/common/platform/state
|
||||
import { DefaultStateProvider } from "@bitwarden/common/platform/state/implementations/default-state.provider";
|
||||
import { StateEventRegistrarService } from "@bitwarden/common/platform/state/state-event-registrar.service";
|
||||
import { MemoryStorageService as MemoryStorageServiceForStateProviders } from "@bitwarden/common/platform/state/storage/memory-storage.service";
|
||||
import { DefaultBiometricStateService } from "@bitwarden/key-management";
|
||||
/* eslint-enable import/no-restricted-paths */
|
||||
import { DefaultBiometricStateService } from "@bitwarden/key-management";
|
||||
import { NodeCryptoFunctionService } from "@bitwarden/node/services/node-crypto-function.service";
|
||||
|
||||
import { MainSshAgentService } from "./autofill/main/main-ssh-agent.service";
|
||||
import { DesktopAutofillSettingsService } from "./autofill/services/desktop-autofill-settings.service";
|
||||
@@ -46,7 +47,6 @@ import { WindowMain } from "./main/window.main";
|
||||
import { NativeAutofillMain } from "./platform/main/autofill/native-autofill.main";
|
||||
import { ClipboardMain } from "./platform/main/clipboard.main";
|
||||
import { DesktopCredentialStorageListener } from "./platform/main/desktop-credential-storage-listener";
|
||||
import { MainCryptoFunctionService } from "./platform/main/main-crypto-function.service";
|
||||
import { VersionMain } from "./platform/main/version.main";
|
||||
import { DesktopSettingsService } from "./platform/services/desktop-settings.service";
|
||||
import { ElectronLogMainService } from "./platform/services/electron-log.main.service";
|
||||
@@ -68,7 +68,7 @@ export class Main {
|
||||
desktopCredentialStorageListener: DesktopCredentialStorageListener;
|
||||
mainBiometricsIpcListener: MainBiometricsIPCListener;
|
||||
desktopSettingsService: DesktopSettingsService;
|
||||
mainCryptoFunctionService: MainCryptoFunctionService;
|
||||
mainCryptoFunctionService: NodeCryptoFunctionService;
|
||||
migrationRunner: MigrationRunner;
|
||||
ssoUrlService: SsoUrlService;
|
||||
|
||||
@@ -140,8 +140,7 @@ export class Main {
|
||||
|
||||
this.i18nService = new I18nMainService("en", "./locales/", globalStateProvider);
|
||||
|
||||
this.mainCryptoFunctionService = new MainCryptoFunctionService();
|
||||
this.mainCryptoFunctionService.init();
|
||||
this.mainCryptoFunctionService = new NodeCryptoFunctionService();
|
||||
|
||||
const stateEventRegistrarService = new StateEventRegistrarService(
|
||||
globalStateProvider,
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
import { ipcMain } from "electron";
|
||||
|
||||
import { CryptoFunctionService } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service";
|
||||
import { crypto } from "@bitwarden/desktop-napi";
|
||||
import { NodeCryptoFunctionService } from "@bitwarden/node/services/node-crypto-function.service";
|
||||
|
||||
export class MainCryptoFunctionService
|
||||
extends NodeCryptoFunctionService
|
||||
implements CryptoFunctionService
|
||||
{
|
||||
init() {
|
||||
ipcMain.handle(
|
||||
"crypto.argon2",
|
||||
async (
|
||||
event,
|
||||
opts: {
|
||||
password: Uint8Array;
|
||||
salt: Uint8Array;
|
||||
iterations: number;
|
||||
memory: number;
|
||||
parallelism: number;
|
||||
},
|
||||
) => {
|
||||
return await crypto.argon2(
|
||||
Buffer.from(opts.password),
|
||||
Buffer.from(opts.salt),
|
||||
opts.iterations,
|
||||
opts.memory,
|
||||
opts.parallelism,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -98,17 +98,6 @@ const nativeMessaging = {
|
||||
},
|
||||
};
|
||||
|
||||
const crypto = {
|
||||
argon2: (
|
||||
password: Uint8Array,
|
||||
salt: Uint8Array,
|
||||
iterations: number,
|
||||
memory: number,
|
||||
parallelism: number,
|
||||
): Promise<Uint8Array> =>
|
||||
ipcRenderer.invoke("crypto.argon2", { password, salt, iterations, memory, parallelism }),
|
||||
};
|
||||
|
||||
const ephemeralStore = {
|
||||
setEphemeralValue: (key: string, value: string): Promise<void> =>
|
||||
ipcRenderer.invoke("setEphemeralValue", { key, value }),
|
||||
|
||||
@@ -41,11 +41,6 @@ const common = {
|
||||
},
|
||||
type: "asset/resource",
|
||||
},
|
||||
{
|
||||
test: /argon2(-simd)?\.wasm$/,
|
||||
loader: "base64-loader",
|
||||
type: "javascript/auto",
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [],
|
||||
@@ -154,13 +149,7 @@ const renderer = {
|
||||
test: /[\/\\]@angular[\/\\].+\.js$/,
|
||||
parser: { system: true },
|
||||
},
|
||||
{
|
||||
test: /argon2(-simd)?\.wasm$/,
|
||||
loader: "base64-loader",
|
||||
type: "javascript/auto",
|
||||
},
|
||||
],
|
||||
noParse: /argon2(-simd)?\.wasm$/,
|
||||
},
|
||||
experiments: {
|
||||
asyncWebAssembly: true,
|
||||
|
||||
@@ -90,11 +90,6 @@ const moduleRules = [
|
||||
test: /\.[jt]sx?$/,
|
||||
loader: "@ngtools/webpack",
|
||||
},
|
||||
{
|
||||
test: /argon2(-simd)?\.wasm$/,
|
||||
loader: "base64-loader",
|
||||
type: "javascript/auto",
|
||||
},
|
||||
];
|
||||
|
||||
const plugins = [
|
||||
@@ -404,7 +399,6 @@ const webpackConfig = {
|
||||
clean: true,
|
||||
},
|
||||
module: {
|
||||
noParse: /argon2(-simd)?\.wasm$/,
|
||||
rules: moduleRules,
|
||||
},
|
||||
experiments: {
|
||||
|
||||
@@ -12,13 +12,6 @@ export abstract class CryptoFunctionService {
|
||||
algorithm: "sha256" | "sha512",
|
||||
iterations: number,
|
||||
): Promise<Uint8Array>;
|
||||
abstract argon2(
|
||||
password: string | Uint8Array,
|
||||
salt: string | Uint8Array,
|
||||
iterations: number,
|
||||
memory: number,
|
||||
parallelism: number,
|
||||
): Promise<Uint8Array>;
|
||||
abstract hkdf(
|
||||
ikm: Uint8Array,
|
||||
salt: string | Uint8Array,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import * as argon2 from "argon2-browser";
|
||||
import * as forge from "node-forge";
|
||||
|
||||
import { EncryptionType } from "../../../platform/enums";
|
||||
@@ -14,7 +13,6 @@ import { CryptoFunctionService } from "../abstractions/crypto-function.service";
|
||||
export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
private crypto: Crypto;
|
||||
private subtle: SubtleCrypto;
|
||||
private wasmSupported: boolean;
|
||||
|
||||
constructor(globalContext: { crypto: Crypto }) {
|
||||
if (globalContext?.crypto?.subtle == null) {
|
||||
@@ -24,7 +22,6 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
}
|
||||
this.crypto = globalContext.crypto;
|
||||
this.subtle = this.crypto.subtle;
|
||||
this.wasmSupported = this.checkIfWasmSupported();
|
||||
}
|
||||
|
||||
async pbkdf2(
|
||||
@@ -55,33 +52,6 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
return new Uint8Array(buffer);
|
||||
}
|
||||
|
||||
async argon2(
|
||||
password: string | Uint8Array,
|
||||
salt: string | Uint8Array,
|
||||
iterations: number,
|
||||
memory: number,
|
||||
parallelism: number,
|
||||
): Promise<Uint8Array> {
|
||||
if (!this.wasmSupported) {
|
||||
throw "Webassembly support is required for the Argon2 KDF feature.";
|
||||
}
|
||||
|
||||
const passwordArr = new Uint8Array(this.toBuf(password));
|
||||
const saltArr = new Uint8Array(this.toBuf(salt));
|
||||
|
||||
const result = await argon2.hash({
|
||||
pass: passwordArr,
|
||||
salt: saltArr,
|
||||
time: iterations,
|
||||
mem: memory,
|
||||
parallelism: parallelism,
|
||||
hashLen: 32,
|
||||
type: argon2.ArgonType.Argon2id,
|
||||
});
|
||||
argon2.unloadRuntime();
|
||||
return result.hash;
|
||||
}
|
||||
|
||||
async hkdf(
|
||||
ikm: Uint8Array,
|
||||
salt: string | Uint8Array,
|
||||
@@ -442,21 +412,4 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
private toWebCryptoAesMode(mode: "cbc" | "ecb"): string {
|
||||
return mode === "cbc" ? "AES-CBC" : "AES-ECB";
|
||||
}
|
||||
|
||||
// ref: https://stackoverflow.com/a/47880734/1090359
|
||||
private checkIfWasmSupported(): boolean {
|
||||
try {
|
||||
if (typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function") {
|
||||
const module = new WebAssembly.Module(
|
||||
Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00),
|
||||
);
|
||||
if (module instanceof WebAssembly.Module) {
|
||||
return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { PBKDF2KdfConfig, Argon2KdfConfig } from "@bitwarden/key-management";
|
||||
|
||||
import { CryptoFunctionService } from "../../key-management/crypto/abstractions/crypto-function.service";
|
||||
import { CsprngArray } from "../../types/csprng";
|
||||
import { SdkLoadService } from "../abstractions/sdk/sdk-load.service";
|
||||
import { EncryptionType } from "../enums";
|
||||
import { SymmetricCryptoKey } from "../models/domain/symmetric-crypto-key";
|
||||
|
||||
@@ -77,27 +78,30 @@ describe("KeyGenerationService", () => {
|
||||
|
||||
describe("deriveKeyFromPassword", () => {
|
||||
it("should derive a 32 byte key from a password using pbkdf2", async () => {
|
||||
const password = "password";
|
||||
const salt = "salt";
|
||||
const password = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
const salt = new Uint8Array([9, 10, 11, 12]);
|
||||
const kdfConfig = new PBKDF2KdfConfig(600_000);
|
||||
|
||||
cryptoFunctionService.pbkdf2.mockResolvedValue(new Uint8Array(32));
|
||||
Object.defineProperty(SdkLoadService, "Ready", {
|
||||
value: Promise.resolve(),
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
const key = await sut.deriveKeyFromPassword(password, salt, kdfConfig);
|
||||
|
||||
expect(key.inner().type).toEqual(EncryptionType.AesCbc256_B64);
|
||||
});
|
||||
|
||||
it("should derive a 32 byte key from a password using argon2id", async () => {
|
||||
const password = "password";
|
||||
const salt = "salt";
|
||||
const password = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
const salt = new Uint8Array([9, 10, 11, 12]);
|
||||
const kdfConfig = new Argon2KdfConfig(3, 16, 4);
|
||||
|
||||
cryptoFunctionService.hash.mockResolvedValue(new Uint8Array(32));
|
||||
cryptoFunctionService.argon2.mockResolvedValue(new Uint8Array(32));
|
||||
Object.defineProperty(SdkLoadService, "Ready", {
|
||||
value: Promise.resolve(),
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
const key = await sut.deriveKeyFromPassword(password, salt, kdfConfig);
|
||||
|
||||
expect(key.inner().type).toEqual(EncryptionType.AesCbc256_B64);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
// @ts-strict-ignore
|
||||
// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop.
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { KdfConfig, PBKDF2KdfConfig, Argon2KdfConfig, KdfType } from "@bitwarden/key-management";
|
||||
import { KdfConfig } from "@bitwarden/key-management";
|
||||
import { PureCrypto } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { CryptoFunctionService } from "../../key-management/crypto/abstractions/crypto-function.service";
|
||||
import { CsprngArray } from "../../types/csprng";
|
||||
import { KeyGenerationService as KeyGenerationServiceAbstraction } from "../abstractions/key-generation.service";
|
||||
import { SdkLoadService } from "../abstractions/sdk/sdk-load.service";
|
||||
import { EncryptionType } from "../enums";
|
||||
import { Utils } from "../misc/utils";
|
||||
import { SymmetricCryptoKey } from "../models/domain/symmetric-crypto-key";
|
||||
@@ -47,38 +49,17 @@ export class KeyGenerationService implements KeyGenerationServiceAbstraction {
|
||||
salt: string | Uint8Array,
|
||||
kdfConfig: KdfConfig,
|
||||
): Promise<SymmetricCryptoKey> {
|
||||
let key: Uint8Array = null;
|
||||
if (kdfConfig.kdfType == null || kdfConfig.kdfType === KdfType.PBKDF2_SHA256) {
|
||||
if (kdfConfig.iterations == null) {
|
||||
kdfConfig.iterations = PBKDF2KdfConfig.ITERATIONS.defaultValue;
|
||||
}
|
||||
|
||||
key = await this.cryptoFunctionService.pbkdf2(password, salt, "sha256", kdfConfig.iterations);
|
||||
} else if (kdfConfig.kdfType == KdfType.Argon2id) {
|
||||
if (kdfConfig.iterations == null) {
|
||||
kdfConfig.iterations = Argon2KdfConfig.ITERATIONS.defaultValue;
|
||||
}
|
||||
|
||||
if (kdfConfig.memory == null) {
|
||||
kdfConfig.memory = Argon2KdfConfig.MEMORY.defaultValue;
|
||||
}
|
||||
|
||||
if (kdfConfig.parallelism == null) {
|
||||
kdfConfig.parallelism = Argon2KdfConfig.PARALLELISM.defaultValue;
|
||||
}
|
||||
|
||||
const saltHash = await this.cryptoFunctionService.hash(salt, "sha256");
|
||||
key = await this.cryptoFunctionService.argon2(
|
||||
password,
|
||||
saltHash,
|
||||
kdfConfig.iterations,
|
||||
kdfConfig.memory * 1024, // convert to KiB from MiB
|
||||
kdfConfig.parallelism,
|
||||
);
|
||||
} else {
|
||||
throw new Error("Unknown Kdf.");
|
||||
if (typeof password === "string") {
|
||||
password = new TextEncoder().encode(password);
|
||||
}
|
||||
return new SymmetricCryptoKey(key);
|
||||
if (typeof salt === "string") {
|
||||
salt = new TextEncoder().encode(salt);
|
||||
}
|
||||
|
||||
await SdkLoadService.Ready;
|
||||
return new SymmetricCryptoKey(
|
||||
PureCrypto.derive_kdf_material(password, salt, kdfConfig.toSdkConfig()),
|
||||
);
|
||||
}
|
||||
|
||||
async stretchKey(key: SymmetricCryptoKey): Promise<SymmetricCryptoKey> {
|
||||
|
||||
@@ -33,29 +33,6 @@ export class NodeCryptoFunctionService implements CryptoFunctionService {
|
||||
});
|
||||
}
|
||||
|
||||
async argon2(
|
||||
password: string | Uint8Array,
|
||||
salt: string | Uint8Array,
|
||||
iterations: number,
|
||||
memory: number,
|
||||
parallelism: number,
|
||||
): Promise<Uint8Array> {
|
||||
const nodePassword = this.toNodeValue(password);
|
||||
const nodeSalt = this.toNodeBuffer(this.toUint8Buffer(salt));
|
||||
|
||||
const argon2 = await import("argon2");
|
||||
const hash = await argon2.hash(nodePassword, {
|
||||
salt: nodeSalt,
|
||||
raw: true,
|
||||
hashLength: 32,
|
||||
timeCost: iterations,
|
||||
memoryCost: memory,
|
||||
parallelism: parallelism,
|
||||
type: argon2.argon2id,
|
||||
});
|
||||
return this.toUint8Buffer(hash);
|
||||
}
|
||||
|
||||
// ref: https://tools.ietf.org/html/rfc5869
|
||||
async hkdf(
|
||||
ikm: Uint8Array,
|
||||
|
||||
269
package-lock.json
generated
269
package-lock.json
generated
@@ -7,7 +7,6 @@
|
||||
"": {
|
||||
"name": "@bitwarden/clients",
|
||||
"version": "0.0.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0",
|
||||
"workspaces": [
|
||||
"apps/*",
|
||||
@@ -36,8 +35,6 @@
|
||||
"@nx/eslint": "21.1.2",
|
||||
"@nx/jest": "21.1.2",
|
||||
"@nx/js": "21.1.2",
|
||||
"argon2": "0.41.1",
|
||||
"argon2-browser": "1.18.0",
|
||||
"big-integer": "1.6.52",
|
||||
"bootstrap": "4.6.0",
|
||||
"braintree-web-drop-in": "1.44.0",
|
||||
@@ -64,7 +61,6 @@
|
||||
"oidc-client-ts": "2.4.1",
|
||||
"open": "10.1.2",
|
||||
"papaparse": "5.5.3",
|
||||
"patch-package": "8.0.0",
|
||||
"proper-lockfile": "4.1.2",
|
||||
"qrcode-parser": "2.1.3",
|
||||
"qrious": "4.0.2",
|
||||
@@ -102,7 +98,6 @@
|
||||
"@storybook/test-runner": "0.22.0",
|
||||
"@storybook/theming": "8.6.12",
|
||||
"@storybook/web-components-webpack5": "8.6.12",
|
||||
"@types/argon2-browser": "1.18.4",
|
||||
"@types/chrome": "0.0.306",
|
||||
"@types/firefox-webext-browser": "120.0.4",
|
||||
"@types/inquirer": "8.2.10",
|
||||
@@ -206,7 +201,6 @@
|
||||
"dependencies": {
|
||||
"@koa/multer": "4.0.0",
|
||||
"@koa/router": "13.1.0",
|
||||
"argon2": "0.41.1",
|
||||
"big-integer": "1.6.52",
|
||||
"browser-hrtime": "1.1.8",
|
||||
"chalk": "4.1.2",
|
||||
@@ -9873,15 +9867,6 @@
|
||||
"node": ">=4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@phc/format": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@phc/format/-/format-1.0.0.tgz",
|
||||
"integrity": "sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@phenomnomnominal/tsquery": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@phenomnomnominal/tsquery/-/tsquery-5.0.1.tgz",
|
||||
@@ -12071,13 +12056,6 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/argon2-browser": {
|
||||
"version": "1.18.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/argon2-browser/-/argon2-browser-1.18.4.tgz",
|
||||
"integrity": "sha512-K/PHAEKzdCY4mCRhgUTBcuTxeaJyLoPcd5pJ1UFSTb/FAPjj3TCK4EM/DvNmVtDzkQBMD5peJjtch3kVQDf4YQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/aria-query": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
|
||||
@@ -14799,27 +14777,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/argon2": {
|
||||
"version": "0.41.1",
|
||||
"resolved": "https://registry.npmjs.org/argon2/-/argon2-0.41.1.tgz",
|
||||
"integrity": "sha512-dqCW8kJXke8Ik+McUcMDltrbuAWETPyU6iq+4AhxqKphWi7pChB/Zgd/Tp/o8xRLbg8ksMj46F/vph9wnxpTzQ==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@phc/format": "^1.0.0",
|
||||
"node-addon-api": "^8.1.0",
|
||||
"node-gyp-build": "^4.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/argon2-browser": {
|
||||
"version": "1.18.0",
|
||||
"resolved": "https://registry.npmjs.org/argon2-browser/-/argon2-browser-1.18.0.tgz",
|
||||
"integrity": "sha512-ImVAGIItnFnvET1exhsQB7apRztcoC5TnlSqernMJDUjbc/DLq3UEYeXFrLPrlaIl8cVfwnXb6wX2KpFf2zxHw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
@@ -16390,6 +16347,7 @@
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
|
||||
"integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.0",
|
||||
@@ -18210,6 +18168,7 @@
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
||||
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-define-property": "^1.0.0",
|
||||
@@ -20914,15 +20873,6 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/find-yarn-workspace-root": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz",
|
||||
"integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"micromatch": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/flat": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
|
||||
@@ -21939,6 +21889,7 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
||||
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-define-property": "^1.0.0"
|
||||
@@ -23621,6 +23572,7 @@
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
|
||||
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/isbinaryfile": {
|
||||
@@ -25682,25 +25634,6 @@
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/json-stable-stringify": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz",
|
||||
"integrity": "sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.8",
|
||||
"call-bound": "^1.0.4",
|
||||
"isarray": "^2.0.5",
|
||||
"jsonify": "^0.0.1",
|
||||
"object-keys": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/json-stable-stringify-without-jsonify": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
|
||||
@@ -25744,15 +25677,6 @@
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonify": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz",
|
||||
"integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==",
|
||||
"license": "Public Domain",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonparse": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
|
||||
@@ -25875,15 +25799,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/klaw-sync": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz",
|
||||
"integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.1.11"
|
||||
}
|
||||
},
|
||||
"node_modules/kleur": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
|
||||
@@ -29102,15 +29017,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-addon-api": {
|
||||
"version": "8.4.0",
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.4.0.tgz",
|
||||
"integrity": "sha512-D9DI/gXHvVmjHS08SVch0Em8G5S1P+QWtU31appcKT/8wFSPRcdHadIFSAntdMMVM5zz+/DL+bL/gz3UDppqtg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^18 || ^20 || >= 21"
|
||||
}
|
||||
},
|
||||
"node_modules/node-api-version": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.1.tgz",
|
||||
@@ -30703,6 +30609,7 @@
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -31585,171 +31492,6 @@
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/patch-package": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.0.tgz",
|
||||
"integrity": "sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@yarnpkg/lockfile": "^1.1.0",
|
||||
"chalk": "^4.1.2",
|
||||
"ci-info": "^3.7.0",
|
||||
"cross-spawn": "^7.0.3",
|
||||
"find-yarn-workspace-root": "^2.0.0",
|
||||
"fs-extra": "^9.0.0",
|
||||
"json-stable-stringify": "^1.0.2",
|
||||
"klaw-sync": "^6.0.0",
|
||||
"minimist": "^1.2.6",
|
||||
"open": "^7.4.2",
|
||||
"rimraf": "^2.6.3",
|
||||
"semver": "^7.5.3",
|
||||
"slash": "^2.0.0",
|
||||
"tmp": "^0.0.33",
|
||||
"yaml": "^2.2.2"
|
||||
},
|
||||
"bin": {
|
||||
"patch-package": "index.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14",
|
||||
"npm": ">5"
|
||||
}
|
||||
},
|
||||
"node_modules/patch-package/node_modules/brace-expansion": {
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/patch-package/node_modules/fs-extra": {
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
|
||||
"integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"at-least-node": "^1.0.0",
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/patch-package/node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"deprecated": "Glob versions prior to v9 are no longer supported",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/patch-package/node_modules/is-docker": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
|
||||
"integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"is-docker": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/patch-package/node_modules/is-wsl": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
|
||||
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-docker": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/patch-package/node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/patch-package/node_modules/open": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
|
||||
"integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-docker": "^2.0.0",
|
||||
"is-wsl": "^2.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/patch-package/node_modules/rimraf": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||
"deprecated": "Rimraf versions prior to v4 are no longer supported",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/patch-package/node_modules/slash": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
|
||||
"integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/patch-package/node_modules/tmp": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"os-tmpdir": "~1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/path-browserify": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
|
||||
@@ -34504,6 +34246,7 @@
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
||||
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"define-data-property": "^1.1.4",
|
||||
|
||||
@@ -29,8 +29,7 @@
|
||||
"build-storybook": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" ng run components:build-storybook",
|
||||
"build-storybook:ci": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" ng run components:build-storybook --webpack-stats-json",
|
||||
"test-stories": "test-storybook --url http://localhost:6006",
|
||||
"test-stories:watch": "test-stories --watch",
|
||||
"postinstall": "patch-package"
|
||||
"test-stories:watch": "test-stories --watch"
|
||||
},
|
||||
"workspaces": [
|
||||
"apps/*",
|
||||
@@ -62,7 +61,6 @@
|
||||
"@storybook/test-runner": "0.22.0",
|
||||
"@storybook/theming": "8.6.12",
|
||||
"@storybook/web-components-webpack5": "8.6.12",
|
||||
"@types/argon2-browser": "1.18.4",
|
||||
"@types/chrome": "0.0.306",
|
||||
"@types/firefox-webext-browser": "120.0.4",
|
||||
"@types/inquirer": "8.2.10",
|
||||
@@ -172,8 +170,6 @@
|
||||
"@nx/eslint": "21.1.2",
|
||||
"@nx/jest": "21.1.2",
|
||||
"@nx/js": "21.1.2",
|
||||
"argon2": "0.41.1",
|
||||
"argon2-browser": "1.18.0",
|
||||
"big-integer": "1.6.52",
|
||||
"bootstrap": "4.6.0",
|
||||
"braintree-web-drop-in": "1.44.0",
|
||||
@@ -200,7 +196,6 @@
|
||||
"oidc-client-ts": "2.4.1",
|
||||
"open": "10.1.2",
|
||||
"papaparse": "5.5.3",
|
||||
"patch-package": "8.0.0",
|
||||
"proper-lockfile": "4.1.2",
|
||||
"qrcode-parser": "2.1.3",
|
||||
"qrious": "4.0.2",
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
diff --git a/node_modules/argon2-browser/lib/argon2.js b/node_modules/argon2-browser/lib/argon2.js
|
||||
index ffa77a5..98b2f13 100644
|
||||
--- a/node_modules/argon2-browser/lib/argon2.js
|
||||
+++ b/node_modules/argon2-browser/lib/argon2.js
|
||||
@@ -78,16 +78,27 @@
|
||||
if (global.loadArgon2WasmBinary) {
|
||||
return global.loadArgon2WasmBinary();
|
||||
}
|
||||
+
|
||||
+ const simd = checkIfSIMDSupported();
|
||||
+
|
||||
if (typeof require === 'function') {
|
||||
- return Promise.resolve(require('../dist/argon2.wasm')).then(
|
||||
- (wasmModule) => {
|
||||
- return decodeWasmBinary(wasmModule);
|
||||
- }
|
||||
- );
|
||||
+ if (simd) {
|
||||
+ return Promise.resolve(require('../dist/argon2-simd.wasm')).then(
|
||||
+ (wasmModule) => {
|
||||
+ return decodeWasmBinary(wasmModule);
|
||||
+ }
|
||||
+ );
|
||||
+ } else {
|
||||
+ return Promise.resolve(require('../dist/argon2.wasm')).then(
|
||||
+ (wasmModule) => {
|
||||
+ return decodeWasmBinary(wasmModule);
|
||||
+ }
|
||||
+ );
|
||||
+ }
|
||||
}
|
||||
const wasmPath =
|
||||
global.argon2WasmPath ||
|
||||
- 'node_modules/argon2-browser/dist/argon2.wasm';
|
||||
+ 'node_modules/argon2-browser/dist/argon2' + (simd? "-simd" : "") + '.wasm';
|
||||
return fetch(wasmPath)
|
||||
.then((response) => response.arrayBuffer())
|
||||
.then((ab) => new Uint8Array(ab));
|
||||
@@ -351,7 +362,28 @@
|
||||
loadModule._module.unloadRuntime();
|
||||
delete loadModule._promise;
|
||||
delete loadModule._module;
|
||||
+ if (typeof require !== 'undefined') {
|
||||
+ delete require.cache[require.resolve('../dist/argon2.js')]
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // ref: https://stackoverflow.com/a/47880734/1090359
|
||||
+ // ref: https://github.com/GoogleChromeLabs/wasm-feature-detect/blob/main/src/detectors/simd/module.wat (translated with wat2wasm)
|
||||
+ function checkIfSIMDSupported() {
|
||||
+ try {
|
||||
+ if (typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function") {
|
||||
+ const module = new WebAssembly.Module(
|
||||
+ Uint8Array.of(0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01, 0x7b, 0x03, 0x02, 0x01, 0x00, 0x0a, 0x0a, 0x01, 0x08, 0x00, 0x41, 0x00, 0xfd, 0x0f, 0xfd, 0x62, 0x0b)
|
||||
+ );
|
||||
+ if (module instanceof WebAssembly.Module) {
|
||||
+ return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
|
||||
+ }
|
||||
+ }
|
||||
+ } catch {
|
||||
+ return false;
|
||||
}
|
||||
+ return false;
|
||||
}
|
||||
|
||||
return {
|
||||
Reference in New Issue
Block a user