mirror of
https://github.com/bitwarden/browser
synced 2026-02-28 10:33:31 +00:00
Replace uses of encstring with unsigned shared key
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
import { UnsignedSharedKey } from "@bitwarden/sdk-internal";
|
||||
|
||||
export type EncryptedOrganizationKeyData =
|
||||
| OrganizationEncryptedOrganizationKeyData
|
||||
| ProviderEncryptedOrganizationKeyData;
|
||||
|
||||
type OrganizationEncryptedOrganizationKeyData = {
|
||||
type: "organization";
|
||||
key: string;
|
||||
key: UnsignedSharedKey;
|
||||
};
|
||||
|
||||
type ProviderEncryptedOrganizationKeyData = {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { UnsignedSharedKey } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { EncryptService } from "../../../key-management/crypto/abstractions/encrypt.service";
|
||||
import { EncString } from "../../../key-management/crypto/models/enc-string";
|
||||
import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key";
|
||||
@@ -5,15 +7,15 @@ import { OrgKey, UserPrivateKey } from "../../../types/key";
|
||||
import { EncryptedOrganizationKeyData } from "../data/encrypted-organization-key.data";
|
||||
|
||||
export abstract class BaseEncryptedOrganizationKey {
|
||||
abstract get encryptedOrganizationKey(): EncString;
|
||||
abstract get encryptedOrganizationKey(): UnsignedSharedKey;
|
||||
|
||||
static fromData(data: EncryptedOrganizationKeyData) {
|
||||
switch (data.type) {
|
||||
case "organization":
|
||||
return new EncryptedOrganizationKey(data.key);
|
||||
return new EncryptedOrganizationKey(data.key as UnsignedSharedKey);
|
||||
|
||||
case "provider":
|
||||
return new ProviderEncryptedOrganizationKey(data.key, data.providerId);
|
||||
return new ProviderEncryptedOrganizationKey(data.key as UnsignedSharedKey, data.providerId);
|
||||
|
||||
default:
|
||||
return null;
|
||||
@@ -28,7 +30,7 @@ export abstract class BaseEncryptedOrganizationKey {
|
||||
}
|
||||
|
||||
export class EncryptedOrganizationKey implements BaseEncryptedOrganizationKey {
|
||||
constructor(private key: string) {}
|
||||
constructor(private key: UnsignedSharedKey) {}
|
||||
|
||||
async decrypt(encryptService: EncryptService, privateKey: UserPrivateKey) {
|
||||
return (await encryptService.decapsulateKeyUnsigned(
|
||||
@@ -38,7 +40,7 @@ export class EncryptedOrganizationKey implements BaseEncryptedOrganizationKey {
|
||||
}
|
||||
|
||||
get encryptedOrganizationKey() {
|
||||
return new EncString(this.key);
|
||||
return this.key;
|
||||
}
|
||||
|
||||
toData(): EncryptedOrganizationKeyData {
|
||||
@@ -51,7 +53,7 @@ export class EncryptedOrganizationKey implements BaseEncryptedOrganizationKey {
|
||||
|
||||
export class ProviderEncryptedOrganizationKey implements BaseEncryptedOrganizationKey {
|
||||
constructor(
|
||||
private key: string,
|
||||
private key: UnsignedSharedKey,
|
||||
private providerId: string,
|
||||
) {}
|
||||
|
||||
@@ -67,7 +69,7 @@ export class ProviderEncryptedOrganizationKey implements BaseEncryptedOrganizati
|
||||
}
|
||||
|
||||
get encryptedOrganizationKey() {
|
||||
return new EncString(this.key);
|
||||
return this.key;
|
||||
}
|
||||
|
||||
toData(): EncryptedOrganizationKeyData {
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
|
||||
import { UnsignedSharedKey } from "@bitwarden/sdk-internal";
|
||||
|
||||
// @ts-strict-ignore
|
||||
interface TokenizedPaymentMethod {
|
||||
type: "bankAccount" | "card" | "payPal";
|
||||
@@ -20,7 +23,7 @@ export class ProviderSetupRequest {
|
||||
businessName: string;
|
||||
billingEmail: string;
|
||||
token: string;
|
||||
key: string;
|
||||
key: UnsignedSharedKey;
|
||||
paymentMethod: TokenizedPaymentMethod;
|
||||
billingAddress: BillingAddress;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { UnsignedSharedKey } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { MemberDecryptionType } from "../../../auth/enums/sso";
|
||||
import { ProductTierType } from "../../../billing/enums";
|
||||
import { BaseResponse } from "../../../models/response/base.response";
|
||||
@@ -29,7 +31,7 @@ export class ProfileOrganizationResponse extends BaseResponse {
|
||||
seats: number;
|
||||
maxCollections: number;
|
||||
maxStorageGb?: number;
|
||||
key: string;
|
||||
key: UnsignedSharedKey;
|
||||
hasPublicAndPrivateKeys: boolean;
|
||||
status: OrganizationUserStatusType;
|
||||
type: OrganizationUserType;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { UnsignedSharedKey } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { BaseResponse } from "../../../models/response/base.response";
|
||||
import {
|
||||
ProviderStatusType,
|
||||
@@ -10,7 +12,7 @@ import { PermissionsApi } from "../api/permissions.api";
|
||||
export class ProfileProviderResponse extends BaseResponse {
|
||||
id: string;
|
||||
name: string;
|
||||
key: string;
|
||||
key: UnsignedSharedKey;
|
||||
status: ProviderUserStatusType;
|
||||
type: ProviderUserType;
|
||||
enabled: boolean;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { UnsignedSharedKey } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { DeviceType } from "../../../enums";
|
||||
import { BaseResponse } from "../../../models/response/base.response";
|
||||
|
||||
@@ -11,7 +13,7 @@ export class AuthRequestResponse extends BaseResponse {
|
||||
requestDeviceIdentifier: string;
|
||||
requestIpAddress: string;
|
||||
requestCountryName: string;
|
||||
key: string; // could be either an encrypted MasterKey or an encrypted UserKey
|
||||
key: UnsignedSharedKey; // could be either an encrypted MasterKey or an encrypted UserKey
|
||||
masterPasswordHash: string; // if hash is present, the `key` above is an encrypted MasterKey (else `key` is an encrypted UserKey)
|
||||
creationDate: string;
|
||||
requestApproved?: boolean;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// @ts-strict-ignore
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { UnsignedSharedKey } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { DeviceType } from "../../../enums";
|
||||
import { EncString } from "../../../key-management/crypto/models/enc-string";
|
||||
import { RotateableKeySet } from "../../../key-management/keys/models/rotateable-key-set";
|
||||
@@ -16,7 +18,7 @@ export class ProtectedDeviceResponse extends BaseResponse {
|
||||
this.type = this.getResponseProperty("type");
|
||||
this.creationDate = new Date(this.getResponseProperty("creationDate"));
|
||||
if (response.encryptedUserKey) {
|
||||
this.encryptedUserKey = new EncString(this.getResponseProperty("encryptedUserKey"));
|
||||
this.encryptedUserKey = this.getResponseProperty("encryptedUserKey");
|
||||
}
|
||||
if (response.encryptedPublicKey) {
|
||||
this.encryptedPublicKey = new EncString(this.getResponseProperty("encryptedPublicKey"));
|
||||
@@ -32,7 +34,7 @@ export class ProtectedDeviceResponse extends BaseResponse {
|
||||
* Intended to be the users symmetric key that is encrypted in some form, the current way to encrypt this is with
|
||||
* the devices public key.
|
||||
*/
|
||||
encryptedUserKey: EncString;
|
||||
encryptedUserKey: UnsignedSharedKey;
|
||||
/**
|
||||
* Intended to be the public key that was generated for a device upon trust and encrypted. Currenly encrypted using
|
||||
* a users symmetric key so that when trusted and unlocked a user can decrypt the public key for all their devices.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { UnsignedSharedKey } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { EncString } from "../../../../key-management/crypto/models/enc-string";
|
||||
import { BaseResponse } from "../../../../models/response/base.response";
|
||||
|
||||
@@ -18,7 +20,7 @@ export class TrustedDeviceUserDecryptionOptionResponse extends BaseResponse {
|
||||
hasManageResetPasswordPermission: boolean;
|
||||
isTdeOffboarding: boolean;
|
||||
encryptedPrivateKey: EncString;
|
||||
encryptedUserKey: EncString;
|
||||
encryptedUserKey: UnsignedSharedKey;
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
@@ -35,7 +37,7 @@ export class TrustedDeviceUserDecryptionOptionResponse extends BaseResponse {
|
||||
this.encryptedPrivateKey = new EncString(this.getResponseProperty("EncryptedPrivateKey"));
|
||||
}
|
||||
if (response.EncryptedUserKey) {
|
||||
this.encryptedUserKey = new EncString(this.getResponseProperty("EncryptedUserKey"));
|
||||
this.encryptedUserKey = this.getResponseProperty("EncryptedUserKey");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { UnsignedSharedKey } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { EncString } from "../../../../key-management/crypto/models/enc-string";
|
||||
import { BaseResponse } from "../../../../models/response/base.response";
|
||||
|
||||
@@ -10,7 +12,7 @@ export interface IWebAuthnPrfDecryptionOptionServerResponse {
|
||||
|
||||
export class WebAuthnPrfDecryptionOptionResponse extends BaseResponse {
|
||||
encryptedPrivateKey: EncString;
|
||||
encryptedUserKey: EncString;
|
||||
encryptedUserKey: UnsignedSharedKey;
|
||||
|
||||
constructor(response: IWebAuthnPrfDecryptionOptionServerResponse) {
|
||||
super(response);
|
||||
@@ -18,7 +20,7 @@ export class WebAuthnPrfDecryptionOptionResponse extends BaseResponse {
|
||||
this.encryptedPrivateKey = new EncString(this.getResponseProperty("EncryptedPrivateKey"));
|
||||
}
|
||||
if (response.EncryptedUserKey) {
|
||||
this.encryptedUserKey = new EncString(this.getResponseProperty("EncryptedUserKey"));
|
||||
this.encryptedUserKey = this.getResponseProperty("EncryptedUserKey") as UnsignedSharedKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ export class PasswordResetEnrollmentServiceImplementation
|
||||
const encryptedKey = await this.encryptService.encapsulateKeyUnsigned(userKey, orgPublicKey);
|
||||
|
||||
const resetRequest = new OrganizationUserResetPasswordEnrollmentRequest();
|
||||
resetRequest.resetPasswordKey = encryptedKey.encryptedString;
|
||||
resetRequest.resetPasswordKey = encryptedKey;
|
||||
|
||||
await this.organizationUserApiService.putOrganizationUserResetPasswordEnrollment(
|
||||
organizationId,
|
||||
|
||||
@@ -16,6 +16,7 @@ import { newGuid } from "@bitwarden/guid";
|
||||
// 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 { KeyService } from "@bitwarden/key-management";
|
||||
import { UnsignedSharedKey } from "@bitwarden/sdk-internal";
|
||||
import { UserId } from "@bitwarden/user-core";
|
||||
|
||||
import { OrganizationKeysRequest } from "../../admin-console/models/request/organization-keys.request";
|
||||
@@ -80,7 +81,7 @@ describe("OrganizationBillingService", () => {
|
||||
} as OrganizationResponse;
|
||||
|
||||
organizationApiService.create.mockResolvedValue(organizationResponse);
|
||||
keyService.makeOrgKey.mockResolvedValue([new EncString("encrypted-key"), {} as OrgKey]);
|
||||
keyService.makeOrgKey.mockResolvedValue(["encrypted-key" as UnsignedSharedKey, {} as OrgKey]);
|
||||
keyService.makeKeyPair.mockResolvedValue(["key", new EncString("encrypted-key")]);
|
||||
encryptService.encryptString.mockResolvedValue(new EncString("collection-encrypted"));
|
||||
|
||||
@@ -104,7 +105,7 @@ describe("OrganizationBillingService", () => {
|
||||
} as SubscriptionInformation;
|
||||
|
||||
organizationApiService.create.mockRejectedValue(new Error("Failed to create organization"));
|
||||
keyService.makeOrgKey.mockResolvedValue([new EncString("encrypted-key"), {} as OrgKey]);
|
||||
keyService.makeOrgKey.mockResolvedValue(["encrypted-key" as UnsignedSharedKey, {} as OrgKey]);
|
||||
keyService.makeKeyPair.mockResolvedValue(["key", new EncString("encrypted-key")]);
|
||||
encryptService.encryptString.mockResolvedValue(new EncString("collection-encrypted"));
|
||||
|
||||
@@ -164,7 +165,7 @@ describe("OrganizationBillingService", () => {
|
||||
} as OrganizationResponse;
|
||||
|
||||
organizationApiService.createWithoutPayment.mockResolvedValue(organizationResponse);
|
||||
keyService.makeOrgKey.mockResolvedValue([new EncString("encrypted-key"), {} as OrgKey]);
|
||||
keyService.makeOrgKey.mockResolvedValue(["encrypted-key" as UnsignedSharedKey, {} as OrgKey]);
|
||||
keyService.makeKeyPair.mockResolvedValue(["key", new EncString("encrypted-key")]);
|
||||
encryptService.encryptString.mockResolvedValue(new EncString("collection-encrypted"));
|
||||
|
||||
@@ -186,7 +187,7 @@ describe("OrganizationBillingService", () => {
|
||||
} as SubscriptionInformation;
|
||||
|
||||
organizationApiService.createWithoutPayment.mockRejectedValue(new Error("Creation failed"));
|
||||
keyService.makeOrgKey.mockResolvedValue([new EncString("encrypted-key"), {} as OrgKey]);
|
||||
keyService.makeOrgKey.mockResolvedValue(["encrypted-key" as UnsignedSharedKey, {} as OrgKey]);
|
||||
keyService.makeKeyPair.mockResolvedValue(["key", new EncString("encrypted-key")]);
|
||||
encryptService.encryptString.mockResolvedValue(new EncString("collection-encrypted"));
|
||||
|
||||
@@ -224,7 +225,7 @@ describe("OrganizationBillingService", () => {
|
||||
} as OrganizationResponse;
|
||||
|
||||
organizationApiService.create.mockResolvedValue(organizationResponse);
|
||||
keyService.makeOrgKey.mockResolvedValue([new EncString("encrypted-key"), {} as OrgKey]);
|
||||
keyService.makeOrgKey.mockResolvedValue(["encrypted-key" as UnsignedSharedKey, {} as OrgKey]);
|
||||
keyService.makeKeyPair.mockResolvedValue(["key", new EncString("encrypted-key")]);
|
||||
encryptService.encryptString.mockResolvedValue(new EncString("collection-encrypted"));
|
||||
|
||||
@@ -258,7 +259,7 @@ describe("OrganizationBillingService", () => {
|
||||
} as SubscriptionInformation;
|
||||
|
||||
organizationApiService.create.mockRejectedValue(new Error("Failed to create organization"));
|
||||
keyService.makeOrgKey.mockResolvedValue([new EncString("encrypted-key"), {} as OrgKey]);
|
||||
keyService.makeOrgKey.mockResolvedValue(["encrypted-key" as UnsignedSharedKey, {} as OrgKey]);
|
||||
keyService.makeKeyPair.mockResolvedValue(["key", new EncString("encrypted-key")]);
|
||||
encryptService.encryptString.mockResolvedValue(new EncString("collection-encrypted"));
|
||||
// Act & Assert
|
||||
@@ -271,7 +272,7 @@ describe("OrganizationBillingService", () => {
|
||||
describe("organization key creation methods", () => {
|
||||
const organizationKeys = {
|
||||
orgKey: new SymmetricCryptoKey(new Uint8Array(64)) as OrgKey,
|
||||
publicKeyEncapsulatedOrgKey: new EncString("encryptedOrgKey"),
|
||||
publicKeyEncapsulatedOrgKey: "encryptedOrgKey" as UnsignedSharedKey,
|
||||
publicKey: "public-key",
|
||||
encryptedPrivateKey: new EncString("encryptedPrivateKey"),
|
||||
};
|
||||
@@ -298,7 +299,7 @@ describe("OrganizationBillingService", () => {
|
||||
billingEmail: "test@example.com",
|
||||
initiationPath: "Registration form",
|
||||
planType: 0,
|
||||
key: organizationKeys.publicKeyEncapsulatedOrgKey.encryptedString,
|
||||
key: organizationKeys.publicKeyEncapsulatedOrgKey,
|
||||
keys: new OrganizationKeysRequest(
|
||||
organizationKeys.publicKey,
|
||||
organizationKeys.encryptedPrivateKey.encryptedString!,
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @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 { KeyService } from "@bitwarden/key-management";
|
||||
import { UnsignedSharedKey } from "@bitwarden/sdk-internal";
|
||||
import { UserId } from "@bitwarden/user-core";
|
||||
|
||||
import { ApiService } from "../../abstractions/api.service";
|
||||
@@ -27,7 +29,7 @@ import { PlanType } from "../enums";
|
||||
import { OrganizationNoPaymentMethodCreateRequest } from "../models/request/organization-no-payment-method-create-request";
|
||||
|
||||
interface OrganizationKeys {
|
||||
encryptedKey: EncString;
|
||||
encryptedKey: UnsignedSharedKey;
|
||||
publicKey: string;
|
||||
encryptedPrivateKey: EncString;
|
||||
encryptedCollectionName: EncString;
|
||||
@@ -158,7 +160,7 @@ export class OrganizationBillingService implements OrganizationBillingServiceAbs
|
||||
request: OrganizationCreateRequest | OrganizationNoPaymentMethodCreateRequest,
|
||||
keys: OrganizationKeys,
|
||||
): void {
|
||||
request.key = keys.encryptedKey.encryptedString;
|
||||
request.key = keys.encryptedKey;
|
||||
request.keys = new OrganizationKeysRequest(
|
||||
keys.publicKey,
|
||||
keys.encryptedPrivateKey.encryptedString,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { UnsignedSharedKey } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { EncArrayBuffer } from "../../../platform/models/domain/enc-array-buffer";
|
||||
import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key";
|
||||
@@ -143,7 +144,7 @@ export abstract class EncryptService {
|
||||
abstract encapsulateKeyUnsigned(
|
||||
sharedKey: SymmetricCryptoKey,
|
||||
encapsulationKey: Uint8Array,
|
||||
): Promise<EncString>;
|
||||
): Promise<UnsignedSharedKey>;
|
||||
/**
|
||||
* Decapsulates a shared symmetric key with an asymmetric private key
|
||||
* Note: This does not establish sender authenticity
|
||||
@@ -154,7 +155,7 @@ export abstract class EncryptService {
|
||||
* @throws Error if decapsulation fails
|
||||
*/
|
||||
abstract decapsulateKeyUnsigned(
|
||||
encryptedSharedKey: EncString,
|
||||
encryptedSharedKey: UnsignedSharedKey,
|
||||
decapsulationKey: Uint8Array,
|
||||
): Promise<SymmetricCryptoKey>;
|
||||
|
||||
|
||||
@@ -101,15 +101,6 @@ export class EncString {
|
||||
this.iv = encPieces[0];
|
||||
this.data = encPieces[1];
|
||||
break;
|
||||
case EncryptionType.Rsa2048_OaepSha256_B64:
|
||||
case EncryptionType.Rsa2048_OaepSha1_B64:
|
||||
this.data = encPieces[0];
|
||||
break;
|
||||
case EncryptionType.Rsa2048_OaepSha256_HmacSha256_B64:
|
||||
case EncryptionType.Rsa2048_OaepSha1_HmacSha256_B64:
|
||||
this.data = encPieces[0];
|
||||
this.mac = encPieces[1];
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { EncryptionType } from "@bitwarden/common/platform/enums";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { EncArrayBuffer } from "@bitwarden/common/platform/models/domain/enc-array-buffer";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import { PureCrypto } from "@bitwarden/sdk-internal";
|
||||
import { PureCrypto, UnsignedSharedKey } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { EncryptService } from "../abstractions/encrypt.service";
|
||||
|
||||
@@ -215,7 +215,7 @@ export class EncryptServiceImplementation implements EncryptService {
|
||||
async encapsulateKeyUnsigned(
|
||||
sharedKey: SymmetricCryptoKey,
|
||||
encapsulationKey: Uint8Array,
|
||||
): Promise<EncString> {
|
||||
): Promise<UnsignedSharedKey> {
|
||||
if (sharedKey == null) {
|
||||
throw new Error("No sharedKey provided for encapsulation");
|
||||
}
|
||||
@@ -223,13 +223,14 @@ export class EncryptServiceImplementation implements EncryptService {
|
||||
throw new Error("No encapsulationKey provided for encapsulation");
|
||||
}
|
||||
await SdkLoadService.Ready;
|
||||
return new EncString(
|
||||
PureCrypto.encapsulate_key_unsigned(sharedKey.toEncoded(), encapsulationKey),
|
||||
);
|
||||
return PureCrypto.encapsulate_key_unsigned(
|
||||
sharedKey.toEncoded(),
|
||||
encapsulationKey,
|
||||
) as UnsignedSharedKey;
|
||||
}
|
||||
|
||||
async decapsulateKeyUnsigned(
|
||||
encryptedSharedKey: EncString,
|
||||
encryptedSharedKey: UnsignedSharedKey,
|
||||
decapsulationKey: Uint8Array,
|
||||
): Promise<SymmetricCryptoKey> {
|
||||
if (encryptedSharedKey == null) {
|
||||
@@ -240,10 +241,7 @@ export class EncryptServiceImplementation implements EncryptService {
|
||||
}
|
||||
|
||||
await SdkLoadService.Ready;
|
||||
const keyBytes = PureCrypto.decapsulate_key_unsigned(
|
||||
encryptedSharedKey.encryptedString,
|
||||
decapsulationKey,
|
||||
);
|
||||
const keyBytes = PureCrypto.decapsulate_key_unsigned(encryptedSharedKey, decapsulationKey);
|
||||
return new SymmetricCryptoKey(keyBytes);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { EncryptionType } from "@bitwarden/common/platform/enums";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { EncArrayBuffer } from "@bitwarden/common/platform/models/domain/enc-array-buffer";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import { PureCrypto } from "@bitwarden/sdk-internal";
|
||||
import { PureCrypto, UnsignedSharedKey } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { makeStaticByteArray } from "../../../../spec";
|
||||
|
||||
@@ -357,7 +357,7 @@ describe("EncryptService", () => {
|
||||
|
||||
it("encrypts data with provided key", async () => {
|
||||
const actual = await encryptService.encapsulateKeyUnsigned(testKey, publicKey);
|
||||
expect(actual).toEqual(new EncString("encapsulated_key_unsigned"));
|
||||
expect(actual).toEqual("encapsulated_key_unsigned");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -369,13 +369,16 @@ describe("EncryptService", () => {
|
||||
});
|
||||
|
||||
it("throws if no private key is provided", () => {
|
||||
return expect(encryptService.decapsulateKeyUnsigned(encString, null)).rejects.toThrow(
|
||||
"No decapsulationKey provided for decapsulation",
|
||||
);
|
||||
const unsignedSharedKey = encString.encryptedString as unknown as UnsignedSharedKey;
|
||||
return expect(
|
||||
encryptService.decapsulateKeyUnsigned(unsignedSharedKey, null),
|
||||
).rejects.toThrow("No decapsulationKey provided for decapsulation");
|
||||
});
|
||||
|
||||
it("decrypts data with provided key", async () => {
|
||||
const actual = await encryptService.decapsulateKeyUnsigned(makeEncString(data), privateKey);
|
||||
const unsignedSharedKey = makeEncString(data)
|
||||
.encryptedString as unknown as UnsignedSharedKey;
|
||||
const actual = await encryptService.decapsulateKeyUnsigned(unsignedSharedKey, privateKey);
|
||||
expect(actual.toEncoded()).toEqualBuffer(new Uint8Array(64));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { OtherDeviceKeysUpdateRequest } from "@bitwarden/common/auth/models/request/update-devices-trust.request";
|
||||
import { UnsignedSharedKey } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { DeviceResponse } from "../../../auth/abstractions/devices/responses/device.response";
|
||||
import { UserId } from "../../../types/guid";
|
||||
@@ -42,7 +43,7 @@ export abstract class DeviceTrustServiceAbstraction {
|
||||
abstract decryptUserKeyWithDeviceKey(
|
||||
userId: UserId,
|
||||
encryptedDevicePrivateKey: EncString,
|
||||
encryptedUserKey: EncString,
|
||||
encryptedUserKey: UnsignedSharedKey,
|
||||
deviceKey: DeviceKey,
|
||||
): Promise<UserKey | null>;
|
||||
abstract rotateDevicesTrust(
|
||||
|
||||
@@ -8,6 +8,7 @@ import { UserDecryptionOptionsServiceAbstraction } from "@bitwarden/auth/common"
|
||||
// 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 { KeyService } from "@bitwarden/key-management";
|
||||
import { UnsignedSharedKey } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { AccountService } from "../../../auth/abstractions/account.service";
|
||||
import { DeviceResponse } from "../../../auth/abstractions/devices/responses/device.response";
|
||||
@@ -188,7 +189,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction {
|
||||
const deviceIdentifier = await this.appIdService.getAppId();
|
||||
const deviceResponse = await this.devicesApiService.updateTrustedDeviceKeys(
|
||||
deviceIdentifier,
|
||||
devicePublicKeyEncryptedUserKey.encryptedString,
|
||||
devicePublicKeyEncryptedUserKey,
|
||||
userKeyEncryptedDevicePublicKey.encryptedString,
|
||||
deviceKeyEncryptedDevicePrivateKey.encryptedString,
|
||||
);
|
||||
@@ -250,7 +251,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction {
|
||||
|
||||
const request = new OtherDeviceKeysUpdateRequest();
|
||||
request.encryptedPublicKey = newRotateableKeySet.encryptedPublicKey.encryptedString;
|
||||
request.encryptedUserKey = newRotateableKeySet.encapsulatedDownstreamKey.encryptedString;
|
||||
request.encryptedUserKey = newRotateableKeySet.encapsulatedDownstreamKey;
|
||||
request.deviceId = device.id;
|
||||
return request;
|
||||
})
|
||||
@@ -313,7 +314,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction {
|
||||
);
|
||||
|
||||
const currentDeviceUpdateRequest = new DeviceKeysUpdateRequest();
|
||||
currentDeviceUpdateRequest.encryptedUserKey = encryptedNewUserKey.encryptedString;
|
||||
currentDeviceUpdateRequest.encryptedUserKey = encryptedNewUserKey;
|
||||
currentDeviceUpdateRequest.encryptedPublicKey = encryptedDevicePublicKey.encryptedString;
|
||||
|
||||
// TODO: For device management, allow this method to take an array of device ids that can be looped over and individually rotated
|
||||
@@ -387,7 +388,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction {
|
||||
async decryptUserKeyWithDeviceKey(
|
||||
userId: UserId,
|
||||
encryptedDevicePrivateKey: EncString,
|
||||
encryptedUserKey: EncString,
|
||||
encryptedUserKey: UnsignedSharedKey,
|
||||
deviceKey: DeviceKey,
|
||||
): Promise<UserKey | null> {
|
||||
if (!userId) {
|
||||
@@ -418,7 +419,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction {
|
||||
|
||||
// Attempt to decrypt encryptedUserDataKey with devicePrivateKey
|
||||
const userKey = await this.encryptService.decapsulateKeyUnsigned(
|
||||
new EncString(encryptedUserKey.encryptedString),
|
||||
encryptedUserKey,
|
||||
devicePrivateKey,
|
||||
);
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ import { KeyGenerationService } from "../../crypto";
|
||||
import { CryptoFunctionService } from "../../crypto/abstractions/crypto-function.service";
|
||||
import { EncryptService } from "../../crypto/abstractions/encrypt.service";
|
||||
import { EncString } from "../../crypto/models/enc-string";
|
||||
import { UnsignedSharedKey } from "@bitwarden/sdk-internal";
|
||||
|
||||
import {
|
||||
SHOULD_TRUST_DEVICE,
|
||||
@@ -350,7 +351,7 @@ describe("deviceTrustService", () => {
|
||||
|
||||
const deviceRsaKeyLength = 2048;
|
||||
let mockDeviceRsaKeyPair: [Uint8Array, Uint8Array];
|
||||
let mockDevicePublicKeyEncryptedUserKey: EncString;
|
||||
let mockDevicePublicKeyEncryptedUserKey: UnsignedSharedKey;
|
||||
let mockUserKeyEncryptedDevicePublicKey: EncString;
|
||||
let mockDeviceKeyEncryptedDevicePrivateKey: EncString;
|
||||
|
||||
@@ -386,10 +387,8 @@ describe("deviceTrustService", () => {
|
||||
new Uint8Array(deviceRsaKeyLength),
|
||||
];
|
||||
|
||||
mockDevicePublicKeyEncryptedUserKey = new EncString(
|
||||
EncryptionType.Rsa2048_OaepSha1_B64,
|
||||
"mockDevicePublicKeyEncryptedUserKey",
|
||||
);
|
||||
mockDevicePublicKeyEncryptedUserKey =
|
||||
"4.mockDevicePublicKeyEncryptedUserKey" as UnsignedSharedKey;
|
||||
|
||||
mockUserKeyEncryptedDevicePublicKey = new EncString(
|
||||
EncryptionType.AesCbc256_HmacSha256_B64,
|
||||
@@ -460,7 +459,7 @@ describe("deviceTrustService", () => {
|
||||
expect(devicesApiServiceUpdateTrustedDeviceKeysSpy).toHaveBeenCalledTimes(1);
|
||||
expect(devicesApiServiceUpdateTrustedDeviceKeysSpy).toHaveBeenCalledWith(
|
||||
mockDeviceId,
|
||||
mockDevicePublicKeyEncryptedUserKey.encryptedString,
|
||||
mockDevicePublicKeyEncryptedUserKey,
|
||||
mockUserKeyEncryptedDevicePublicKey.encryptedString,
|
||||
mockDeviceKeyEncryptedDevicePrivateKey.encryptedString,
|
||||
);
|
||||
@@ -542,7 +541,7 @@ describe("deviceTrustService", () => {
|
||||
describe("decryptUserKeyWithDeviceKey", () => {
|
||||
let mockDeviceKey: DeviceKey;
|
||||
let mockEncryptedDevicePrivateKey: EncString;
|
||||
let mockEncryptedUserKey: EncString;
|
||||
let mockEncryptedUserKey: UnsignedSharedKey;
|
||||
let mockUserKey: UserKey;
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -557,10 +556,7 @@ describe("deviceTrustService", () => {
|
||||
"mockEncryptedDevicePrivateKey",
|
||||
);
|
||||
|
||||
mockEncryptedUserKey = new EncString(
|
||||
EncryptionType.AesCbc256_HmacSha256_B64,
|
||||
"mockEncryptedUserKey",
|
||||
);
|
||||
mockEncryptedUserKey = "2.mockEncryptedUserKey" as UnsignedSharedKey;
|
||||
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
@@ -698,7 +694,7 @@ describe("deviceTrustService", () => {
|
||||
encryptService.decryptBytes.mockResolvedValue(null);
|
||||
encryptService.encryptString.mockResolvedValue(new EncString("test_encrypted_data"));
|
||||
encryptService.encapsulateKeyUnsigned.mockResolvedValue(
|
||||
new EncString("test_encrypted_data"),
|
||||
"test_encrypted_data" as UnsignedSharedKey,
|
||||
);
|
||||
|
||||
const protectedDeviceResponse = new ProtectedDeviceResponse({
|
||||
@@ -708,7 +704,7 @@ describe("deviceTrustService", () => {
|
||||
name: "Firefox",
|
||||
type: DeviceType.FirefoxBrowser,
|
||||
encryptedPublicKey: "",
|
||||
encryptedUserKey: "",
|
||||
encryptedUserKey: "" as UnsignedSharedKey,
|
||||
});
|
||||
devicesApiService.getDeviceKeys.mockResolvedValue(protectedDeviceResponse);
|
||||
|
||||
@@ -746,7 +742,7 @@ describe("deviceTrustService", () => {
|
||||
encryptService.unwrapEncapsulationKey.mockResolvedValue(new Uint8Array(64));
|
||||
encryptService.wrapEncapsulationKey.mockResolvedValue(new EncString("test_encrypted_data"));
|
||||
encryptService.encapsulateKeyUnsigned.mockResolvedValue(
|
||||
new EncString("test_encrypted_data"),
|
||||
"test_encrypted_data" as UnsignedSharedKey,
|
||||
);
|
||||
|
||||
const protectedDeviceResponse = new ProtectedDeviceResponse({
|
||||
@@ -756,7 +752,7 @@ describe("deviceTrustService", () => {
|
||||
name: "Firefox",
|
||||
type: DeviceType.FirefoxBrowser,
|
||||
encryptedPublicKey: "",
|
||||
encryptedUserKey: "",
|
||||
encryptedUserKey: "" as UnsignedSharedKey,
|
||||
});
|
||||
devicesApiService.getDeviceKeys.mockResolvedValue(protectedDeviceResponse);
|
||||
const fakeOldUserKeyData = new Uint8Array(64);
|
||||
@@ -823,7 +819,7 @@ describe("deviceTrustService", () => {
|
||||
|
||||
it("rotates current device keys and calls api service when the current device is trusted", async () => {
|
||||
const currentEncryptedPublicKey = new EncString("2.cHVibGlj|cHVibGlj|cHVibGlj");
|
||||
const currentEncryptedUserKey = new EncString("4.dXNlcg==");
|
||||
const currentEncryptedUserKey = "4.dXNlcg==" as UnsignedSharedKey;
|
||||
|
||||
const fakeOldUserKeyData = new Uint8Array(new Uint8Array(64));
|
||||
// Fill the first byte with something identifiable
|
||||
@@ -849,7 +845,7 @@ describe("deviceTrustService", () => {
|
||||
name: "Firefox",
|
||||
type: DeviceType.FirefoxBrowser,
|
||||
encryptedPublicKey: currentEncryptedPublicKey.encryptedString,
|
||||
encryptedUserKey: currentEncryptedUserKey.encryptedString,
|
||||
encryptedUserKey: currentEncryptedUserKey,
|
||||
}),
|
||||
);
|
||||
});
|
||||
@@ -871,7 +867,7 @@ describe("deviceTrustService", () => {
|
||||
expect(new Uint8Array(data.toEncoded())[0]).toBe(FakeNewUserKeyMarker); // New key should have the first byte be '1';
|
||||
|
||||
expect(new Uint8Array(publicKey)[0]).toBe(FakeDecryptedPublicKeyMarker);
|
||||
return Promise.resolve(new EncString("4.ZW5jcnlwdGVkdXNlcg=="));
|
||||
return Promise.resolve("4.ZW5jcnlwdGVkdXNlcg==" as UnsignedSharedKey);
|
||||
});
|
||||
|
||||
// Mock the reencryption of the device public key with the new user key
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { UnsignedSharedKey } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key";
|
||||
import { PrfKey } from "../../../types/key";
|
||||
import { EncString } from "../../crypto/models/enc-string";
|
||||
@@ -21,7 +23,7 @@ export class RotateableKeySet<UpstreamKey extends SymmetricCryptoKey = Symmetric
|
||||
|
||||
constructor(
|
||||
/** `DownstreamKey` protected by publicKey */
|
||||
readonly encapsulatedDownstreamKey: EncString,
|
||||
readonly encapsulatedDownstreamKey: UnsignedSharedKey,
|
||||
|
||||
/** DownstreamKey encrypted PublicKey */
|
||||
readonly encryptedPublicKey: EncString,
|
||||
|
||||
@@ -8,6 +8,7 @@ import { Utils } from "../../../platform/misc/utils";
|
||||
import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key";
|
||||
import { EncryptService } from "../../crypto/abstractions/encrypt.service";
|
||||
import { EncString } from "../../crypto/models/enc-string";
|
||||
import { UnsignedSharedKey } from "@bitwarden/sdk-internal";
|
||||
import { RotateableKeySet } from "../models/rotateable-key-set";
|
||||
|
||||
import { DefaultRotateableKeySetService } from "./default-rotateable-key-set.service";
|
||||
@@ -47,7 +48,7 @@ describe("DefaultRotateableKeySetService", () => {
|
||||
it("should create a new key set", async () => {
|
||||
const externalKey = createSymmetricKey();
|
||||
const userKey = createSymmetricKey();
|
||||
const encryptedUserKey = new EncString("encryptedUserKey");
|
||||
const encryptedUserKey = "encryptedUserKey" as UnsignedSharedKey;
|
||||
const encryptedPublicKey = new EncString("encryptedPublicKey");
|
||||
const encryptedPrivateKey = new EncString("encryptedPrivateKey");
|
||||
keyService.makeKeyPair.mockResolvedValue(["publicKey", encryptedPrivateKey]);
|
||||
@@ -73,7 +74,7 @@ describe("DefaultRotateableKeySetService", () => {
|
||||
|
||||
describe("rotateKeySet", () => {
|
||||
const keySet = new RotateableKeySet(
|
||||
new EncString("encUserKey"),
|
||||
"encUserKey" as UnsignedSharedKey,
|
||||
new EncString("encPublicKey"),
|
||||
new EncString("encPrivateKey"),
|
||||
);
|
||||
@@ -149,7 +150,7 @@ describe("DefaultRotateableKeySetService", () => {
|
||||
const newDownstreamKey = new SymmetricCryptoKey(new Uint8Array(64));
|
||||
const publicKey = Utils.fromB64ToArray("decryptedPublicKey");
|
||||
const newEncryptedPublicKey = new EncString("newEncPublicKey");
|
||||
const newEncryptedRotateableKey = new EncString("newEncUserKey");
|
||||
const newEncryptedRotateableKey = "newEncUserKey" as UnsignedSharedKey;
|
||||
|
||||
encryptService.unwrapEncapsulationKey.mockResolvedValue(publicKey);
|
||||
encryptService.wrapEncapsulationKey.mockResolvedValue(newEncryptedPublicKey);
|
||||
|
||||
@@ -67,13 +67,13 @@ export class DefaultRotateableKeySetService implements RotateableKeySetService {
|
||||
publicKey,
|
||||
newDownstreamKey,
|
||||
);
|
||||
const newEncryptedRotateableKey = await this.encryptService.encapsulateKeyUnsigned(
|
||||
const encapsulatedDownstreamKey = await this.encryptService.encapsulateKeyUnsigned(
|
||||
newDownstreamKey,
|
||||
publicKey,
|
||||
);
|
||||
|
||||
const newRotateableKeySet = new RotateableKeySet<UpstreamKey>(
|
||||
newEncryptedRotateableKey,
|
||||
encapsulatedDownstreamKey,
|
||||
newEncryptedPublicKey,
|
||||
keySet.encryptedPrivateKey,
|
||||
);
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { EncryptedString } from "../../../key-management/crypto/models/enc-string";
|
||||
import { UnsignedSharedKey } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { ProviderId } from "../../../types/guid";
|
||||
import { CRYPTO_DISK, UserKeyDefinition } from "../../state";
|
||||
|
||||
export const USER_ENCRYPTED_PROVIDER_KEYS = UserKeyDefinition.record<EncryptedString, ProviderId>(
|
||||
export const USER_ENCRYPTED_PROVIDER_KEYS = UserKeyDefinition.record<UnsignedSharedKey, ProviderId>(
|
||||
CRYPTO_DISK,
|
||||
"providerKeys",
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user