1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-10 13:23:34 +00:00

[PM-24079] Switch EncryptedString to SDK type (#15796)

* Update usages of sdk to type-safe SDK type

* Update sdk version

* Update to "toSdk"
This commit is contained in:
Bernd Schoolmann
2025-07-30 23:49:50 +02:00
committed by GitHub
parent 0ebd4a841b
commit 021d275c43
18 changed files with 99 additions and 87 deletions

View File

@@ -1,6 +1,8 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { Jsonify, Opaque } from "type-fest";
import { Jsonify } from "type-fest";
import { EncString as SdkEncString } from "@bitwarden/sdk-internal";
import { EncryptionType, EXPECTED_NUM_PARTS_BY_ENCRYPTION_TYPE } from "../../../platform/enums";
import { Encrypted } from "../../../platform/interfaces/encrypted";
@@ -10,7 +12,7 @@ import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-cr
export const DECRYPT_ERROR = "[error: cannot decrypt]";
export class EncString implements Encrypted {
encryptedString?: EncryptedString;
encryptedString?: SdkEncString;
encryptionType?: EncryptionType;
decryptedValue?: string;
data?: string;
@@ -42,7 +44,11 @@ export class EncString implements Encrypted {
return this.data == null ? null : Utils.fromB64ToArray(this.data);
}
toJSON() {
toSdk(): SdkEncString {
return this.encryptedString;
}
toJSON(): string {
return this.encryptedString as string;
}
@@ -56,14 +62,14 @@ export class EncString implements Encrypted {
private initFromData(encType: EncryptionType, data: string, iv: string, mac: string) {
if (iv != null) {
this.encryptedString = (encType + "." + iv + "|" + data) as EncryptedString;
this.encryptedString = (encType + "." + iv + "|" + data) as SdkEncString;
} else {
this.encryptedString = (encType + "." + data) as EncryptedString;
this.encryptedString = (encType + "." + data) as SdkEncString;
}
// mac
if (mac != null) {
this.encryptedString = (this.encryptedString + "|" + mac) as EncryptedString;
this.encryptedString = (this.encryptedString + "|" + mac) as SdkEncString;
}
this.encryptionType = encType;
@@ -73,7 +79,7 @@ export class EncString implements Encrypted {
}
private initFromEncryptedString(encryptedString: string) {
this.encryptedString = encryptedString as EncryptedString;
this.encryptedString = encryptedString as SdkEncString;
if (!this.encryptedString) {
return;
}
@@ -191,4 +197,8 @@ export class EncString implements Encrypted {
}
}
export type EncryptedString = Opaque<string, "EncString">;
/**
* Temporary type mapping until consumers are moved over.
* @deprecated - Use SdkEncString directly
*/
export type EncryptedString = SdkEncString;

View File

@@ -22,6 +22,7 @@ import {
ClientSettings,
DeviceType as SdkDeviceType,
TokenProvider,
UnsignedSharedKey,
} from "@bitwarden/sdk-internal";
import { EncryptedOrganizationKeyData } from "../../../admin-console/models/data/encrypted-organization-key.data";
@@ -237,7 +238,7 @@ export class DefaultSdkService implements SdkService {
organizationKeys: new Map(
Object.entries(orgKeys ?? {})
.filter(([_, v]) => v.type === "organization")
.map(([k, v]) => [k, v.key]),
.map(([k, v]) => [k, v.key as UnsignedSharedKey]),
),
});
}

View File

@@ -128,8 +128,8 @@ export class Attachment extends Domain {
url: this.url,
size: this.size,
sizeName: this.sizeName,
fileName: this.fileName?.toJSON(),
key: this.key?.toJSON(),
fileName: this.fileName?.toSdk(),
key: this.key?.toSdk(),
};
}

View File

@@ -95,12 +95,12 @@ export class Card extends Domain {
*/
toSdkCard(): SdkCard {
return {
cardholderName: this.cardholderName?.toJSON(),
brand: this.brand?.toJSON(),
number: this.number?.toJSON(),
expMonth: this.expMonth?.toJSON(),
expYear: this.expYear?.toJSON(),
code: this.code?.toJSON(),
cardholderName: this.cardholderName?.toSdk(),
brand: this.brand?.toSdk(),
number: this.number?.toSdk(),
expMonth: this.expMonth?.toSdk(),
expYear: this.expYear?.toSdk(),
code: this.code?.toSdk(),
};
}

View File

@@ -11,6 +11,7 @@ import {
CipherRepromptType as SdkCipherRepromptType,
LoginLinkedIdType,
Cipher as SdkCipher,
EncString as SdkEncString,
} from "@bitwarden/sdk-internal";
import { makeStaticByteArray, mockEnc, mockFromJson } from "../../../../spec/utils";
@@ -1010,22 +1011,22 @@ describe("Cipher DTO", () => {
organizationId: "orgId",
folderId: "folderId",
collectionIds: [],
key: "EncryptedString",
name: "EncryptedString",
notes: "EncryptedString",
key: "EncryptedString" as SdkEncString,
name: "EncryptedString" as SdkEncString,
notes: "EncryptedString" as SdkEncString,
type: SdkCipherType.Login,
login: {
username: "EncryptedString",
password: "EncryptedString",
username: "EncryptedString" as SdkEncString,
password: "EncryptedString" as SdkEncString,
passwordRevisionDate: "2022-01-31T12:00:00.000Z",
uris: [
{
uri: "EncryptedString",
uriChecksum: "EncryptedString",
uri: "EncryptedString" as SdkEncString,
uriChecksum: "EncryptedString" as SdkEncString,
match: UriMatchType.Domain,
},
],
totp: "EncryptedString",
totp: "EncryptedString" as SdkEncString,
autofillOnPageLoad: false,
fido2Credentials: undefined,
},
@@ -1049,35 +1050,35 @@ describe("Cipher DTO", () => {
url: "url",
size: "1100",
sizeName: "1.1 KB",
fileName: "file",
key: "EncKey",
fileName: "file" as SdkEncString,
key: "EncKey" as SdkEncString,
},
{
id: "a2",
url: "url",
size: "1100",
sizeName: "1.1 KB",
fileName: "file",
key: "EncKey",
fileName: "file" as SdkEncString,
key: "EncKey" as SdkEncString,
},
],
fields: [
{
name: "EncryptedString",
value: "EncryptedString",
name: "EncryptedString" as SdkEncString,
value: "EncryptedString" as SdkEncString,
type: FieldType.Linked,
linkedId: LoginLinkedIdType.Username,
},
{
name: "EncryptedString",
value: "EncryptedString",
name: "EncryptedString" as SdkEncString,
value: "EncryptedString" as SdkEncString,
type: FieldType.Linked,
linkedId: LoginLinkedIdType.Password,
},
],
passwordHistory: [
{
password: "EncryptedString",
password: "EncryptedString" as SdkEncString,
lastUsedDate: "2022-01-31T12:00:00.000Z",
},
],

View File

@@ -348,9 +348,9 @@ export class Cipher extends Domain implements Decryptable<CipherView> {
organizationId: this.organizationId ?? undefined,
folderId: this.folderId ?? undefined,
collectionIds: this.collectionIds ?? [],
key: this.key?.toJSON(),
name: this.name.toJSON(),
notes: this.notes?.toJSON(),
key: this.key?.toSdk(),
name: this.name.toSdk(),
notes: this.notes?.toSdk(),
type: this.type,
favorite: this.favorite ?? false,
organizationUseTotp: this.organizationUseTotp ?? false,

View File

@@ -158,18 +158,18 @@ export class Fido2Credential extends Domain {
*/
toSdkFido2Credential(): SdkFido2Credential {
return {
credentialId: this.credentialId?.toJSON(),
keyType: this.keyType.toJSON(),
keyAlgorithm: this.keyAlgorithm.toJSON(),
keyCurve: this.keyCurve.toJSON(),
keyValue: this.keyValue.toJSON(),
rpId: this.rpId.toJSON(),
userHandle: this.userHandle?.toJSON(),
userName: this.userName?.toJSON(),
counter: this.counter.toJSON(),
rpName: this.rpName?.toJSON(),
userDisplayName: this.userDisplayName?.toJSON(),
discoverable: this.discoverable?.toJSON(),
credentialId: this.credentialId?.toSdk(),
keyType: this.keyType.toSdk(),
keyAlgorithm: this.keyAlgorithm.toSdk(),
keyCurve: this.keyCurve.toSdk(),
keyValue: this.keyValue.toSdk(),
rpId: this.rpId.toSdk(),
userHandle: this.userHandle?.toSdk(),
userName: this.userName?.toSdk(),
counter: this.counter.toSdk(),
rpName: this.rpName?.toSdk(),
userDisplayName: this.userDisplayName?.toSdk(),
discoverable: this.discoverable?.toSdk(),
creationDate: this.creationDate.toISOString(),
};
}

View File

@@ -83,8 +83,8 @@ export class Field extends Domain {
*/
toSdkField(): SdkField {
return {
name: this.name?.toJSON(),
value: this.value?.toJSON(),
name: this.name?.toSdk(),
value: this.value?.toSdk(),
type: this.type,
// Safe type cast: client and SDK LinkedIdType enums have identical values
linkedId: this.linkedId as unknown as SdkLinkedIdType,

View File

@@ -175,24 +175,24 @@ export class Identity extends Domain {
*/
toSdkIdentity(): SdkIdentity {
return {
title: this.title?.toJSON(),
firstName: this.firstName?.toJSON(),
middleName: this.middleName?.toJSON(),
lastName: this.lastName?.toJSON(),
address1: this.address1?.toJSON(),
address2: this.address2?.toJSON(),
address3: this.address3?.toJSON(),
city: this.city?.toJSON(),
state: this.state?.toJSON(),
postalCode: this.postalCode?.toJSON(),
country: this.country?.toJSON(),
company: this.company?.toJSON(),
email: this.email?.toJSON(),
phone: this.phone?.toJSON(),
ssn: this.ssn?.toJSON(),
username: this.username?.toJSON(),
passportNumber: this.passportNumber?.toJSON(),
licenseNumber: this.licenseNumber?.toJSON(),
title: this.title?.toSdk(),
firstName: this.firstName?.toSdk(),
middleName: this.middleName?.toSdk(),
lastName: this.lastName?.toSdk(),
address1: this.address1?.toSdk(),
address2: this.address2?.toSdk(),
address3: this.address3?.toSdk(),
city: this.city?.toSdk(),
state: this.state?.toSdk(),
postalCode: this.postalCode?.toSdk(),
country: this.country?.toSdk(),
company: this.company?.toSdk(),
email: this.email?.toSdk(),
phone: this.phone?.toSdk(),
ssn: this.ssn?.toSdk(),
username: this.username?.toSdk(),
passportNumber: this.passportNumber?.toSdk(),
licenseNumber: this.licenseNumber?.toSdk(),
};
}

View File

@@ -97,8 +97,8 @@ export class LoginUri extends Domain {
*/
toSdkLoginUri(): SdkLoginUri {
return {
uri: this.uri?.toJSON(),
uriChecksum: this.uriChecksum?.toJSON(),
uri: this.uri?.toSdk(),
uriChecksum: this.uriChecksum?.toSdk(),
match: this.match,
};
}

View File

@@ -155,10 +155,10 @@ export class Login extends Domain {
toSdkLogin(): SdkLogin {
return {
uris: this.uris?.map((u) => u.toSdkLoginUri()),
username: this.username?.toJSON(),
password: this.password?.toJSON(),
username: this.username?.toSdk(),
password: this.password?.toSdk(),
passwordRevisionDate: this.passwordRevisionDate?.toISOString(),
totp: this.totp?.toJSON(),
totp: this.totp?.toSdk(),
autofillOnPageLoad: this.autofillOnPageLoad ?? undefined,
fido2Credentials: this.fido2Credentials?.map((f) => f.toSdkFido2Credential()),
};

View File

@@ -67,7 +67,7 @@ export class Password extends Domain {
*/
toSdkPasswordHistory(): PasswordHistory {
return {
password: this.password.toJSON(),
password: this.password.toSdk(),
lastUsedDate: this.lastUsedDate.toISOString(),
};
}

View File

@@ -80,9 +80,9 @@ export class SshKey extends Domain {
*/
toSdkSshKey(): SdkSshKey {
return {
privateKey: this.privateKey.toJSON(),
publicKey: this.publicKey.toJSON(),
fingerprint: this.keyFingerprint.toJSON(),
privateKey: this.privateKey.toSdk(),
publicKey: this.publicKey.toSdk(),
fingerprint: this.keyFingerprint.toSdk(),
};
}

View File

@@ -69,7 +69,7 @@ export class AttachmentView implements View {
size: this.size,
sizeName: this.sizeName,
fileName: this.fileName,
key: this.encryptedKey?.toJSON(),
key: this.encryptedKey?.toSdk(),
// TODO: PM-23005 - Temporary field, should be removed when encrypted migration is complete
decryptedKey: this.key ? this.key.toBase64() : null,
};

View File

@@ -331,7 +331,7 @@ export class CipherView implements View, InitializerMetadata {
creationDate: (this.creationDate ?? new Date()).toISOString(),
deletedDate: this.deletedDate?.toISOString(),
reprompt: this.reprompt ?? CipherRepromptType.None,
key: this.key?.toJSON(),
key: this.key?.toSdk(),
// Cipher type specific properties are set in the switch statement below
// CipherView initializes each with default constructors (undefined values)
// The SDK does not expect those undefined values and will throw exceptions

View File

@@ -15,7 +15,7 @@ import { UserId } from "@bitwarden/common/types/guid";
import { UserKey } from "@bitwarden/common/types/key";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
import { VerifyAsymmetricKeysResponse } from "@bitwarden/sdk-internal";
import { VerifyAsymmetricKeysResponse, EncString as SdkEncString } from "@bitwarden/sdk-internal";
import { KeyService } from "../../abstractions/key.service";
import { UserAsymmetricKeysRegenerationApiService } from "../abstractions/user-asymmetric-key-regeneration-api.service";
@@ -28,7 +28,7 @@ function setupVerificationResponse(
) {
const mockKeyPairResponse = {
userPublicKey: "userPublicKey",
userKeyEncryptedPrivateKey: "userKeyEncryptedPrivateKey",
userKeyEncryptedPrivateKey: "userKeyEncryptedPrivateKey" as SdkEncString,
};
sdkService.client.crypto