mirror of
https://github.com/bitwarden/browser
synced 2026-02-13 23:13:36 +00:00
Refactor symmetric encrypt interface
This commit is contained in:
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"cSpell.words": ["Csprng", "decryptable", "Popout", "Reprompt", "takeuntil"],
|
||||
"cSpell.words": ["Csprng", "Decapsulation", "decryptable", "Popout", "Reprompt", "takeuntil"],
|
||||
"search.exclude": {
|
||||
"**/locales/[^e]*/messages.json": true,
|
||||
"**/locales/*[^n]/messages.json": true,
|
||||
|
||||
@@ -350,7 +350,7 @@ export class NativeMessagingBackground {
|
||||
await this.secureCommunication();
|
||||
}
|
||||
|
||||
return await this.encryptService.encrypt(
|
||||
return await this.encryptService.encryptString(
|
||||
JSON.stringify(message),
|
||||
this.secureChannel!.sharedSecret!,
|
||||
);
|
||||
|
||||
@@ -127,7 +127,7 @@ describe("LocalBackedSessionStorage", () => {
|
||||
describe("save", () => {
|
||||
const encString = makeEncString("encrypted");
|
||||
beforeEach(() => {
|
||||
encryptService.encrypt.mockResolvedValue(encString);
|
||||
encryptService.encryptString.mockResolvedValue(encString);
|
||||
});
|
||||
|
||||
it("logs a warning when saving the same value twice and in a dev environment", async () => {
|
||||
@@ -157,7 +157,10 @@ describe("LocalBackedSessionStorage", () => {
|
||||
|
||||
it("encrypts and saves the value to local storage", async () => {
|
||||
await sut.save("test", "value");
|
||||
expect(encryptService.encrypt).toHaveBeenCalledWith(JSON.stringify("value"), sessionKey);
|
||||
expect(encryptService.encryptString).toHaveBeenCalledWith(
|
||||
JSON.stringify("value"),
|
||||
sessionKey,
|
||||
);
|
||||
expect(localStorage.internalStore["session_test"]).toEqual(encString.encryptedString);
|
||||
});
|
||||
|
||||
|
||||
@@ -140,7 +140,10 @@ export class LocalBackedSessionStorageService
|
||||
}
|
||||
|
||||
const valueJson = JSON.stringify(value);
|
||||
const encValue = await this.encryptService.encrypt(valueJson, await this.sessionKey.get());
|
||||
const encValue = await this.encryptService.encryptString(
|
||||
valueJson,
|
||||
await this.sessionKey.get(),
|
||||
);
|
||||
await this.localStorage.save(this.sessionStorageKey(key), encValue.encryptedString);
|
||||
}
|
||||
|
||||
|
||||
@@ -204,7 +204,7 @@ export class EditCommand {
|
||||
(u) => new SelectionReadOnlyRequest(u.id, u.readOnly, u.hidePasswords, u.manage),
|
||||
);
|
||||
const request = new CollectionRequest();
|
||||
request.name = (await this.encryptService.encrypt(req.name, orgKey)).encryptedString;
|
||||
request.name = (await this.encryptService.encryptString(req.name, orgKey)).encryptedString;
|
||||
request.externalId = req.externalId;
|
||||
request.groups = groups;
|
||||
request.users = users;
|
||||
|
||||
@@ -61,7 +61,7 @@ export class NodeEnvSecureStorageService implements AbstractStorageService {
|
||||
if (sessionKey == null) {
|
||||
throw new Error("No session key available.");
|
||||
}
|
||||
const encValue = await this.encryptService.encryptToBytes(
|
||||
const encValue = await this.encryptService.encryptFileData(
|
||||
Utils.fromB64ToArray(plainValue),
|
||||
sessionKey,
|
||||
);
|
||||
|
||||
@@ -227,7 +227,7 @@ export class CreateCommand {
|
||||
(u) => new SelectionReadOnlyRequest(u.id, u.readOnly, u.hidePasswords, u.manage),
|
||||
);
|
||||
const request = new CollectionRequest();
|
||||
request.name = (await this.encryptService.encrypt(req.name, orgKey)).encryptedString;
|
||||
request.name = (await this.encryptService.encryptString(req.name, orgKey)).encryptedString;
|
||||
request.externalId = req.externalId;
|
||||
request.groups = groups;
|
||||
request.users = users;
|
||||
|
||||
@@ -110,7 +110,7 @@ export class ElectronKeyService extends DefaultKeyService {
|
||||
// Set a key half if it doesn't exist
|
||||
const keyBytes = await this.cryptoFunctionService.randomBytes(32);
|
||||
clientKeyHalf = Utils.fromBufferToUtf8(keyBytes) as CsprngString;
|
||||
const encKey = await this.encryptService.encrypt(clientKeyHalf, userKey);
|
||||
const encKey = await this.encryptService.encryptString(clientKeyHalf, userKey);
|
||||
await this.biometricStateService.setEncryptedClientKeyHalf(encKey, userId);
|
||||
}
|
||||
|
||||
|
||||
@@ -350,7 +350,7 @@ export class BiometricMessageHandlerService {
|
||||
throw new Error("Session secret is missing");
|
||||
}
|
||||
|
||||
const encrypted = await this.encryptService.encrypt(
|
||||
const encrypted = await this.encryptService.encryptString(
|
||||
JSON.stringify(message),
|
||||
SymmetricCryptoKey.fromString(sessionSecret),
|
||||
);
|
||||
|
||||
@@ -168,7 +168,7 @@ export class DuckDuckGoMessageHandlerService {
|
||||
payload: DecryptedCommandData,
|
||||
key: SymmetricCryptoKey,
|
||||
): Promise<EncString> {
|
||||
return await this.encryptService.encrypt(JSON.stringify(payload), key);
|
||||
return await this.encryptService.encryptString(JSON.stringify(payload), key);
|
||||
}
|
||||
|
||||
private async decryptPayload(message: EncryptedMessage): Promise<DecryptedCommandData> {
|
||||
|
||||
@@ -36,7 +36,7 @@ describe("RotateableKeySetService", () => {
|
||||
keyService.makeKeyPair.mockResolvedValue(["publicKey", encryptedPrivateKey as any]);
|
||||
keyService.getUserKey.mockResolvedValue({ key: userKey.key } as any);
|
||||
encryptService.rsaEncrypt.mockResolvedValue(encryptedUserKey as any);
|
||||
encryptService.encrypt.mockResolvedValue(encryptedPublicKey as any);
|
||||
encryptService.wrapEncapsulationKey.mockResolvedValue(encryptedPublicKey as any);
|
||||
|
||||
const result = await service.createKeySet(externalKey as any);
|
||||
|
||||
|
||||
@@ -26,7 +26,10 @@ export class RotateableKeySetService {
|
||||
const userKey = await this.keyService.getUserKey();
|
||||
const rawPublicKey = Utils.fromB64ToArray(publicKey);
|
||||
const encryptedUserKey = await this.encryptService.rsaEncrypt(userKey.key, rawPublicKey);
|
||||
const encryptedPublicKey = await this.encryptService.encrypt(rawPublicKey, userKey);
|
||||
const encryptedPublicKey = await this.encryptService.wrapEncapsulationKey(
|
||||
rawPublicKey,
|
||||
userKey,
|
||||
);
|
||||
return new RotateableKeySet(encryptedUserKey, encryptedPublicKey, encryptedPrivateKey);
|
||||
}
|
||||
|
||||
@@ -59,7 +62,10 @@ export class RotateableKeySetService {
|
||||
if (publicKey == null) {
|
||||
throw new Error("failed to rotate key set: could not decrypt public key");
|
||||
}
|
||||
const newEncryptedPublicKey = await this.encryptService.encrypt(publicKey, newUserKey);
|
||||
const newEncryptedPublicKey = await this.encryptService.wrapEncapsulationKey(
|
||||
publicKey,
|
||||
newUserKey,
|
||||
);
|
||||
const newEncryptedUserKey = await this.encryptService.rsaEncrypt(newUserKey.key, publicKey);
|
||||
|
||||
const newRotateableKeySet = new RotateableKeySet<ExternalKey>(
|
||||
|
||||
@@ -81,7 +81,10 @@ describe("AcceptOrganizationInviteService", () => {
|
||||
"orgPublicKey",
|
||||
{ encryptedString: "string" } as EncString,
|
||||
]);
|
||||
encryptService.encrypt.mockResolvedValue({ encryptedString: "string" } as EncString);
|
||||
encryptService.wrapDecapsulationKey.mockResolvedValue({
|
||||
encryptedString: "string",
|
||||
} as EncString);
|
||||
encryptService.encryptString.mockResolvedValue({ encryptedString: "string" } as EncString);
|
||||
const invite = createOrgInvite({ initOrganization: true });
|
||||
|
||||
const result = await sut.validateAndAcceptInvite(invite);
|
||||
|
||||
@@ -141,7 +141,7 @@ export class AcceptOrganizationInviteService {
|
||||
|
||||
const [encryptedOrgKey, orgKey] = await this.keyService.makeOrgKey<OrgKey>();
|
||||
const [orgPublicKey, encryptedOrgPrivateKey] = await this.keyService.makeKeyPair(orgKey);
|
||||
const collection = await this.encryptService.encrypt(
|
||||
const collection = await this.encryptService.encryptString(
|
||||
this.i18nService.t("defaultCollection"),
|
||||
orgKey,
|
||||
);
|
||||
|
||||
@@ -614,7 +614,7 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy {
|
||||
if (this.createOrganization) {
|
||||
const orgKey = await this.keyService.makeOrgKey<OrgKey>();
|
||||
const key = orgKey[0].encryptedString;
|
||||
const collection = await this.encryptService.encrypt(
|
||||
const collection = await this.encryptService.encryptString(
|
||||
this.i18nService.t("defaultCollection"),
|
||||
orgKey[1],
|
||||
);
|
||||
@@ -804,7 +804,7 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy {
|
||||
);
|
||||
const providerKey = await this.keyService.getProviderKey(this.providerId);
|
||||
providerRequest.organizationCreateRequest.key = (
|
||||
await this.encryptService.encrypt(orgKey.key, providerKey)
|
||||
await this.encryptService.wrapSymmetricKey(orgKey, providerKey)
|
||||
).encryptedString;
|
||||
const orgId = (
|
||||
await this.apiService.postProviderCreateOrganization(this.providerId, providerRequest)
|
||||
|
||||
@@ -51,7 +51,7 @@ export class OrganizationSelfHostingLicenseUploaderComponent extends AbstractSel
|
||||
|
||||
const orgKey = await this.keyService.makeOrgKey<OrgKey>();
|
||||
const key = orgKey[0].encryptedString;
|
||||
const collection = await this.encryptService.encrypt(
|
||||
const collection = await this.encryptService.encryptString(
|
||||
this.i18nService.t("defaultCollection"),
|
||||
orgKey[1],
|
||||
);
|
||||
|
||||
@@ -119,7 +119,10 @@ describe("KeyRotationService", () => {
|
||||
mockKeyService.hashMasterKey.mockResolvedValue("mockMasterPasswordHash");
|
||||
mockConfigService.getFeatureFlag.mockResolvedValue(true);
|
||||
|
||||
mockEncryptService.encrypt.mockResolvedValue({
|
||||
mockEncryptService.wrapSymmetricKey.mockResolvedValue({
|
||||
encryptedString: "mockEncryptedData",
|
||||
} as any);
|
||||
mockEncryptService.wrapDecapsulationKey.mockResolvedValue({
|
||||
encryptedString: "mockEncryptedData",
|
||||
} as any);
|
||||
|
||||
|
||||
@@ -125,7 +125,9 @@ export class UserKeyRotationService {
|
||||
const { privateKey, publicKey } = keyPair;
|
||||
|
||||
const accountKeysRequest = new AccountKeysRequest(
|
||||
(await this.encryptService.encrypt(privateKey, newUnencryptedUserKey)).encryptedString!,
|
||||
(
|
||||
await this.encryptService.wrapDecapsulationKey(privateKey, newUnencryptedUserKey)
|
||||
).encryptedString!,
|
||||
Utils.fromBufferToB64(publicKey),
|
||||
);
|
||||
|
||||
@@ -357,6 +359,6 @@ export class UserKeyRotationService {
|
||||
if (privateKey == null) {
|
||||
throw new Error("No private key found for user key rotation");
|
||||
}
|
||||
return (await this.encryptService.encrypt(privateKey, newUserKey)).encryptedString;
|
||||
return (await this.encryptService.wrapDecapsulationKey(privateKey, newUserKey)).encryptedString;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ describe("CriticalAppsService", () => {
|
||||
{ id: "id2", organizationId: "org1", uri: "https://example.org" },
|
||||
] as PasswordHealthReportApplicationsResponse[];
|
||||
|
||||
encryptService.encrypt.mockResolvedValue(new EncString("encryptedUrlName"));
|
||||
encryptService.encryptString.mockResolvedValue(new EncString("encryptedUrlName"));
|
||||
criticalAppsApiService.saveCriticalApps.mockReturnValue(of(response));
|
||||
|
||||
// act
|
||||
@@ -67,7 +67,7 @@ describe("CriticalAppsService", () => {
|
||||
|
||||
// expectations
|
||||
expect(keyService.getOrgKey).toHaveBeenCalledWith("org1");
|
||||
expect(encryptService.encrypt).toHaveBeenCalledTimes(2);
|
||||
expect(encryptService.encryptString).toHaveBeenCalledTimes(2);
|
||||
expect(criticalAppsApiService.saveCriticalApps).toHaveBeenCalledWith(request);
|
||||
});
|
||||
|
||||
@@ -95,7 +95,7 @@ describe("CriticalAppsService", () => {
|
||||
{ id: "id1", organizationId: "org1", uri: "test" },
|
||||
] as PasswordHealthReportApplicationsResponse[];
|
||||
|
||||
encryptService.encrypt.mockResolvedValue(new EncString("encryptedUrlName"));
|
||||
encryptService.encryptString.mockResolvedValue(new EncString("encryptedUrlName"));
|
||||
criticalAppsApiService.saveCriticalApps.mockReturnValue(of(response));
|
||||
|
||||
// act
|
||||
@@ -103,7 +103,7 @@ describe("CriticalAppsService", () => {
|
||||
|
||||
// expectations
|
||||
expect(keyService.getOrgKey).toHaveBeenCalledWith("org1");
|
||||
expect(encryptService.encrypt).toHaveBeenCalledTimes(1);
|
||||
expect(encryptService.encryptString).toHaveBeenCalledTimes(1);
|
||||
expect(criticalAppsApiService.saveCriticalApps).toHaveBeenCalledWith(request);
|
||||
});
|
||||
|
||||
|
||||
@@ -164,7 +164,7 @@ export class CriticalAppsService {
|
||||
newEntries: string[],
|
||||
): Promise<PasswordHealthReportApplicationsRequest[]> {
|
||||
const criticalAppsPromises = newEntries.map(async (url) => {
|
||||
const encryptedUrlName = await this.encryptService.encrypt(url, key);
|
||||
const encryptedUrlName = await this.encryptService.encryptString(url, key);
|
||||
return {
|
||||
organizationId: orgId,
|
||||
url: encryptedUrlName?.encryptedString?.toString() ?? "",
|
||||
|
||||
@@ -36,7 +36,7 @@ export class WebProviderService {
|
||||
const orgKey = await this.keyService.getOrgKey(organizationId);
|
||||
const providerKey = await this.keyService.getProviderKey(providerId);
|
||||
|
||||
const encryptedOrgKey = await this.encryptService.encrypt(orgKey.key, providerKey);
|
||||
const encryptedOrgKey = await this.encryptService.wrapSymmetricKey(orgKey, providerKey);
|
||||
|
||||
const request = new ProviderAddOrganizationRequest();
|
||||
request.organizationId = organizationId;
|
||||
@@ -55,7 +55,7 @@ export class WebProviderService {
|
||||
),
|
||||
);
|
||||
const providerKey = await this.keyService.getProviderKey(providerId);
|
||||
const encryptedOrgKey = await this.encryptService.encrypt(orgKey.key, providerKey);
|
||||
const encryptedOrgKey = await this.encryptService.wrapSymmetricKey(orgKey, providerKey);
|
||||
await this.providerApiService.addOrganizationToProvider(providerId, {
|
||||
key: encryptedOrgKey.encryptedString,
|
||||
organizationId,
|
||||
@@ -74,15 +74,15 @@ export class WebProviderService {
|
||||
|
||||
const [publicKey, encryptedPrivateKey] = await this.keyService.makeKeyPair(organizationKey);
|
||||
|
||||
const encryptedCollectionName = await this.encryptService.encrypt(
|
||||
const encryptedCollectionName = await this.encryptService.encryptString(
|
||||
this.i18nService.t("defaultCollection"),
|
||||
organizationKey,
|
||||
);
|
||||
|
||||
const providerKey = await this.keyService.getProviderKey(providerId);
|
||||
|
||||
const encryptedProviderKey = await this.encryptService.encrypt(
|
||||
organizationKey.key,
|
||||
const encryptedProviderKey = await this.encryptService.wrapSymmetricKey(
|
||||
organizationKey,
|
||||
providerKey,
|
||||
);
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ export class ProjectService {
|
||||
): Promise<ProjectRequest> {
|
||||
const orgKey = await this.getOrganizationKey(organizationId);
|
||||
const request = new ProjectRequest();
|
||||
request.name = await this.encryptService.encrypt(projectView.name, orgKey);
|
||||
request.name = await this.encryptService.encryptString(projectView.name, orgKey);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ describe("SecretService", () => {
|
||||
|
||||
sut = new SecretService(keyService, apiService, encryptService, accessPolicyService);
|
||||
|
||||
encryptService.encrypt.mockResolvedValue({
|
||||
encryptService.encryptString.mockResolvedValue({
|
||||
encryptedString: "mockEncryptedString",
|
||||
} as EncString);
|
||||
encryptService.decryptToUtf8.mockResolvedValue(mockUnencryptedData);
|
||||
|
||||
@@ -166,9 +166,9 @@ export class SecretService {
|
||||
const orgKey = await this.getOrganizationKey(organizationId);
|
||||
const request = new SecretRequest();
|
||||
const [key, value, note] = await Promise.all([
|
||||
this.encryptService.encrypt(secretView.name, orgKey),
|
||||
this.encryptService.encrypt(secretView.value, orgKey),
|
||||
this.encryptService.encrypt(secretView.note, orgKey),
|
||||
this.encryptService.encryptString(secretView.name, orgKey),
|
||||
this.encryptService.encryptString(secretView.value, orgKey),
|
||||
this.encryptService.encryptString(secretView.note, orgKey),
|
||||
]);
|
||||
request.key = key.encryptedString;
|
||||
request.value = value.encryptedString;
|
||||
|
||||
@@ -102,12 +102,12 @@ export class AccessService {
|
||||
const organizationKey = await this.getOrganizationKey(organizationId);
|
||||
const accessTokenRequest = new AccessTokenRequest();
|
||||
const [name, encryptedPayload, key] = await Promise.all([
|
||||
await this.encryptService.encrypt(accessTokenView.name, organizationKey),
|
||||
await this.encryptService.encrypt(
|
||||
await this.encryptService.encryptString(accessTokenView.name, organizationKey),
|
||||
await this.encryptService.encryptString(
|
||||
JSON.stringify({ encryptionKey: organizationKey.keyB64 }),
|
||||
encryptionKey,
|
||||
),
|
||||
await this.encryptService.encrypt(encryptionKey.keyB64, organizationKey),
|
||||
await this.encryptService.encryptString(encryptionKey.keyB64, organizationKey),
|
||||
]);
|
||||
|
||||
accessTokenRequest.name = name;
|
||||
|
||||
@@ -130,7 +130,10 @@ export class ServiceAccountService {
|
||||
serviceAccountView: ServiceAccountView,
|
||||
) {
|
||||
const request = new ServiceAccountRequest();
|
||||
request.name = await this.encryptService.encrypt(serviceAccountView.name, organizationKey);
|
||||
request.name = await this.encryptService.encryptString(
|
||||
serviceAccountView.name,
|
||||
organizationKey,
|
||||
);
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ describe("SecretsManagerPortingApiService", () => {
|
||||
|
||||
sut = new SecretsManagerPortingApiService(apiService, encryptService, keyService);
|
||||
|
||||
encryptService.encrypt.mockResolvedValue(mockEncryptedString);
|
||||
encryptService.encryptString.mockResolvedValue(mockEncryptedString);
|
||||
encryptService.decryptToUtf8.mockResolvedValue(mockUnencryptedString);
|
||||
|
||||
const mockRandomBytes = new Uint8Array(64) as CsprngArray;
|
||||
|
||||
@@ -86,7 +86,7 @@ export class SecretsManagerPortingApiService {
|
||||
importData.projects.map(async (p: any) => {
|
||||
const project = new SecretsManagerImportedProjectRequest();
|
||||
project.id = p.id;
|
||||
project.name = await this.encryptService.encrypt(p.name, orgKey);
|
||||
project.name = await this.encryptService.encryptString(p.name, orgKey);
|
||||
return project;
|
||||
}),
|
||||
);
|
||||
@@ -96,9 +96,9 @@ export class SecretsManagerPortingApiService {
|
||||
const secret = new SecretsManagerImportedSecretRequest();
|
||||
|
||||
[secret.key, secret.value, secret.note] = await Promise.all([
|
||||
this.encryptService.encrypt(s.key, orgKey),
|
||||
this.encryptService.encrypt(s.value, orgKey),
|
||||
this.encryptService.encrypt(s.note, orgKey),
|
||||
this.encryptService.encryptString(s.key, orgKey),
|
||||
this.encryptService.encryptString(s.value, orgKey),
|
||||
this.encryptService.encryptString(s.note, orgKey),
|
||||
]);
|
||||
|
||||
secret.id = s.id;
|
||||
|
||||
@@ -146,7 +146,7 @@ export class DefaultCollectionAdminService implements CollectionAdminService {
|
||||
}
|
||||
const collection = new CollectionRequest();
|
||||
collection.externalId = model.externalId;
|
||||
collection.name = (await this.encryptService.encrypt(model.name, key)).encryptedString;
|
||||
collection.name = (await this.encryptService.encryptString(model.name, key)).encryptedString;
|
||||
collection.groups = model.groups.map(
|
||||
(group) =>
|
||||
new SelectionReadOnlyRequest(group.id, group.readOnly, group.hidePasswords, group.manage),
|
||||
|
||||
@@ -112,7 +112,7 @@ export class DefaultCollectionService implements CollectionService {
|
||||
collection.organizationId = model.organizationId;
|
||||
collection.readOnly = model.readOnly;
|
||||
collection.externalId = model.externalId;
|
||||
collection.name = await this.encryptService.encrypt(model.name, key);
|
||||
collection.name = await this.encryptService.encryptString(model.name, key);
|
||||
return collection;
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ export class DefaultvNextCollectionService implements vNextCollectionService {
|
||||
collection.organizationId = model.organizationId;
|
||||
collection.readOnly = model.readOnly;
|
||||
collection.externalId = model.externalId;
|
||||
collection.name = await this.encryptService.encrypt(model.name, key);
|
||||
collection.name = await this.encryptService.encryptString(model.name, key);
|
||||
return collection;
|
||||
}
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ export class SetPasswordComponent extends BaseChangePasswordComponent implements
|
||||
const existingUserPublicKeyB64 = Utils.fromBufferToB64(existingUserPublicKey);
|
||||
newKeyPair = [
|
||||
existingUserPublicKeyB64,
|
||||
await this.encryptService.encrypt(existingUserPrivateKey, userKey[0]),
|
||||
await this.encryptService.wrapDecapsulationKey(existingUserPrivateKey, userKey[0]),
|
||||
];
|
||||
} else {
|
||||
newKeyPair = await this.keyService.makeKeyPair(userKey[0]);
|
||||
|
||||
@@ -193,7 +193,7 @@ export class PinService implements PinServiceAbstraction {
|
||||
|
||||
const pinKey = await this.makePinKey(pin, email, kdfConfig);
|
||||
|
||||
return await this.encryptService.encrypt(userKey.key, pinKey);
|
||||
return await this.encryptService.wrapSymmetricKey(userKey, pinKey);
|
||||
}
|
||||
|
||||
async storePinKeyEncryptedUserKey(
|
||||
@@ -239,7 +239,7 @@ export class PinService implements PinServiceAbstraction {
|
||||
throw new Error("No UserKey provided. Cannot create userKeyEncryptedPin.");
|
||||
}
|
||||
|
||||
return await this.encryptService.encrypt(pin, userKey);
|
||||
return await this.encryptService.encryptString(pin, userKey);
|
||||
}
|
||||
|
||||
async getOldPinKeyEncryptedMasterKey(userId: UserId): Promise<EncryptedString | null> {
|
||||
|
||||
@@ -189,7 +189,7 @@ describe("PinService", () => {
|
||||
await sut.createPinKeyEncryptedUserKey(mockPin, mockUserKey, mockUserId);
|
||||
|
||||
// Assert
|
||||
expect(encryptService.encrypt).toHaveBeenCalledWith(mockUserKey.key, mockPinKey);
|
||||
expect(encryptService.wrapSymmetricKey).toHaveBeenCalledWith(mockUserKey, mockPinKey);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -278,11 +278,11 @@ describe("PinService", () => {
|
||||
});
|
||||
|
||||
it("should create a userKeyEncryptedPin from the provided PIN and userKey", async () => {
|
||||
encryptService.encrypt.mockResolvedValue(mockUserKeyEncryptedPin);
|
||||
encryptService.encryptString.mockResolvedValue(mockUserKeyEncryptedPin);
|
||||
|
||||
const result = await sut.createUserKeyEncryptedPin(mockPin, mockUserKey);
|
||||
|
||||
expect(encryptService.encrypt).toHaveBeenCalledWith(mockPin, mockUserKey);
|
||||
expect(encryptService.encryptString).toHaveBeenCalledWith(mockPin, mockUserKey);
|
||||
expect(result).toEqual(mockUserKeyEncryptedPin);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -293,7 +293,7 @@ describe("TokenService", () => {
|
||||
|
||||
const mockEncryptedAccessToken = "encryptedAccessToken";
|
||||
|
||||
encryptService.encrypt.mockResolvedValue({
|
||||
encryptService.encryptString.mockResolvedValue({
|
||||
encryptedString: mockEncryptedAccessToken,
|
||||
} as any);
|
||||
|
||||
|
||||
@@ -289,7 +289,7 @@ export class TokenService implements TokenServiceAbstraction {
|
||||
private async encryptAccessToken(accessToken: string, userId: UserId): Promise<EncString> {
|
||||
const accessTokenKey = await this.getOrCreateAccessTokenKey(userId);
|
||||
|
||||
return await this.encryptService.encrypt(accessToken, accessTokenKey);
|
||||
return await this.encryptService.encryptString(accessToken, accessTokenKey);
|
||||
}
|
||||
|
||||
private async decryptAccessToken(
|
||||
|
||||
@@ -114,7 +114,7 @@ export class OrganizationBillingService implements OrganizationBillingServiceAbs
|
||||
private async makeOrganizationKeys(): Promise<OrganizationKeys> {
|
||||
const [encryptedKey, key] = await this.keyService.makeOrgKey<OrgKey>();
|
||||
const [publicKey, encryptedPrivateKey] = await this.keyService.makeKeyPair(key);
|
||||
const encryptedCollectionName = await this.encryptService.encrypt(
|
||||
const encryptedCollectionName = await this.encryptService.encryptString(
|
||||
this.i18nService.t("defaultCollection"),
|
||||
key,
|
||||
);
|
||||
|
||||
@@ -6,8 +6,24 @@ import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
|
||||
export abstract class EncryptService {
|
||||
abstract encrypt(plainValue: string | Uint8Array, key: SymmetricCryptoKey): Promise<EncString>;
|
||||
abstract encryptToBytes(plainValue: Uint8Array, key: SymmetricCryptoKey): Promise<EncArrayBuffer>;
|
||||
abstract encryptString(plainValue: string, key: SymmetricCryptoKey): Promise<EncString>;
|
||||
abstract encryptFileData(
|
||||
plainValue: Uint8Array,
|
||||
key: SymmetricCryptoKey,
|
||||
): Promise<EncArrayBuffer>;
|
||||
abstract wrapDecapsulationKey(
|
||||
decapsulationKeyPcks8: Uint8Array,
|
||||
key: SymmetricCryptoKey,
|
||||
): Promise<EncString>;
|
||||
abstract wrapEncapsulationKey(
|
||||
encapsulationKeySpki: Uint8Array,
|
||||
key: SymmetricCryptoKey,
|
||||
): Promise<EncString>;
|
||||
abstract wrapSymmetricKey(
|
||||
encapsulatedKey: SymmetricCryptoKey,
|
||||
key: SymmetricCryptoKey,
|
||||
): Promise<EncString>;
|
||||
|
||||
/**
|
||||
* Decrypts an EncString to a string
|
||||
* @param encString - The EncString to decrypt
|
||||
|
||||
@@ -24,7 +24,7 @@ export class EncryptServiceImplementation implements EncryptService {
|
||||
protected logMacFailures: boolean,
|
||||
) {}
|
||||
|
||||
async encrypt(plainValue: string | Uint8Array, key: SymmetricCryptoKey): Promise<EncString> {
|
||||
async encryptString(plainValue: string, key: SymmetricCryptoKey): Promise<EncString> {
|
||||
if (key == null) {
|
||||
throw new Error("No encryption key provided.");
|
||||
}
|
||||
@@ -33,21 +33,75 @@ export class EncryptServiceImplementation implements EncryptService {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
let plainBuf: Uint8Array;
|
||||
if (typeof plainValue === "string") {
|
||||
plainBuf = Utils.fromUtf8ToArray(plainValue);
|
||||
} else {
|
||||
plainBuf = plainValue;
|
||||
const plainBuf: Uint8Array = Utils.fromUtf8ToArray(plainValue);
|
||||
return this.encryptUint8Array(plainBuf, key);
|
||||
}
|
||||
|
||||
async wrapDecapsulationKey(
|
||||
privateKeyPkcs8: Uint8Array,
|
||||
key: SymmetricCryptoKey,
|
||||
): Promise<EncString> {
|
||||
if (privateKeyPkcs8 == null) {
|
||||
throw new Error("No private key provided for encapsulation.");
|
||||
}
|
||||
|
||||
const encObj = await this.aesEncrypt(plainBuf, key);
|
||||
if (key == null) {
|
||||
throw new Error("No encryption key provided for encapsulation.");
|
||||
}
|
||||
|
||||
return await this.encryptUint8Array(privateKeyPkcs8, key);
|
||||
}
|
||||
|
||||
async wrapEncapsulationKey(
|
||||
encapsulationKeySpki: Uint8Array,
|
||||
key: SymmetricCryptoKey,
|
||||
): Promise<EncString> {
|
||||
if (encapsulationKeySpki == null) {
|
||||
throw new Error("No encapsulation key provided for encapsulation.");
|
||||
}
|
||||
|
||||
if (key == null) {
|
||||
throw new Error("No encryption key provided for encapsulation.");
|
||||
}
|
||||
|
||||
return await this.encryptUint8Array(encapsulationKeySpki, key);
|
||||
}
|
||||
|
||||
async wrapSymmetricKey(
|
||||
encapsulatedKey: SymmetricCryptoKey,
|
||||
key: SymmetricCryptoKey,
|
||||
): Promise<EncString> {
|
||||
if (encapsulatedKey == null) {
|
||||
throw new Error("No encapsulated key provided for encapsulation.");
|
||||
}
|
||||
|
||||
if (key == null) {
|
||||
throw new Error("No encryption key provided for encapsulation.");
|
||||
}
|
||||
|
||||
return await this.encryptUint8Array(encapsulatedKey.encKey, key);
|
||||
}
|
||||
|
||||
private async encryptUint8Array(
|
||||
plainValue: Uint8Array,
|
||||
key: SymmetricCryptoKey,
|
||||
): Promise<EncString> {
|
||||
if (key == null) {
|
||||
throw new Error("No encryption key provided.");
|
||||
}
|
||||
|
||||
if (plainValue == null) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
const encObj = await this.aesEncrypt(plainValue, 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.encType, data, iv, mac);
|
||||
}
|
||||
|
||||
async encryptToBytes(plainValue: Uint8Array, key: SymmetricCryptoKey): Promise<EncArrayBuffer> {
|
||||
async encryptFileData(plainValue: Uint8Array, key: SymmetricCryptoKey): Promise<EncArrayBuffer> {
|
||||
if (key == null) {
|
||||
throw new Error("No encryption key provided.");
|
||||
}
|
||||
|
||||
@@ -28,13 +28,13 @@ describe("EncryptService", () => {
|
||||
|
||||
describe("encrypt", () => {
|
||||
it("throws if no key is provided", () => {
|
||||
return expect(encryptService.encrypt(null, null)).rejects.toThrow(
|
||||
return expect(encryptService.encryptString(null, null)).rejects.toThrow(
|
||||
"No encryption key provided.",
|
||||
);
|
||||
});
|
||||
it("returns null if no data is provided", async () => {
|
||||
const key = mock<SymmetricCryptoKey>();
|
||||
const actual = await encryptService.encrypt(null, key);
|
||||
const actual = await encryptService.encryptString(null, key);
|
||||
expect(actual).toBeNull();
|
||||
});
|
||||
it("creates an EncString for Aes256Cbc", async () => {
|
||||
@@ -42,7 +42,7 @@ describe("EncryptService", () => {
|
||||
const plainValue = "data";
|
||||
cryptoFunctionService.aesEncrypt.mockResolvedValue(makeStaticByteArray(4, 100));
|
||||
cryptoFunctionService.randomBytes.mockResolvedValue(makeStaticByteArray(16) as CsprngArray);
|
||||
const result = await encryptService.encrypt(plainValue, key);
|
||||
const result = await encryptService.encryptString(plainValue, key);
|
||||
expect(cryptoFunctionService.aesEncrypt).toHaveBeenCalledWith(
|
||||
Utils.fromByteStringToArray(plainValue),
|
||||
makeStaticByteArray(16),
|
||||
@@ -59,7 +59,7 @@ describe("EncryptService", () => {
|
||||
cryptoFunctionService.hmac.mockResolvedValue(makeStaticByteArray(32));
|
||||
cryptoFunctionService.aesEncrypt.mockResolvedValue(makeStaticByteArray(4, 100));
|
||||
cryptoFunctionService.randomBytes.mockResolvedValue(makeStaticByteArray(16) as CsprngArray);
|
||||
const result = await encryptService.encrypt(plainValue, key);
|
||||
const result = await encryptService.encryptString(plainValue, key);
|
||||
expect(cryptoFunctionService.aesEncrypt).toHaveBeenCalledWith(
|
||||
Utils.fromByteStringToArray(plainValue),
|
||||
makeStaticByteArray(16),
|
||||
@@ -85,7 +85,7 @@ describe("EncryptService", () => {
|
||||
const plainValue = makeStaticByteArray(16, 1);
|
||||
|
||||
it("throws if no key is provided", () => {
|
||||
return expect(encryptService.encryptToBytes(plainValue, null)).rejects.toThrow(
|
||||
return expect(encryptService.encryptFileData(plainValue, null)).rejects.toThrow(
|
||||
"No encryption key",
|
||||
);
|
||||
});
|
||||
@@ -97,7 +97,7 @@ describe("EncryptService", () => {
|
||||
cryptoFunctionService.randomBytes.mockResolvedValue(iv as CsprngArray);
|
||||
cryptoFunctionService.aesEncrypt.mockResolvedValue(cipherText);
|
||||
|
||||
const actual = await encryptService.encryptToBytes(plainValue, key);
|
||||
const actual = await encryptService.encryptFileData(plainValue, key);
|
||||
const expectedBytes = new Uint8Array(1 + iv.byteLength + cipherText.byteLength);
|
||||
expectedBytes.set([EncryptionType.AesCbc256_B64]);
|
||||
expectedBytes.set(iv, 1);
|
||||
@@ -115,7 +115,7 @@ describe("EncryptService", () => {
|
||||
cryptoFunctionService.aesEncrypt.mockResolvedValue(cipherText);
|
||||
cryptoFunctionService.hmac.mockResolvedValue(mac);
|
||||
|
||||
const actual = await encryptService.encryptToBytes(plainValue, key);
|
||||
const actual = await encryptService.encryptFileData(plainValue, key);
|
||||
const expectedBytes = new Uint8Array(
|
||||
1 + iv.byteLength + mac.byteLength + cipherText.byteLength,
|
||||
);
|
||||
|
||||
@@ -163,10 +163,10 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction {
|
||||
this.encryptService.rsaEncrypt(userKey.key, devicePublicKey),
|
||||
|
||||
// Encrypt devicePublicKey with user key
|
||||
this.encryptService.encrypt(devicePublicKey, userKey),
|
||||
this.encryptService.wrapEncapsulationKey(devicePublicKey, userKey),
|
||||
|
||||
// Encrypt devicePrivateKey with deviceKey
|
||||
this.encryptService.encrypt(devicePrivateKey, deviceKey),
|
||||
this.encryptService.wrapDecapsulationKey(devicePrivateKey, deviceKey),
|
||||
]);
|
||||
|
||||
// Send encrypted keys to server
|
||||
@@ -234,7 +234,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction {
|
||||
);
|
||||
|
||||
// Re-encrypt the device public key with the new user key
|
||||
const encryptedDevicePublicKey = await this.encryptService.encrypt(
|
||||
const encryptedDevicePublicKey = await this.encryptService.wrapEncapsulationKey(
|
||||
decryptedDevicePublicKey,
|
||||
newUserKey,
|
||||
);
|
||||
|
||||
@@ -345,8 +345,6 @@ describe("deviceTrustService", () => {
|
||||
|
||||
const deviceRsaKeyLength = 2048;
|
||||
let mockDeviceRsaKeyPair: [Uint8Array, Uint8Array];
|
||||
let mockDevicePrivateKey: Uint8Array;
|
||||
let mockDevicePublicKey: Uint8Array;
|
||||
let mockDevicePublicKeyEncryptedUserKey: EncString;
|
||||
let mockUserKeyEncryptedDevicePublicKey: EncString;
|
||||
let mockDeviceKeyEncryptedDevicePrivateKey: EncString;
|
||||
@@ -365,7 +363,8 @@ describe("deviceTrustService", () => {
|
||||
let rsaGenerateKeyPairSpy: jest.SpyInstance;
|
||||
let cryptoSvcGetUserKeySpy: jest.SpyInstance;
|
||||
let cryptoSvcRsaEncryptSpy: jest.SpyInstance;
|
||||
let encryptServiceEncryptSpy: jest.SpyInstance;
|
||||
let encryptServiceWrapDecapsulationKeySpy: jest.SpyInstance;
|
||||
let encryptServiceWrapEncapsulationKeySpy: jest.SpyInstance;
|
||||
let appIdServiceGetAppIdSpy: jest.SpyInstance;
|
||||
let devicesApiServiceUpdateTrustedDeviceKeysSpy: jest.SpyInstance;
|
||||
|
||||
@@ -383,9 +382,6 @@ describe("deviceTrustService", () => {
|
||||
new Uint8Array(deviceRsaKeyLength),
|
||||
];
|
||||
|
||||
mockDevicePublicKey = mockDeviceRsaKeyPair[0];
|
||||
mockDevicePrivateKey = mockDeviceRsaKeyPair[1];
|
||||
|
||||
mockDevicePublicKeyEncryptedUserKey = new EncString(
|
||||
EncryptionType.Rsa2048_OaepSha1_B64,
|
||||
"mockDevicePublicKeyEncryptedUserKey",
|
||||
@@ -418,13 +414,17 @@ describe("deviceTrustService", () => {
|
||||
.spyOn(encryptService, "rsaEncrypt")
|
||||
.mockResolvedValue(mockDevicePublicKeyEncryptedUserKey);
|
||||
|
||||
encryptServiceEncryptSpy = jest
|
||||
.spyOn(encryptService, "encrypt")
|
||||
encryptServiceWrapEncapsulationKeySpy = jest
|
||||
.spyOn(encryptService, "wrapEncapsulationKey")
|
||||
.mockImplementation((plainValue, key) => {
|
||||
if (plainValue === mockDevicePublicKey && key === mockUserKey) {
|
||||
if (plainValue instanceof Uint8Array && key instanceof SymmetricCryptoKey) {
|
||||
return Promise.resolve(mockUserKeyEncryptedDevicePublicKey);
|
||||
}
|
||||
if (plainValue === mockDevicePrivateKey && key === mockDeviceKey) {
|
||||
});
|
||||
encryptServiceWrapDecapsulationKeySpy = jest
|
||||
.spyOn(encryptService, "wrapDecapsulationKey")
|
||||
.mockImplementation((plainValue, key) => {
|
||||
if (plainValue instanceof Uint8Array && key instanceof SymmetricCryptoKey) {
|
||||
return Promise.resolve(mockDeviceKeyEncryptedDevicePrivateKey);
|
||||
}
|
||||
});
|
||||
@@ -451,7 +451,8 @@ describe("deviceTrustService", () => {
|
||||
const userKeyKey: Uint8Array = cryptoSvcRsaEncryptSpy.mock.calls[0][0];
|
||||
expect(userKeyKey.byteLength).toBe(64);
|
||||
|
||||
expect(encryptServiceEncryptSpy).toHaveBeenCalledTimes(2);
|
||||
expect(encryptServiceWrapDecapsulationKeySpy).toHaveBeenCalledTimes(1);
|
||||
expect(encryptServiceWrapEncapsulationKeySpy).toHaveBeenCalledTimes(1);
|
||||
|
||||
expect(appIdServiceGetAppIdSpy).toHaveBeenCalledTimes(1);
|
||||
expect(devicesApiServiceUpdateTrustedDeviceKeysSpy).toHaveBeenCalledTimes(1);
|
||||
@@ -507,9 +508,14 @@ describe("deviceTrustService", () => {
|
||||
errorText: "rsaEncrypt error",
|
||||
},
|
||||
{
|
||||
method: "encryptService.encrypt",
|
||||
spy: () => encryptServiceEncryptSpy,
|
||||
errorText: "encryptService.encrypt error",
|
||||
method: "encryptService.wrapEncapsulationKey",
|
||||
spy: () => encryptServiceWrapEncapsulationKeySpy,
|
||||
errorText: "encryptService.wrapEncapsulationKey error",
|
||||
},
|
||||
{
|
||||
method: "encryptService.wrapDecapsulationKey",
|
||||
spy: () => encryptServiceWrapDecapsulationKeySpy,
|
||||
errorText: "encryptService.wrapDecapsulationKey error",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -748,7 +754,7 @@ describe("deviceTrustService", () => {
|
||||
});
|
||||
|
||||
// Mock the reencryption of the device public key with the new user key
|
||||
encryptService.encrypt.mockImplementationOnce((plainValue, key) => {
|
||||
encryptService.wrapEncapsulationKey.mockImplementationOnce((plainValue, key) => {
|
||||
expect(plainValue).toBeInstanceOf(Uint8Array);
|
||||
expect(new Uint8Array(plainValue as Uint8Array)[0]).toBe(FakeDecryptedPublicKeyMarker);
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ describe("DomainBase", () => {
|
||||
});
|
||||
|
||||
function setUpCryptography() {
|
||||
encryptService.encrypt.mockImplementation((value) => {
|
||||
encryptService.encryptString.mockImplementation((value) => {
|
||||
let data: string;
|
||||
if (typeof value === "string") {
|
||||
data = value;
|
||||
@@ -82,7 +82,7 @@ describe("DomainBase", () => {
|
||||
|
||||
const domain = new TestDomain();
|
||||
|
||||
domain.encToString = await encryptService.encrypt("string", key);
|
||||
domain.encToString = await encryptService.encryptString("string", key);
|
||||
|
||||
const decrypted = await domain["decryptObjWithKey"](["encToString"], key, encryptService);
|
||||
|
||||
@@ -96,8 +96,8 @@ describe("DomainBase", () => {
|
||||
|
||||
const domain = new TestDomain();
|
||||
|
||||
domain.encToString = await encryptService.encrypt("string", key);
|
||||
domain.encString2 = await encryptService.encrypt("string2", key);
|
||||
domain.encToString = await encryptService.encryptString("string", key);
|
||||
domain.encString2 = await encryptService.encryptString("string2", key);
|
||||
|
||||
const decrypted = await domain["decryptObjWithKey"](
|
||||
["encToString", "encString2"],
|
||||
|
||||
@@ -123,7 +123,7 @@ describe("EncString", () => {
|
||||
.mockResolvedValue("decrypted");
|
||||
|
||||
function setupEncryption() {
|
||||
encryptService.encrypt.mockImplementation(async (data, key) => {
|
||||
encryptService.encryptString.mockImplementation(async (data, key) => {
|
||||
if (typeof data === "string") {
|
||||
return makeEncString(data);
|
||||
} else {
|
||||
|
||||
@@ -22,7 +22,9 @@ describe("OrgKeyEncryptor", () => {
|
||||
// on this property--that the facade treats its data like a opaque objects--to trace
|
||||
// the data through several function calls. Should the encryptor interact with the
|
||||
// objects themselves, these mocks will break.
|
||||
encryptService.encrypt.mockImplementation((p) => Promise.resolve(p as unknown as EncString));
|
||||
encryptService.encryptString.mockImplementation((p) =>
|
||||
Promise.resolve(p as unknown as EncString),
|
||||
);
|
||||
encryptService.decryptToUtf8.mockImplementation((c) => Promise.resolve(c as unknown as string));
|
||||
dataPacker.pack.mockImplementation((v) => v as string);
|
||||
dataPacker.unpack.mockImplementation(<T>(v: string) => v as T);
|
||||
@@ -95,7 +97,7 @@ describe("OrgKeyEncryptor", () => {
|
||||
|
||||
// these are data flow expectations; the operations all all pass-through mocks
|
||||
expect(dataPacker.pack).toHaveBeenCalledWith(value);
|
||||
expect(encryptService.encrypt).toHaveBeenCalledWith(value, orgKey);
|
||||
expect(encryptService.encryptString).toHaveBeenCalledWith(value, orgKey);
|
||||
expect(result).toBe(value);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -37,7 +37,7 @@ export class OrganizationKeyEncryptor extends OrganizationEncryptor {
|
||||
this.assertHasValue("secret", secret);
|
||||
|
||||
let packed = this.dataPacker.pack(secret);
|
||||
const encrypted = await this.encryptService.encrypt(packed, this.key);
|
||||
const encrypted = await this.encryptService.encryptString(packed, this.key);
|
||||
packed = null;
|
||||
|
||||
return encrypted;
|
||||
|
||||
@@ -22,7 +22,9 @@ describe("UserKeyEncryptor", () => {
|
||||
// on this property--that the facade treats its data like a opaque objects--to trace
|
||||
// the data through several function calls. Should the encryptor interact with the
|
||||
// objects themselves, these mocks will break.
|
||||
encryptService.encrypt.mockImplementation((p) => Promise.resolve(p as unknown as EncString));
|
||||
encryptService.encryptString.mockImplementation((p) =>
|
||||
Promise.resolve(p as unknown as EncString),
|
||||
);
|
||||
encryptService.decryptToUtf8.mockImplementation((c) => Promise.resolve(c as unknown as string));
|
||||
dataPacker.pack.mockImplementation((v) => v as string);
|
||||
dataPacker.unpack.mockImplementation(<T>(v: string) => v as T);
|
||||
@@ -95,7 +97,7 @@ describe("UserKeyEncryptor", () => {
|
||||
|
||||
// these are data flow expectations; the operations all all pass-through mocks
|
||||
expect(dataPacker.pack).toHaveBeenCalledWith(value);
|
||||
expect(encryptService.encrypt).toHaveBeenCalledWith(value, userKey);
|
||||
expect(encryptService.encryptString).toHaveBeenCalledWith(value, userKey);
|
||||
expect(result).toBe(value);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -37,7 +37,7 @@ export class UserKeyEncryptor extends UserEncryptor {
|
||||
this.assertHasValue("secret", secret);
|
||||
|
||||
let packed = this.dataPacker.pack(secret);
|
||||
const encrypted = await this.encryptService.encrypt(packed, this.key);
|
||||
const encrypted = await this.encryptService.encryptString(packed, this.key);
|
||||
packed = null;
|
||||
|
||||
return encrypted;
|
||||
|
||||
@@ -479,7 +479,7 @@ describe("SendService", () => {
|
||||
beforeEach(() => {
|
||||
encryptService.decryptToBytes.mockResolvedValue(new Uint8Array(32));
|
||||
encryptedKey = new EncString("Re-encrypted Send Key");
|
||||
encryptService.encrypt.mockResolvedValue(encryptedKey);
|
||||
encryptService.wrapSymmetricKey.mockResolvedValue(encryptedKey);
|
||||
});
|
||||
|
||||
it("returns re-encrypted user sends", async () => {
|
||||
|
||||
@@ -81,12 +81,12 @@ export class SendService implements InternalSendServiceAbstraction {
|
||||
if (key == null) {
|
||||
key = await this.keyService.getUserKey();
|
||||
}
|
||||
send.key = await this.encryptService.encrypt(model.key, key);
|
||||
send.name = await this.encryptService.encrypt(model.name, model.cryptoKey);
|
||||
send.notes = await this.encryptService.encrypt(model.notes, model.cryptoKey);
|
||||
send.key = await this.encryptService.wrapSymmetricKey(new SymmetricCryptoKey(model.key), key);
|
||||
send.name = await this.encryptService.encryptString(model.name, model.cryptoKey);
|
||||
send.notes = await this.encryptService.encryptString(model.notes, model.cryptoKey);
|
||||
if (send.type === SendType.Text) {
|
||||
send.text = new SendText();
|
||||
send.text.text = await this.encryptService.encrypt(model.text.text, model.cryptoKey);
|
||||
send.text.text = await this.encryptService.encryptString(model.text.text, model.cryptoKey);
|
||||
send.text.hidden = model.text.hidden;
|
||||
} else if (send.type === SendType.File) {
|
||||
send.file = new SendFile();
|
||||
@@ -287,8 +287,10 @@ export class SendService implements InternalSendServiceAbstraction {
|
||||
) {
|
||||
const requests = await Promise.all(
|
||||
sends.map(async (send) => {
|
||||
const sendKey = await this.encryptService.decryptToBytes(send.key, originalUserKey);
|
||||
send.key = await this.encryptService.encrypt(sendKey, rotateUserKey);
|
||||
const sendKey = new SymmetricCryptoKey(
|
||||
await this.encryptService.decryptToBytes(send.key, originalUserKey),
|
||||
);
|
||||
send.key = await this.encryptService.wrapSymmetricKey(sendKey, rotateUserKey);
|
||||
return new SendWithIdRequest(send);
|
||||
}),
|
||||
);
|
||||
@@ -326,8 +328,8 @@ export class SendService implements InternalSendServiceAbstraction {
|
||||
if (key == null) {
|
||||
key = await this.keyService.getUserKey();
|
||||
}
|
||||
const encFileName = await this.encryptService.encrypt(fileName, key);
|
||||
const encFileData = await this.encryptService.encryptToBytes(new Uint8Array(data), key);
|
||||
const encFileName = await this.encryptService.encryptString(fileName, key);
|
||||
const encFileData = await this.encryptService.encryptFileData(new Uint8Array(data), key);
|
||||
return [encFileName, encFileData];
|
||||
}
|
||||
|
||||
|
||||
@@ -129,8 +129,8 @@ describe("Cipher Service", () => {
|
||||
let cipherObj: Cipher;
|
||||
|
||||
beforeEach(() => {
|
||||
encryptService.encryptToBytes.mockReturnValue(Promise.resolve(ENCRYPTED_BYTES));
|
||||
encryptService.encrypt.mockReturnValue(Promise.resolve(new EncString(ENCRYPTED_TEXT)));
|
||||
encryptService.encryptFileData.mockReturnValue(Promise.resolve(ENCRYPTED_BYTES));
|
||||
encryptService.encryptString.mockReturnValue(Promise.resolve(new EncString(ENCRYPTED_TEXT)));
|
||||
|
||||
(window as any).bitwardenContainerService = new ContainerService(keyService, encryptService);
|
||||
|
||||
@@ -276,7 +276,8 @@ describe("Cipher Service", () => {
|
||||
keyService.makeCipherKey.mockReturnValue(
|
||||
Promise.resolve(new SymmetricCryptoKey(makeStaticByteArray(64)) as CipherKey),
|
||||
);
|
||||
encryptService.encrypt.mockImplementation(encryptText);
|
||||
encryptService.encryptString.mockImplementation(encryptText);
|
||||
encryptService.wrapSymmetricKey.mockResolvedValue(new EncString("Re-encrypted Cipher Key"));
|
||||
|
||||
jest.spyOn(cipherService as any, "getAutofillOnPageLoadDefault").mockResolvedValue(true);
|
||||
});
|
||||
@@ -398,7 +399,7 @@ describe("Cipher Service", () => {
|
||||
|
||||
encryptService.decryptToBytes.mockResolvedValue(new Uint8Array(32));
|
||||
encryptedKey = new EncString("Re-encrypted Cipher Key");
|
||||
encryptService.encrypt.mockResolvedValue(encryptedKey);
|
||||
encryptService.wrapSymmetricKey.mockResolvedValue(encryptedKey);
|
||||
|
||||
keyService.makeCipherKey.mockResolvedValue(
|
||||
new SymmetricCryptoKey(new Uint8Array(32)) as CipherKey,
|
||||
|
||||
@@ -271,7 +271,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
key,
|
||||
).then(async () => {
|
||||
if (model.key != null) {
|
||||
attachment.key = await this.encryptService.encrypt(model.key.key, key);
|
||||
attachment.key = await this.encryptService.wrapSymmetricKey(model.key, key);
|
||||
}
|
||||
encAttachments.push(attachment);
|
||||
});
|
||||
@@ -893,10 +893,10 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
await this.updateWithServer(cipher);
|
||||
}
|
||||
|
||||
const encFileName = await this.encryptService.encrypt(filename, cipherEncKey);
|
||||
const encFileName = await this.encryptService.encryptString(filename, cipherEncKey);
|
||||
|
||||
const dataEncKey = await this.keyService.makeDataEncKey(cipherEncKey);
|
||||
const encData = await this.encryptService.encryptToBytes(new Uint8Array(data), dataEncKey[0]);
|
||||
const encData = await this.encryptService.encryptFileData(new Uint8Array(data), dataEncKey[0]);
|
||||
|
||||
const response = await this.cipherFileUploadService.upload(
|
||||
cipher,
|
||||
@@ -1496,8 +1496,11 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
|
||||
const dataEncKey = await this.keyService.makeDataEncKey(encKey);
|
||||
|
||||
const encFileName = await this.encryptService.encrypt(attachmentView.fileName, encKey);
|
||||
const encData = await this.encryptService.encryptToBytes(new Uint8Array(decBuf), dataEncKey[0]);
|
||||
const encFileName = await this.encryptService.encryptString(attachmentView.fileName, encKey);
|
||||
const encData = await this.encryptService.encryptFileData(
|
||||
new Uint8Array(decBuf),
|
||||
dataEncKey[0],
|
||||
);
|
||||
|
||||
const fd = new FormData();
|
||||
try {
|
||||
@@ -1552,7 +1555,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
.then(() => {
|
||||
const modelProp = (model as any)[map[theProp] || theProp];
|
||||
if (modelProp && modelProp !== "") {
|
||||
return self.encryptService.encrypt(modelProp, key);
|
||||
return self.encryptService.encryptString(modelProp, key);
|
||||
}
|
||||
return null;
|
||||
})
|
||||
@@ -1598,7 +1601,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
key,
|
||||
);
|
||||
const uriHash = await this.encryptService.hash(model.login.uris[i].uri, "sha256");
|
||||
loginUri.uriChecksum = await this.encryptService.encrypt(uriHash, key);
|
||||
loginUri.uriChecksum = await this.encryptService.encryptString(uriHash, key);
|
||||
cipher.login.uris.push(loginUri);
|
||||
}
|
||||
}
|
||||
@@ -1625,8 +1628,11 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
},
|
||||
key,
|
||||
);
|
||||
domainKey.counter = await this.encryptService.encrypt(String(viewKey.counter), key);
|
||||
domainKey.discoverable = await this.encryptService.encrypt(
|
||||
domainKey.counter = await this.encryptService.encryptString(
|
||||
String(viewKey.counter),
|
||||
key,
|
||||
);
|
||||
domainKey.discoverable = await this.encryptService.encryptString(
|
||||
String(viewKey.discoverable),
|
||||
key,
|
||||
);
|
||||
@@ -1818,8 +1824,8 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
}
|
||||
|
||||
// Then, we have to encrypt the cipher key with the proper key.
|
||||
cipher.key = await this.encryptService.encrypt(
|
||||
decryptedCipherKey.key,
|
||||
cipher.key = await this.encryptService.wrapSymmetricKey(
|
||||
decryptedCipherKey,
|
||||
keyForCipherKeyEncryption,
|
||||
);
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ describe("Folder Service", () => {
|
||||
model.id = "2";
|
||||
model.name = "Test Folder";
|
||||
|
||||
encryptService.encrypt.mockResolvedValue(new EncString("ENC"));
|
||||
encryptService.encryptString.mockResolvedValue(new EncString("ENC"));
|
||||
|
||||
const result = await folderService.encrypt(model, null);
|
||||
|
||||
@@ -211,7 +211,7 @@ describe("Folder Service", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
encryptedKey = new EncString("Re-encrypted Folder");
|
||||
encryptService.encrypt.mockResolvedValue(encryptedKey);
|
||||
encryptService.encryptString.mockResolvedValue(encryptedKey);
|
||||
});
|
||||
|
||||
it("returns re-encrypted user folders", async () => {
|
||||
|
||||
@@ -84,7 +84,7 @@ export class FolderService implements InternalFolderServiceAbstraction {
|
||||
async encrypt(model: FolderView, key: SymmetricCryptoKey): Promise<Folder> {
|
||||
const folder = new Folder();
|
||||
folder.id = model.id;
|
||||
folder.name = await this.encryptService.encrypt(model.name, key);
|
||||
folder.name = await this.encryptService.encryptString(model.name, key);
|
||||
return folder;
|
||||
}
|
||||
|
||||
|
||||
@@ -232,7 +232,7 @@ export class DefaultKeyService implements KeyServiceAbstraction {
|
||||
}
|
||||
|
||||
const newUserKey = await this.keyGenerationService.createKey(512);
|
||||
return this.buildProtectedSymmetricKey(masterKey, newUserKey.key);
|
||||
return this.buildProtectedSymmetricKey(masterKey, newUserKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -319,7 +319,7 @@ export class DefaultKeyService implements KeyServiceAbstraction {
|
||||
userKey?: UserKey,
|
||||
): Promise<[UserKey, EncString]> {
|
||||
userKey ||= await this.getUserKey();
|
||||
return await this.buildProtectedSymmetricKey(masterKey, userKey.key);
|
||||
return await this.buildProtectedSymmetricKey(masterKey, userKey);
|
||||
}
|
||||
|
||||
// TODO: move to MasterPasswordService
|
||||
@@ -429,7 +429,7 @@ export class DefaultKeyService implements KeyServiceAbstraction {
|
||||
}
|
||||
|
||||
const newSymKey = await this.keyGenerationService.createKey(512);
|
||||
return this.buildProtectedSymmetricKey(key, newSymKey.key);
|
||||
return this.buildProtectedSymmetricKey(key, newSymKey);
|
||||
}
|
||||
|
||||
private async clearOrgKeys(userId: UserId): Promise<void> {
|
||||
@@ -543,7 +543,7 @@ export class DefaultKeyService implements KeyServiceAbstraction {
|
||||
|
||||
const keyPair = await this.cryptoFunctionService.rsaGenerateKeyPair(2048);
|
||||
const publicB64 = Utils.fromBufferToB64(keyPair[0]);
|
||||
const privateEnc = await this.encryptService.encrypt(keyPair[1], key);
|
||||
const privateEnc = await this.encryptService.wrapDecapsulationKey(keyPair[1], key);
|
||||
return [publicB64, privateEnc];
|
||||
}
|
||||
|
||||
@@ -821,18 +821,21 @@ export class DefaultKeyService implements KeyServiceAbstraction {
|
||||
|
||||
private async buildProtectedSymmetricKey<T extends SymmetricCryptoKey>(
|
||||
encryptionKey: SymmetricCryptoKey,
|
||||
newSymKey: Uint8Array,
|
||||
newSymKey: SymmetricCryptoKey,
|
||||
): Promise<[T, EncString]> {
|
||||
let protectedSymKey: EncString;
|
||||
if (encryptionKey.key.byteLength === 32) {
|
||||
const stretchedEncryptionKey = await this.keyGenerationService.stretchKey(encryptionKey);
|
||||
protectedSymKey = await this.encryptService.encrypt(newSymKey, stretchedEncryptionKey);
|
||||
protectedSymKey = await this.encryptService.wrapSymmetricKey(
|
||||
newSymKey,
|
||||
stretchedEncryptionKey,
|
||||
);
|
||||
} else if (encryptionKey.key.byteLength === 64) {
|
||||
protectedSymKey = await this.encryptService.encrypt(newSymKey, encryptionKey);
|
||||
protectedSymKey = await this.encryptService.wrapSymmetricKey(newSymKey, encryptionKey);
|
||||
} else {
|
||||
throw new Error("Invalid key size.");
|
||||
}
|
||||
return [new SymmetricCryptoKey(newSymKey) as T, protectedSymKey];
|
||||
return [newSymKey as T, protectedSymKey];
|
||||
}
|
||||
|
||||
// --LEGACY METHODS--
|
||||
|
||||
@@ -23,8 +23,8 @@ export class BaseVaultExportService {
|
||||
const salt = Utils.fromBufferToB64(await this.cryptoFunctionService.randomBytes(16));
|
||||
const key = await this.pinService.makePinKey(password, salt, kdfConfig);
|
||||
|
||||
const encKeyValidation = await this.encryptService.encrypt(Utils.newGuid(), key);
|
||||
const encText = await this.encryptService.encrypt(clearText, key);
|
||||
const encKeyValidation = await this.encryptService.encryptString(Utils.newGuid(), key);
|
||||
const encText = await this.encryptService.encryptString(clearText, key);
|
||||
|
||||
const jsonDoc: BitwardenPasswordProtectedFileFormat = {
|
||||
encrypted: true,
|
||||
|
||||
@@ -181,7 +181,7 @@ describe("VaultExportService", () => {
|
||||
folderService.folderViews$.mockReturnValue(of(UserFolderViews));
|
||||
folderService.folders$.mockReturnValue(of(UserFolders));
|
||||
kdfConfigService.getKdfConfig.mockResolvedValue(DEFAULT_KDF_CONFIG);
|
||||
encryptService.encrypt.mockResolvedValue(new EncString("encrypted"));
|
||||
encryptService.encryptString.mockResolvedValue(new EncString("encrypted"));
|
||||
|
||||
exportService = new IndividualVaultExportService(
|
||||
folderService,
|
||||
@@ -271,7 +271,7 @@ describe("VaultExportService", () => {
|
||||
});
|
||||
|
||||
it("has a mac property", async () => {
|
||||
encryptService.encrypt.mockResolvedValue(mac);
|
||||
encryptService.encryptString.mockResolvedValue(mac);
|
||||
exportString = await exportService.getPasswordProtectedExport(password);
|
||||
exportObject = JSON.parse(exportString);
|
||||
|
||||
@@ -279,7 +279,7 @@ describe("VaultExportService", () => {
|
||||
});
|
||||
|
||||
it("has data property", async () => {
|
||||
encryptService.encrypt.mockResolvedValue(data);
|
||||
encryptService.encryptString.mockResolvedValue(data);
|
||||
exportString = await exportService.getPasswordProtectedExport(password);
|
||||
exportObject = JSON.parse(exportString);
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ export class IndividualVaultExportService
|
||||
const userKey = await this.keyService.getUserKeyWithLegacySupport(
|
||||
await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId)),
|
||||
);
|
||||
const encKeyValidation = await this.encryptService.encrypt(Utils.newGuid(), userKey);
|
||||
const encKeyValidation = await this.encryptService.encryptString(Utils.newGuid(), userKey);
|
||||
|
||||
const jsonDoc: BitwardenEncryptedIndividualJsonExport = {
|
||||
encrypted: true,
|
||||
|
||||
@@ -248,7 +248,7 @@ export class OrganizationVaultExportService
|
||||
ciphers: Cipher[],
|
||||
): Promise<string> {
|
||||
const orgKey = await this.keyService.getOrgKey(organizationId);
|
||||
const encKeyValidation = await this.encryptService.encrypt(Utils.newGuid(), orgKey);
|
||||
const encKeyValidation = await this.encryptService.encryptString(Utils.newGuid(), orgKey);
|
||||
|
||||
const jsonDoc: BitwardenEncryptedOrgJsonExport = {
|
||||
encrypted: true,
|
||||
|
||||
@@ -171,7 +171,7 @@ describe("VaultExportService", () => {
|
||||
folderService.folderViews$.mockReturnValue(of(UserFolderViews));
|
||||
folderService.folders$.mockReturnValue(of(UserFolders));
|
||||
kdfConfigService.getKdfConfig.mockResolvedValue(DEFAULT_KDF_CONFIG);
|
||||
encryptService.encrypt.mockResolvedValue(new EncString("encrypted"));
|
||||
encryptService.encryptString.mockResolvedValue(new EncString("encrypted"));
|
||||
keyService.userKey$.mockReturnValue(new BehaviorSubject("mockOriginalUserKey" as any));
|
||||
const userId = "" as UserId;
|
||||
const accountInfo: AccountInfo = {
|
||||
@@ -270,7 +270,7 @@ describe("VaultExportService", () => {
|
||||
});
|
||||
|
||||
it("has a mac property", async () => {
|
||||
encryptService.encrypt.mockResolvedValue(mac);
|
||||
encryptService.encryptString.mockResolvedValue(mac);
|
||||
exportString = await exportService.getPasswordProtectedExport(password);
|
||||
exportObject = JSON.parse(exportString);
|
||||
|
||||
@@ -278,7 +278,7 @@ describe("VaultExportService", () => {
|
||||
});
|
||||
|
||||
it("has data property", async () => {
|
||||
encryptService.encrypt.mockResolvedValue(data);
|
||||
encryptService.encryptString.mockResolvedValue(data);
|
||||
exportString = await exportService.getPasswordProtectedExport(password);
|
||||
exportObject = JSON.parse(exportString);
|
||||
|
||||
|
||||
@@ -22,7 +22,9 @@ describe("LocalGeneratorHistoryService", () => {
|
||||
const userKey = new SymmetricCryptoKey(new Uint8Array(64) as CsprngArray) as UserKey;
|
||||
|
||||
beforeEach(() => {
|
||||
encryptService.encrypt.mockImplementation((p) => Promise.resolve(p as unknown as EncString));
|
||||
encryptService.encryptString.mockImplementation((p) =>
|
||||
Promise.resolve(p as unknown as EncString),
|
||||
);
|
||||
encryptService.decryptToUtf8.mockImplementation((c) => Promise.resolve(c.encryptedString));
|
||||
keyService.getUserKey.mockImplementation(() => Promise.resolve(userKey));
|
||||
keyService.userKey$.mockImplementation(() => of(true as unknown as UserKey));
|
||||
|
||||
Reference in New Issue
Block a user