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