mirror of
https://github.com/bitwarden/browser
synced 2026-02-10 13:40:06 +00:00
Tmp
This commit is contained in:
@@ -13,7 +13,7 @@ import { EncryptService } from "@bitwarden/common/key-management/crypto/abstract
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { KeyGenerationService } from "@bitwarden/common/platform/abstractions/key-generation.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { EncryptionType, HashPurpose } from "@bitwarden/common/platform/enums";
|
||||
import { HashPurpose } from "@bitwarden/common/platform/enums";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { EncryptedString } from "@bitwarden/common/platform/models/domain/enc-string";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
@@ -105,22 +105,25 @@ export class UserKeyRotationService {
|
||||
await this.keyService.makeUserKey(newMasterKey);
|
||||
|
||||
const userKey = CryptoClient.generate_user_key();
|
||||
this.logService.info("[Userkey rotation] Encrypting user key in new format");
|
||||
this.logService.info("[Userkey rotation] Encrypting user key in new format" + userKey);
|
||||
const userkeyEncodedBytes = Utils.fromB64ToArray(userKey);
|
||||
const stretchedMasterKey = await this.keyGenerationService.stretchKey(newMasterKey);
|
||||
const userkeyEncrypted = await this.encryptService.encrypt(
|
||||
userkeyEncodedBytes,
|
||||
stretchedMasterKey,
|
||||
);
|
||||
const userkeyBytes = Utils.fromB64ToArray(CryptoClient.decode_userkey(userKey).Aes256CbcHmac);
|
||||
newUnencryptedUserKey = new SymmetricCryptoKey(userkeyBytes, EncryptionType.AesCbc256_HmacSha256_B64) as UserKey;
|
||||
newMasterKeyEncryptedUserKey = userkeyEncrypted;
|
||||
this.logService.info("[Userkey rotation] User key encrypted in new format" + userkeyEncrypted.encryptedString);
|
||||
newUnencryptedUserKey = new SymmetricCryptoKey(userkeyEncodedBytes) as UserKey;
|
||||
newMasterKeyEncryptedUserKey
|
||||
= userkeyEncrypted;
|
||||
|
||||
if (!newUnencryptedUserKey || !newMasterKeyEncryptedUserKey) {
|
||||
this.logService.info("[Userkey rotation] User key could not be created. Aborting!");
|
||||
throw new Error("User key could not be created");
|
||||
}
|
||||
|
||||
this.logService.info("[Userkey rotation] User key created successfully");
|
||||
|
||||
const newMasterKeyAuthenticationHash = await this.keyService.hashMasterKey(
|
||||
newMasterPassword,
|
||||
newMasterKey,
|
||||
|
||||
@@ -295,7 +295,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.stateProvider.setUserState(DEVICE_KEY, deviceKey?.toJSON(), userId);
|
||||
//await this.stateProvider.setUserState(DEVICE_KEY, deviceKey?.toJSON(), userId);
|
||||
} catch (e) {
|
||||
this.logService.error("Failed to set device key", e);
|
||||
}
|
||||
@@ -304,7 +304,6 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction {
|
||||
private async makeDeviceKey(): Promise<DeviceKey> {
|
||||
// Create 512-bit device key
|
||||
const deviceKey = (await this.keyGenerationService.createKey(512)) as DeviceKey;
|
||||
|
||||
return deviceKey;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
// @ts-strict-ignore
|
||||
import { firstValueFrom, map, Observable } from "rxjs";
|
||||
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { CryptoClient } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { EncryptService } from "../../../key-management/crypto/abstractions/encrypt.service";
|
||||
import { KeyGenerationService } from "../../../platform/abstractions/key-generation.service";
|
||||
import { LogService } from "../../../platform/abstractions/log.service";
|
||||
@@ -198,11 +195,7 @@ export class MasterPasswordService implements InternalMasterPasswordServiceAbstr
|
||||
return new SymmetricCryptoKey(decUserKey) as UserKey;
|
||||
} else {
|
||||
this.logService.info("[MasterPasswordService] Userkey in new format; using sdk");
|
||||
const decodedKey = CryptoClient.decode_userkey(decUserKey);
|
||||
if (decodedKey.Aes256CbcHmac != null) {
|
||||
const key = Utils.fromB64ToArray(decodedKey.Aes256CbcHmac);
|
||||
return new SymmetricCryptoKey(key) as UserKey;
|
||||
}
|
||||
return new SymmetricCryptoKey(decUserKey) as UserKey;
|
||||
}
|
||||
} else {
|
||||
throw new Error("Unsupported encryption type.");
|
||||
|
||||
@@ -40,11 +40,15 @@ export class EncryptServiceImplementation implements EncryptService {
|
||||
plainBuf = plainValue;
|
||||
}
|
||||
|
||||
const encObj = await this.aesEncrypt(plainBuf, key);
|
||||
const iv = Utils.fromBufferToB64(encObj.iv);
|
||||
const data = Utils.fromBufferToB64(encObj.data);
|
||||
const mac = encObj.mac != null ? Utils.fromBufferToB64(encObj.mac) : null;
|
||||
return new EncString(encObj.key.encryptionType(), data, iv, mac);
|
||||
if (key.encryptionType() === EncryptionType.AesCbc256_HmacSha256_B64) {
|
||||
const encObj = await this.aesEncrypt(plainBuf, key);
|
||||
const iv = Utils.fromBufferToB64(encObj.iv);
|
||||
const data = Utils.fromBufferToB64(encObj.data);
|
||||
const mac = Utils.fromBufferToB64(encObj.mac);
|
||||
return new EncString(key.encryptionType(), data, iv, mac);
|
||||
} else {
|
||||
throw new Error("Unsupported encryption type.");
|
||||
}
|
||||
}
|
||||
|
||||
async encryptToBytes(plainValue: Uint8Array, key: SymmetricCryptoKey): Promise<EncArrayBuffer> {
|
||||
@@ -52,21 +56,17 @@ export class EncryptServiceImplementation implements EncryptService {
|
||||
throw new Error("No encryption key provided.");
|
||||
}
|
||||
|
||||
const encValue = await this.aesEncrypt(plainValue, key);
|
||||
let macLen = 0;
|
||||
if (encValue.mac != null) {
|
||||
macLen = encValue.mac.byteLength;
|
||||
}
|
||||
|
||||
const encBytes = new Uint8Array(1 + encValue.iv.byteLength + macLen + encValue.data.byteLength);
|
||||
encBytes.set([encValue.key.encryptionType()]);
|
||||
encBytes.set(new Uint8Array(encValue.iv), 1);
|
||||
if (encValue.mac != null) {
|
||||
if (key.encryptionType() !== EncryptionType.AesCbc256_HmacSha256_B64) {
|
||||
const encValue = await this.aesEncrypt(plainValue, key);
|
||||
const encBytes = new Uint8Array(1 + encValue.iv.byteLength + encValue.mac.byteLength + encValue.data.byteLength);
|
||||
encBytes.set([key.encryptionType()]);
|
||||
encBytes.set(new Uint8Array(encValue.iv), 1);
|
||||
encBytes.set(new Uint8Array(encValue.mac), 1 + encValue.iv.byteLength);
|
||||
encBytes.set(new Uint8Array(encValue.data), 1 + encValue.iv.byteLength + encValue.mac.byteLength);
|
||||
return new EncArrayBuffer(encBytes);
|
||||
} else {
|
||||
throw new Error("Unsupported encryption type.");
|
||||
}
|
||||
|
||||
encBytes.set(new Uint8Array(encValue.data), 1 + encValue.iv.byteLength + macLen);
|
||||
return new EncArrayBuffer(encBytes);
|
||||
}
|
||||
|
||||
async decryptToUtf8(
|
||||
@@ -79,35 +79,35 @@ export class EncryptServiceImplementation implements EncryptService {
|
||||
}
|
||||
|
||||
// DO NOT REMOVE OR MOVE. This prevents downgrade to mac-less CBC, which would compromise integrity and confidentiality.
|
||||
if (key.macKey != null && encString?.mac == null) {
|
||||
this.logService.error(
|
||||
"[Encrypt service] Key has mac key but payload is missing mac bytes. Key type " +
|
||||
encryptionTypeName(key.encryptionType()) +
|
||||
"Payload type " +
|
||||
encryptionTypeName(encString.encryptionType),
|
||||
"Decrypt context: " + decryptContext,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
if (key.encryptionType() === EncryptionType.AesCbc256_HmacSha256_B64) {
|
||||
if (encString?.mac == null) {
|
||||
this.logService.error(
|
||||
"[Encrypt service] Key has mac key but payload is missing mac bytes. Key type " +
|
||||
encryptionTypeName(key.encryptionType()) +
|
||||
"Payload type " +
|
||||
encryptionTypeName(encString.encryptionType),
|
||||
"Decrypt context: " + decryptContext,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (key.encryptionType() !== encString.encryptionType) {
|
||||
this.logService.error(
|
||||
"[Encrypt service] Key encryption type does not match payload encryption type. Key type " +
|
||||
encryptionTypeName(key.encryptionType()) +
|
||||
"Payload type " +
|
||||
encryptionTypeName(encString.encryptionType),
|
||||
"Decrypt context: " + decryptContext,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
if (encString.encryptionType !== EncryptionType.AesCbc256_HmacSha256_B64) {
|
||||
this.logService.error(
|
||||
"[Encrypt service] Key encryption type does not match payload encryption type. Key type " +
|
||||
encryptionTypeName(key.encryptionType()) +
|
||||
"Payload type " +
|
||||
encryptionTypeName(encString.encryptionType),
|
||||
"Decrypt context: " + decryptContext,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
const fastParams = this.cryptoFunctionService.aesDecryptFastParameters(
|
||||
encString.data,
|
||||
encString.iv,
|
||||
encString.mac,
|
||||
key,
|
||||
);
|
||||
if (fastParams.macKey != null && fastParams.mac != null) {
|
||||
const fastParams = this.cryptoFunctionService.aesDecryptFastParameters(
|
||||
encString.data,
|
||||
encString.iv,
|
||||
encString.mac,
|
||||
key,
|
||||
);
|
||||
const computedMac = await this.cryptoFunctionService.hmacFast(
|
||||
fastParams.macData,
|
||||
fastParams.macKey,
|
||||
@@ -125,9 +125,14 @@ export class EncryptServiceImplementation implements EncryptService {
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
return await this.cryptoFunctionService.aesDecryptFast({ mode: "cbc", parameters: fastParams });
|
||||
} else if (key.encryptionType() === EncryptionType.AesCbc256_B64) {
|
||||
return Utils.fromBufferToByteString(await this.cryptoFunctionService.aesDecrypt(encString.dataBytes, encString.ivBytes, key.getInnerKey().encryptionKey, "cbc"));
|
||||
} else {
|
||||
throw new Error("Unsupported encryption type.");
|
||||
}
|
||||
|
||||
return await this.cryptoFunctionService.aesDecryptFast({ mode: "cbc", parameters: fastParams });
|
||||
}
|
||||
|
||||
async decryptToBytes(
|
||||
@@ -143,36 +148,37 @@ export class EncryptServiceImplementation implements EncryptService {
|
||||
throw new Error("Nothing provided for decryption.");
|
||||
}
|
||||
|
||||
// DO NOT REMOVE OR MOVE. This prevents downgrade to mac-less CBC, which would compromise integrity and confidentiality.
|
||||
if (key.macKey != null && encThing.macBytes == null) {
|
||||
this.logService.error(
|
||||
"[Encrypt service] Key has mac key but payload is missing mac bytes. Key type " +
|
||||
encryptionTypeName(key.encryptionType()) +
|
||||
" Payload type " +
|
||||
encryptionTypeName(encThing.encryptionType) +
|
||||
" Decrypt context: " +
|
||||
decryptContext,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
const innerKey = key.getInnerKey();
|
||||
if (innerKey.type == EncryptionType.AesCbc256_HmacSha256_B64) {
|
||||
// DO NOT REMOVE OR MOVE. This prevents downgrade to mac-less CBC, which would compromise integrity and confidentiality.
|
||||
if (encThing.macBytes == null) {
|
||||
this.logService.error(
|
||||
"[Encrypt service] Key has mac key but payload is missing mac bytes. Key type " +
|
||||
encryptionTypeName(key.encryptionType()) +
|
||||
" Payload type " +
|
||||
encryptionTypeName(encThing.encryptionType) +
|
||||
" Decrypt context: " +
|
||||
decryptContext,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (key.encryptionType() !== encThing.encryptionType) {
|
||||
this.logService.error(
|
||||
"[Encrypt service] Key encryption type does not match payload encryption type. Key type " +
|
||||
encryptionTypeName(key.encryptionType()) +
|
||||
" Payload type " +
|
||||
encryptionTypeName(encThing.encryptionType) +
|
||||
" Decrypt context: " +
|
||||
decryptContext,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
if (encThing.encryptionType !== EncryptionType.AesCbc256_HmacSha256_B64) {
|
||||
this.logService.error(
|
||||
"[Encrypt service] Key encryption type does not match payload encryption type. Key type " +
|
||||
encryptionTypeName(key.encryptionType()) +
|
||||
" Payload type " +
|
||||
encryptionTypeName(encThing.encryptionType) +
|
||||
" Decrypt context: " +
|
||||
decryptContext,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (key.macKey != null && encThing.macBytes != null) {
|
||||
const macData = new Uint8Array(encThing.ivBytes.byteLength + encThing.dataBytes.byteLength);
|
||||
macData.set(new Uint8Array(encThing.ivBytes), 0);
|
||||
macData.set(new Uint8Array(encThing.dataBytes), encThing.ivBytes.byteLength);
|
||||
const computedMac = await this.cryptoFunctionService.hmac(macData, key.macKey, "sha256");
|
||||
const computedMac = await this.cryptoFunctionService.hmac(macData, innerKey.authenticationKey, "sha256");
|
||||
if (computedMac === null) {
|
||||
this.logMacFailed(
|
||||
"[Encrypt service#decryptToBytes] Failed to compute MAC." +
|
||||
@@ -204,7 +210,7 @@ export class EncryptServiceImplementation implements EncryptService {
|
||||
const result = await this.cryptoFunctionService.aesDecrypt(
|
||||
encThing.dataBytes,
|
||||
encThing.ivBytes,
|
||||
key.encryptionType()
|
||||
key.getInnerKey().encryptionKey,
|
||||
"cbc",
|
||||
);
|
||||
|
||||
|
||||
@@ -70,10 +70,6 @@ export class AccountKeys {
|
||||
return null;
|
||||
}
|
||||
return Object.assign(new AccountKeys(), obj, {
|
||||
cryptoSymmetricKey: EncryptionPair.fromJSON(
|
||||
obj?.cryptoSymmetricKey,
|
||||
SymmetricCryptoKey.fromJSON,
|
||||
),
|
||||
publicKey: Utils.fromByteStringToArray(obj?.publicKey),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ export class SymmetricCryptoKey {
|
||||
|
||||
meta: any;
|
||||
|
||||
constructor(key: Uint8Array, new_format = false) {
|
||||
constructor(key: Uint8Array) {
|
||||
if (key == null) {
|
||||
throw new Error("Must provide key");
|
||||
}
|
||||
@@ -41,6 +41,7 @@ export class SymmetricCryptoKey {
|
||||
authenticationKey: key.slice(32),
|
||||
}
|
||||
} else if (key.byteLength > 64) {
|
||||
this.newFormat = true;
|
||||
const decoded_key = CryptoClient.decode_userkey(key).Aes256CbcHmac;
|
||||
this.key = {
|
||||
type: EncryptionType.AesCbc256_HmacSha256_B64,
|
||||
@@ -56,7 +57,6 @@ export class SymmetricCryptoKey {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
|
||||
static fromString(s: string): SymmetricCryptoKey {
|
||||
if (s == null) {
|
||||
return null;
|
||||
@@ -68,8 +68,15 @@ export class SymmetricCryptoKey {
|
||||
|
||||
// For test only
|
||||
toJSON() {
|
||||
const innerKey = this.getInnerKey();
|
||||
// The whole object is constructed from the initial key, so just store the B64 key
|
||||
return { keyB64: Utils.fromBufferToB64(this) };
|
||||
if (innerKey.type === EncryptionType.AesCbc256_B64) {
|
||||
return { keyB64: Utils.fromBufferToB64(this.key.encryptionKey) };
|
||||
} else if (innerKey.type === EncryptionType.AesCbc256_HmacSha256_B64) {
|
||||
return { keyB64: Utils.fromBufferToB64(new Uint8Array([...innerKey.encryptionKey, ...innerKey.authenticationKey])) };
|
||||
} else {
|
||||
throw new Error("Unsupported encryption type.");
|
||||
}
|
||||
}
|
||||
|
||||
// For test only
|
||||
|
||||
@@ -4,6 +4,7 @@ import * as forge from "node-forge";
|
||||
import { Utils } from "../../platform/misc/utils";
|
||||
import { CsprngArray } from "../../types/csprng";
|
||||
import { CryptoFunctionService } from "../abstractions/crypto-function.service";
|
||||
import { EncryptionType } from "../enums";
|
||||
import { CbcDecryptParameters, EcbDecryptParameters } from "../models/domain/decrypt-parameters";
|
||||
import { SymmetricCryptoKey } from "../models/domain/symmetric-crypto-key";
|
||||
|
||||
@@ -256,8 +257,9 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
p.data = forge.util.decode64(data);
|
||||
p.iv = forge.util.decode64(iv);
|
||||
p.macData = p.iv + p.data;
|
||||
if (p.macKey == null && key.macKeyB64 != null) {
|
||||
p.macKey = forge.util.decode64(key.macKeyB64);
|
||||
const innerKey = key.getInnerKey();
|
||||
if (p.macKey == null && innerKey.type === EncryptionType.AesCbc256_HmacSha256_B64) {
|
||||
p.macKey = forge.util.decode64(Utils.fromBufferToB64(innerKey.authenticationKey));
|
||||
}
|
||||
if (mac != null) {
|
||||
p.mac = forge.util.decode64(mac);
|
||||
|
||||
Reference in New Issue
Block a user