mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 08:13:42 +00:00
[EC-598] feat: allow storage of more information
This commit is contained in:
@@ -1,10 +1,14 @@
|
||||
import { BaseResponse } from "../response/base.response";
|
||||
|
||||
export class Fido2KeyApi extends BaseResponse {
|
||||
key: string;
|
||||
keyType: "ECDSA";
|
||||
keyCurve: "P-256";
|
||||
keyValue: string;
|
||||
rpId: string;
|
||||
origin: string;
|
||||
rpName: string;
|
||||
userHandle: string;
|
||||
userName: string;
|
||||
origin: string;
|
||||
|
||||
constructor(data: any = null) {
|
||||
super(data);
|
||||
@@ -12,9 +16,12 @@ export class Fido2KeyApi extends BaseResponse {
|
||||
return;
|
||||
}
|
||||
|
||||
this.key = this.getResponseProperty("Key");
|
||||
this.keyType = this.getResponseProperty("KeyType");
|
||||
this.keyCurve = this.getResponseProperty("KeyCurve");
|
||||
this.keyValue = this.getResponseProperty("keyValue");
|
||||
this.rpId = this.getResponseProperty("RpId");
|
||||
this.origin = this.getResponseProperty("Origin");
|
||||
this.userHandle = this.getResponseProperty("UserHandle");
|
||||
this.userName = this.getResponseProperty("UserName");
|
||||
this.origin = this.getResponseProperty("Origin");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,27 @@
|
||||
import { Fido2KeyApi } from "../api/fido2-key.api";
|
||||
|
||||
export class Fido2KeyData {
|
||||
key: string;
|
||||
keyType: "ECDSA";
|
||||
keyCurve: "P-256";
|
||||
keyValue: string;
|
||||
rpId: string;
|
||||
origin: string;
|
||||
rpName: string;
|
||||
userHandle: string;
|
||||
userName: string;
|
||||
origin: string;
|
||||
|
||||
constructor(data?: Fido2KeyApi) {
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.key = data.key;
|
||||
this.keyType = data.keyType;
|
||||
this.keyCurve = data.keyCurve;
|
||||
this.keyValue = data.keyValue;
|
||||
this.rpId = data.rpId;
|
||||
this.origin = data.origin;
|
||||
this.rpName = data.rpName;
|
||||
this.userHandle = data.userHandle;
|
||||
this.userName = data.userName;
|
||||
this.origin = data.origin;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,14 @@ import { EncString } from "./enc-string";
|
||||
import { SymmetricCryptoKey } from "./symmetric-crypto-key";
|
||||
|
||||
export class Fido2Key extends Domain {
|
||||
key: EncString; // PCKS#8
|
||||
keyType: EncString;
|
||||
keyCurve: EncString;
|
||||
keyValue: EncString;
|
||||
rpId: EncString;
|
||||
origin: EncString;
|
||||
rpName: EncString;
|
||||
userHandle: EncString;
|
||||
// extensions: Record<string, unknown>;
|
||||
userName: EncString;
|
||||
origin: EncString;
|
||||
|
||||
constructor(obj?: Fido2KeyData) {
|
||||
super();
|
||||
@@ -24,10 +27,14 @@ export class Fido2Key extends Domain {
|
||||
this,
|
||||
obj,
|
||||
{
|
||||
key: null,
|
||||
keyType: null,
|
||||
keyCurve: null,
|
||||
keyValue: null,
|
||||
rpId: null,
|
||||
origin: null,
|
||||
rpName: null,
|
||||
userHandle: null,
|
||||
userName: null,
|
||||
origin: null,
|
||||
},
|
||||
[]
|
||||
);
|
||||
@@ -37,10 +44,14 @@ export class Fido2Key extends Domain {
|
||||
return this.decryptObj(
|
||||
new Fido2KeyView(),
|
||||
{
|
||||
key: null,
|
||||
keyType: null,
|
||||
keyCurve: null,
|
||||
keyValue: null,
|
||||
rpId: null,
|
||||
origin: null,
|
||||
rpName: null,
|
||||
userHandle: null,
|
||||
userName: null,
|
||||
origin: null,
|
||||
},
|
||||
orgId,
|
||||
encKey
|
||||
@@ -50,10 +61,14 @@ export class Fido2Key extends Domain {
|
||||
toFido2KeyData(): Fido2KeyData {
|
||||
const i = new Fido2KeyData();
|
||||
this.buildDataModel(this, i, {
|
||||
key: null,
|
||||
keyType: null,
|
||||
keyCurve: null,
|
||||
keyValue: null,
|
||||
rpId: null,
|
||||
origin: null,
|
||||
rpName: null,
|
||||
userHandle: null,
|
||||
userName: null,
|
||||
origin: null,
|
||||
});
|
||||
return i;
|
||||
}
|
||||
@@ -63,16 +78,24 @@ export class Fido2Key extends Domain {
|
||||
return null;
|
||||
}
|
||||
|
||||
const key = EncString.fromJSON(obj.key);
|
||||
const keyType = EncString.fromJSON(obj.keyType);
|
||||
const keyCurve = EncString.fromJSON(obj.keyCurve);
|
||||
const keyValue = EncString.fromJSON(obj.keyValue);
|
||||
const rpId = EncString.fromJSON(obj.rpId);
|
||||
const origin = EncString.fromJSON(obj.origin);
|
||||
const rpName = EncString.fromJSON(obj.rpName);
|
||||
const userHandle = EncString.fromJSON(obj.userHandle);
|
||||
const userName = EncString.fromJSON(obj.userName);
|
||||
const origin = EncString.fromJSON(obj.origin);
|
||||
|
||||
return Object.assign(new Fido2Key(), obj, {
|
||||
key,
|
||||
keyType,
|
||||
keyCurve,
|
||||
keyValue,
|
||||
rpId,
|
||||
origin,
|
||||
rpName,
|
||||
userHandle,
|
||||
userName,
|
||||
origin,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,14 +125,24 @@ export class CipherRequest {
|
||||
break;
|
||||
case CipherType.Fido2Key:
|
||||
this.fido2Key = new Fido2KeyApi();
|
||||
this.fido2Key.key =
|
||||
cipher.fido2Key.key != null ? cipher.fido2Key.key.encryptedString : null;
|
||||
this.fido2Key.origin =
|
||||
cipher.fido2Key.origin != null ? cipher.fido2Key.origin.encryptedString : null;
|
||||
this.fido2Key.keyType =
|
||||
cipher.fido2Key.keyType != null
|
||||
? (cipher.fido2Key.keyType.encryptedString as "ECDSA")
|
||||
: null;
|
||||
this.fido2Key.keyCurve =
|
||||
cipher.fido2Key.keyCurve != null
|
||||
? (cipher.fido2Key.keyCurve.encryptedString as "P-256")
|
||||
: null;
|
||||
this.fido2Key.keyValue =
|
||||
cipher.fido2Key.keyValue != null ? cipher.fido2Key.keyValue.encryptedString : null;
|
||||
this.fido2Key.rpId =
|
||||
cipher.fido2Key.rpId != null ? cipher.fido2Key.rpId.encryptedString : null;
|
||||
this.fido2Key.userHandle =
|
||||
cipher.fido2Key.userHandle != null ? cipher.fido2Key.userHandle.encryptedString : null;
|
||||
this.fido2Key.userName =
|
||||
cipher.fido2Key.userName != null ? cipher.fido2Key.userName.encryptedString : null;
|
||||
this.fido2Key.origin =
|
||||
cipher.fido2Key.origin != null ? cipher.fido2Key.origin.encryptedString : null;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import { ItemView } from "./item.view";
|
||||
|
||||
export class Fido2KeyView extends ItemView {
|
||||
key: string;
|
||||
keyType: "ECDSA";
|
||||
keyCurve: "P-256";
|
||||
keyValue: string;
|
||||
rpId: string;
|
||||
origin: string;
|
||||
rpName: string;
|
||||
userHandle: string;
|
||||
userName: string;
|
||||
origin: string;
|
||||
|
||||
get subTitle(): string {
|
||||
return null;
|
||||
|
||||
@@ -25,10 +25,14 @@ const STANDARD_ATTESTATION_FORMAT = "packed";
|
||||
|
||||
interface BitCredential {
|
||||
credentialId: CredentialId;
|
||||
privateKey: CryptoKey;
|
||||
keyType: "ECDSA";
|
||||
keyCurve: "P-256";
|
||||
keyValue: CryptoKey;
|
||||
rpId: string;
|
||||
origin: string;
|
||||
rpName: string;
|
||||
userHandle: Uint8Array;
|
||||
userName: string;
|
||||
origin: string;
|
||||
}
|
||||
|
||||
const KeyUsages: KeyUsage[] = ["sign"];
|
||||
@@ -68,10 +72,14 @@ export class Fido2Service implements Fido2ServiceAbstraction {
|
||||
);
|
||||
|
||||
const credentialId = await this.saveCredential({
|
||||
privateKey: keyPair.privateKey,
|
||||
keyType: "ECDSA",
|
||||
keyCurve: "P-256",
|
||||
keyValue: keyPair.privateKey,
|
||||
origin: params.origin,
|
||||
rpId: params.rp.id,
|
||||
rpName: params.rp.name,
|
||||
userHandle: Fido2Utils.stringToBuffer(params.user.id),
|
||||
userName: params.user.displayName,
|
||||
});
|
||||
|
||||
const authData = await generateAuthData({
|
||||
@@ -163,7 +171,7 @@ export class Fido2Service implements Fido2ServiceAbstraction {
|
||||
const signature = await generateSignature({
|
||||
authData,
|
||||
clientData,
|
||||
privateKey: credential.privateKey,
|
||||
privateKey: credential.keyValue,
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -200,16 +208,22 @@ export class Fido2Service implements Fido2ServiceAbstraction {
|
||||
private async saveCredential(
|
||||
credential: Omit<BitCredential, "credentialId">
|
||||
): Promise<CredentialId> {
|
||||
const pcks8Key = await crypto.subtle.exportKey("pkcs8", credential.privateKey);
|
||||
const pcks8Key = await crypto.subtle.exportKey("pkcs8", credential.keyValue);
|
||||
|
||||
const view = new CipherView();
|
||||
view.type = CipherType.Fido2Key;
|
||||
view.name = credential.origin;
|
||||
view.fido2Key = new Fido2KeyView();
|
||||
view.fido2Key.key = Fido2Utils.bufferToString(pcks8Key);
|
||||
view.fido2Key.origin = credential.origin;
|
||||
|
||||
view.fido2Key.keyType = credential.keyType;
|
||||
view.fido2Key.keyCurve = credential.keyCurve;
|
||||
view.fido2Key.keyValue = Fido2Utils.bufferToString(pcks8Key);
|
||||
view.fido2Key.rpId = credential.rpId;
|
||||
view.fido2Key.rpName = credential.rpName;
|
||||
view.fido2Key.userHandle = Fido2Utils.bufferToString(credential.userHandle);
|
||||
view.fido2Key.userName = credential.userName;
|
||||
view.fido2Key.origin = credential.origin;
|
||||
|
||||
const cipher = await this.cipherService.encrypt(view);
|
||||
await this.cipherService.createWithServer(cipher);
|
||||
@@ -238,13 +252,13 @@ interface AuthDataParams {
|
||||
}
|
||||
|
||||
async function mapCipherViewToBitCredential(cipherView: CipherView): Promise<BitCredential> {
|
||||
const keyBuffer = Fido2Utils.stringToBuffer(cipherView.fido2Key.key);
|
||||
const keyBuffer = Fido2Utils.stringToBuffer(cipherView.fido2Key.keyValue);
|
||||
const privateKey = await crypto.subtle.importKey(
|
||||
"pkcs8",
|
||||
keyBuffer,
|
||||
{
|
||||
name: "ECDSA",
|
||||
namedCurve: "P-256",
|
||||
name: cipherView.fido2Key.keyType,
|
||||
namedCurve: cipherView.fido2Key.keyCurve,
|
||||
},
|
||||
true,
|
||||
KeyUsages
|
||||
@@ -252,10 +266,14 @@ async function mapCipherViewToBitCredential(cipherView: CipherView): Promise<Bit
|
||||
|
||||
return {
|
||||
credentialId: new CredentialId(cipherView.id),
|
||||
privateKey,
|
||||
origin: cipherView.fido2Key.origin,
|
||||
keyType: cipherView.fido2Key.keyType,
|
||||
keyCurve: cipherView.fido2Key.keyCurve,
|
||||
keyValue: privateKey,
|
||||
rpId: cipherView.fido2Key.rpId,
|
||||
rpName: cipherView.fido2Key.rpName,
|
||||
userHandle: Fido2Utils.stringToBuffer(cipherView.fido2Key.userHandle),
|
||||
userName: cipherView.fido2Key.userName,
|
||||
origin: cipherView.fido2Key.origin,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user