1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-11 13:53: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 // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @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 { EncryptionType, EXPECTED_NUM_PARTS_BY_ENCRYPTION_TYPE } from "../../../platform/enums";
import { Encrypted } from "../../../platform/interfaces/encrypted"; 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 const DECRYPT_ERROR = "[error: cannot decrypt]";
export class EncString implements Encrypted { export class EncString implements Encrypted {
encryptedString?: EncryptedString; encryptedString?: SdkEncString;
encryptionType?: EncryptionType; encryptionType?: EncryptionType;
decryptedValue?: string; decryptedValue?: string;
data?: string; data?: string;
@@ -42,7 +44,11 @@ export class EncString implements Encrypted {
return this.data == null ? null : Utils.fromB64ToArray(this.data); return this.data == null ? null : Utils.fromB64ToArray(this.data);
} }
toJSON() { toSdk(): SdkEncString {
return this.encryptedString;
}
toJSON(): string {
return this.encryptedString as 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) { private initFromData(encType: EncryptionType, data: string, iv: string, mac: string) {
if (iv != null) { if (iv != null) {
this.encryptedString = (encType + "." + iv + "|" + data) as EncryptedString; this.encryptedString = (encType + "." + iv + "|" + data) as SdkEncString;
} else { } else {
this.encryptedString = (encType + "." + data) as EncryptedString; this.encryptedString = (encType + "." + data) as SdkEncString;
} }
// mac // mac
if (mac != null) { if (mac != null) {
this.encryptedString = (this.encryptedString + "|" + mac) as EncryptedString; this.encryptedString = (this.encryptedString + "|" + mac) as SdkEncString;
} }
this.encryptionType = encType; this.encryptionType = encType;
@@ -73,7 +79,7 @@ export class EncString implements Encrypted {
} }
private initFromEncryptedString(encryptedString: string) { private initFromEncryptedString(encryptedString: string) {
this.encryptedString = encryptedString as EncryptedString; this.encryptedString = encryptedString as SdkEncString;
if (!this.encryptedString) { if (!this.encryptedString) {
return; 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, ClientSettings,
DeviceType as SdkDeviceType, DeviceType as SdkDeviceType,
TokenProvider, TokenProvider,
UnsignedSharedKey,
} from "@bitwarden/sdk-internal"; } from "@bitwarden/sdk-internal";
import { EncryptedOrganizationKeyData } from "../../../admin-console/models/data/encrypted-organization-key.data"; import { EncryptedOrganizationKeyData } from "../../../admin-console/models/data/encrypted-organization-key.data";
@@ -237,7 +238,7 @@ export class DefaultSdkService implements SdkService {
organizationKeys: new Map( organizationKeys: new Map(
Object.entries(orgKeys ?? {}) Object.entries(orgKeys ?? {})
.filter(([_, v]) => v.type === "organization") .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, url: this.url,
size: this.size, size: this.size,
sizeName: this.sizeName, sizeName: this.sizeName,
fileName: this.fileName?.toJSON(), fileName: this.fileName?.toSdk(),
key: this.key?.toJSON(), key: this.key?.toSdk(),
}; };
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -69,7 +69,7 @@ export class AttachmentView implements View {
size: this.size, size: this.size,
sizeName: this.sizeName, sizeName: this.sizeName,
fileName: this.fileName, fileName: this.fileName,
key: this.encryptedKey?.toJSON(), key: this.encryptedKey?.toSdk(),
// TODO: PM-23005 - Temporary field, should be removed when encrypted migration is complete // TODO: PM-23005 - Temporary field, should be removed when encrypted migration is complete
decryptedKey: this.key ? this.key.toBase64() : null, 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(), creationDate: (this.creationDate ?? new Date()).toISOString(),
deletedDate: this.deletedDate?.toISOString(), deletedDate: this.deletedDate?.toISOString(),
reprompt: this.reprompt ?? CipherRepromptType.None, reprompt: this.reprompt ?? CipherRepromptType.None,
key: this.key?.toJSON(), key: this.key?.toSdk(),
// Cipher type specific properties are set in the switch statement below // Cipher type specific properties are set in the switch statement below
// CipherView initializes each with default constructors (undefined values) // CipherView initializes each with default constructors (undefined values)
// The SDK does not expect those undefined values and will throw exceptions // 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 { UserKey } from "@bitwarden/common/types/key";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { Cipher } from "@bitwarden/common/vault/models/domain/cipher"; 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 { KeyService } from "../../abstractions/key.service";
import { UserAsymmetricKeysRegenerationApiService } from "../abstractions/user-asymmetric-key-regeneration-api.service"; import { UserAsymmetricKeysRegenerationApiService } from "../abstractions/user-asymmetric-key-regeneration-api.service";
@@ -28,7 +28,7 @@ function setupVerificationResponse(
) { ) {
const mockKeyPairResponse = { const mockKeyPairResponse = {
userPublicKey: "userPublicKey", userPublicKey: "userPublicKey",
userKeyEncryptedPrivateKey: "userKeyEncryptedPrivateKey", userKeyEncryptedPrivateKey: "userKeyEncryptedPrivateKey" as SdkEncString,
}; };
sdkService.client.crypto sdkService.client.crypto

8
package-lock.json generated
View File

@@ -23,7 +23,7 @@
"@angular/platform-browser": "19.2.14", "@angular/platform-browser": "19.2.14",
"@angular/platform-browser-dynamic": "19.2.14", "@angular/platform-browser-dynamic": "19.2.14",
"@angular/router": "19.2.14", "@angular/router": "19.2.14",
"@bitwarden/sdk-internal": "0.2.0-main.237", "@bitwarden/sdk-internal": "0.2.0-main.239",
"@electron/fuses": "1.8.0", "@electron/fuses": "1.8.0",
"@emotion/css": "11.13.5", "@emotion/css": "11.13.5",
"@koa/multer": "4.0.0", "@koa/multer": "4.0.0",
@@ -4622,9 +4622,9 @@
"link": true "link": true
}, },
"node_modules/@bitwarden/sdk-internal": { "node_modules/@bitwarden/sdk-internal": {
"version": "0.2.0-main.237", "version": "0.2.0-main.239",
"resolved": "https://registry.npmjs.org/@bitwarden/sdk-internal/-/sdk-internal-0.2.0-main.237.tgz", "resolved": "https://registry.npmjs.org/@bitwarden/sdk-internal/-/sdk-internal-0.2.0-main.239.tgz",
"integrity": "sha512-1psCagsmUo2QeIw/xFW/OCfSInl6Gu+LYldbdLuv1z26FurrgmAv8BejDaPRx006BRn0z0hn6TlZtteaZS762w==", "integrity": "sha512-nX1aaoXGWdZVJKLnlewxw3kibgIjukVj/1JD0Dl1OevAVM694MnD/LQTRbyme8rvUxnUhxFjQi6NpwbUJdJPCA==",
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"type-fest": "^4.41.0" "type-fest": "^4.41.0"

View File

@@ -158,7 +158,7 @@
"@angular/platform-browser": "19.2.14", "@angular/platform-browser": "19.2.14",
"@angular/platform-browser-dynamic": "19.2.14", "@angular/platform-browser-dynamic": "19.2.14",
"@angular/router": "19.2.14", "@angular/router": "19.2.14",
"@bitwarden/sdk-internal": "0.2.0-main.237", "@bitwarden/sdk-internal": "0.2.0-main.239",
"@electron/fuses": "1.8.0", "@electron/fuses": "1.8.0",
"@emotion/css": "11.13.5", "@emotion/css": "11.13.5",
"@koa/multer": "4.0.0", "@koa/multer": "4.0.0",