-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Signing keys upgrade #14837
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
quexten
wants to merge
30
commits into
main
Choose a base branch
from
km/signing-upgrade
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+965
โ159
Draft
Signing keys upgrade #14837
Changes from 19 commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
6624d78
Add new encrypt service functions
quexten 6c9fd9a
Undo changes
quexten fbc520b
Cleanup
quexten df18e7b
Merge branch 'main' into km/new-encrypt-service-interface
quexten b2ebf0f
Fix build
quexten c597a55
Fix comments
quexten 69a10b2
Switch encrypt service to use SDK functions
quexten 217af42
Add cose migration on userkey rotation
quexten 77b1cd4
Merge branch 'main' into km/cose-upgrade
quexten a67cccb
Update sdk
quexten 0b87ec6
Set featureflag to default disabled
quexten be966db
Merge branch 'main' into km/cose-upgrade
quexten bc426fc
Add tests
quexten 58203e4
Merge branch 'km/cose-upgrade' of github.com:bitwarden/clients into kโฆ
quexten d8b9698
Merge branch 'main' into km/cose-upgrade
quexten 7b238e8
Update sdk to build 168
quexten fd0602d
Merge branch 'main' into km/cose-upgrade
quexten 54a69aa
Signing keys upgrade
quexten 9945481
Add get other user's keys endpoint
quexten 4c3b640
Use sdk directly to get algorithm
quexten c524175
Cleanup
quexten 43538c2
Add cleanup comment
quexten 8461cad
Undo tsconfig changes
quexten cf8d4be
Implement sdk init with signing key
quexten 3ea1dd1
Undo feature flag changes
quexten 684f961
Clean up sync
quexten f37fb88
Add comments and add backward compatibilty for sync
quexten a04b207
Add more docs
quexten 9128644
Implement clear key
quexten caede2e
Add tests
quexten File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
62 changes: 62 additions & 0 deletions
62
apps/web/src/app/key-management/debug/debug.component.html
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
<ng-container> | ||
<form [formGroup]="formGroup"> | ||
<h1 class="box-header" id="settingsTitle">User Account</h1> | ||
<div class="tw-flex tw-flex-col tw-space-y-3">UserId: {{ userId }}</div> | ||
<h1>User Account Encryption</h1> | ||
<div class="tw-flex tw-flex-col tw-space-y-3"> | ||
<h2>User Symmetric Key</h2> | ||
Type: {{ userKeyType }} <br /> | ||
<input type="text" bitInput formControlName="userKey" placeholder="UserKey" /> | ||
<h2>User Asymmetric Encryption Keys</h2> | ||
Type: {{ privateKeyType }} <br /> | ||
<input type="text" bitInput formControlName="privateKey" placeholder="privateKey" /> | ||
<input type="text" bitInput formControlName="publicKey" placeholder="publicKey" /> | ||
<h2>User Signing Key</h2> | ||
<input type="text" bitInput formControlName="signingKey" placeholder="signingKey" /> | ||
<input type="text" bitInput formControlName="verifyingKey" placeholder="verifyingKey" /> | ||
</div> | ||
|
||
<h1 class="box-header" id="settingsTitle">User Asymmetric Encryption</h1> | ||
Tools to debug the asymmetric encryption PKI. | ||
<div class="tw-flex tw-flex-col tw-space-y-3"> | ||
<h2>User Public Key</h2> | ||
<input type="text" bitInput formControlName="fetchPKIUserId" placeholder="UserId" /> | ||
Result Public Key: {{ otherUserPublicKey }} Verifying Key: | ||
{{ otherUserVerifyingKey }} PublicKeyOwnershipClaim: {{ otherUserPublicKeyOwnershipClaim }} | ||
<button type="button" bitButton buttonType="primary" block (click)="getUserPublicKey()"> | ||
<span> Get Public Key </span> | ||
</button> | ||
</div> | ||
<h1 class="box-header" id="settingsTitle">User Signing</h1> | ||
Tools to debug user signing. | ||
<div class="tw-flex tw-flex-col tw-space-y-3"> | ||
<h2>Public key ownership claim</h2> | ||
Claim | ||
<input | ||
type="text" | ||
bitInput | ||
formControlName="testClaimPublicKeyOwnershipClaim" | ||
placeholder="PublicKeyOwnershipClaim" | ||
/> | ||
PublicKey | ||
<input type="text" bitInput formControlName="testClaimPublicKey" placeholder="PublicKey" /> | ||
VerifKey | ||
<input | ||
type="text" | ||
bitInput | ||
formControlName="testClaimVerifyingKey" | ||
placeholder="VerifyingKey" | ||
/> | ||
Result: {{ testClaimPublicKeyOwnershipResult }} | ||
<button | ||
type="button" | ||
bitButton | ||
buttonType="primary" | ||
block | ||
(click)="verifyPublicKeyOwnershipClaim()" | ||
> | ||
<span> Verify Public Key Ownership Claim </span> | ||
</button> | ||
</div> | ||
</form> | ||
</ng-container> |
110 changes: 110 additions & 0 deletions
110
apps/web/src/app/key-management/debug/debug.component.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import { Component, OnInit } from "@angular/core"; | ||
import { FormBuilder, FormGroup, Validators } from "@angular/forms"; | ||
import { firstValueFrom } from "rxjs"; | ||
|
||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; | ||
import { KeyApiService } from "@bitwarden/common/key-management/keys/services/abstractions/key-api-service.abstraction"; | ||
import { EncryptionType } from "@bitwarden/common/platform/enums"; | ||
import { Utils } from "@bitwarden/common/platform/misc/utils"; | ||
import { KeyService } from "@bitwarden/key-management"; | ||
import { PureCrypto } from "@bitwarden/sdk-internal"; | ||
|
||
import { SharedModule } from "../../shared"; | ||
|
||
// The master key was originally used to encrypt user data, before the user key was introduced. | ||
// This component is used to migrate from the old encryption scheme to the new one. | ||
@Component({ | ||
standalone: true, | ||
imports: [SharedModule], | ||
templateUrl: "debug.component.html", | ||
}) | ||
export class DebugMenu implements OnInit { | ||
userKey: string; | ||
userKeyType: string; | ||
|
||
privateKey: string; | ||
privateKeyType: string; | ||
|
||
userId: string; | ||
|
||
testClaimPublicKeyOwnershipResult: string; | ||
|
||
formGroup: FormGroup = new FormGroup({ | ||
fetchPKIUserId: this.formBuilder.control("", [Validators.required]), | ||
privateKey: this.formBuilder.control("", [Validators.required]), | ||
publicKey: this.formBuilder.control("", [Validators.required]), | ||
userKey: this.formBuilder.control("", [Validators.required]), | ||
signingKey: this.formBuilder.control("", [Validators.required]), | ||
verifyingKey: this.formBuilder.control("", [Validators.required]), | ||
|
||
testClaimVerifyingKey: this.formBuilder.control("", [Validators.required]), | ||
testClaimPublicKey: this.formBuilder.control("", [Validators.required]), | ||
testClaimPublicKeyOwnershipClaim: this.formBuilder.control("", [Validators.required]), | ||
}); | ||
otherUserPublicKey: string | null = null; | ||
otherUserVerifyingKey: string | null = null; | ||
otherUserPublicKeyOwnershipClaim: string | null = null; | ||
|
||
constructor( | ||
private keyService: KeyService, | ||
private accountService: AccountService, | ||
private formBuilder: FormBuilder, | ||
private keyApiService: KeyApiService, | ||
) {} | ||
|
||
async ngOnInit() { | ||
const activeUserId = await firstValueFrom(this.accountService.activeAccount$); | ||
this.userId = activeUserId.id; | ||
const userKey = await firstValueFrom(this.keyService.userKey$(activeUserId.id)); | ||
this.formGroup.get("userKey").setValue(userKey.keyB64); | ||
this.userKeyType = | ||
userKey.inner().type == EncryptionType.AesCbc256_HmacSha256_B64 | ||
? "AES-256-CBC-HMAC-SHA256" | ||
: "COSE"; | ||
|
||
this.privateKey = Utils.fromBufferToB64( | ||
(await firstValueFrom(this.keyService.userPrivateKey$(activeUserId.id))).buffer, | ||
); | ||
this.formGroup.get("privateKey").setValue(this.privateKey); | ||
this.formGroup | ||
.get("publicKey") | ||
.setValue( | ||
Utils.fromBufferToB64( | ||
(await firstValueFrom(this.keyService.userPublicKey$(activeUserId.id))).buffer, | ||
), | ||
); | ||
this.privateKeyType = "RSA"; | ||
|
||
const signingKey = await firstValueFrom(this.keyService.userSigningKey$(activeUserId.id)); | ||
const verifyingKey = Utils.fromBufferToB64( | ||
PureCrypto.verifying_key_for_signing_key(signingKey.inner(), userKey.toEncoded()), | ||
); | ||
this.formGroup.get("signingKey").setValue(signingKey.inner()); | ||
this.formGroup.get("verifyingKey").setValue(verifyingKey); | ||
} | ||
|
||
getUserPublicKey = async () => { | ||
const keys = await this.keyApiService.getUserPublicKeys( | ||
this.formGroup.get("fetchPKIUserId").value, | ||
); | ||
this.otherUserPublicKey = keys.PublicKey; | ||
this.otherUserVerifyingKey = keys.VerifyingKey.toString(); | ||
this.otherUserPublicKeyOwnershipClaim = keys.SignedPublicKeyOwnershipClaim.toString(); | ||
}; | ||
|
||
verifyPublicKeyOwnershipClaim = async () => { | ||
const claim = this.formGroup.get("testClaimPublicKeyOwnershipClaim").value; | ||
const publicKey = this.formGroup.get("testClaimPublicKey").value; | ||
const verifyingKey = this.formGroup.get("testClaimVerifyingKey").value; | ||
try { | ||
const result = PureCrypto.verify_public_key_ownership_claim( | ||
Utils.fromB64ToArray(claim), | ||
Utils.fromB64ToArray(publicKey), | ||
Utils.fromB64ToArray(verifyingKey), | ||
); | ||
this.testClaimPublicKeyOwnershipResult = result ? "Valid" : "Invalid"; | ||
} catch (e) { | ||
this.testClaimPublicKeyOwnershipResult = "Error: " + e; | ||
} | ||
}; | ||
} |
20 changes: 19 additions & 1 deletion
20
apps/web/src/app/key-management/key-rotation/request/account-keys.request.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,28 @@ | ||
import { SigningKeyType } from "@bitwarden/key-management"; | ||
|
||
export class AccountKeysRequest { | ||
// Other keys encrypted by the userkey | ||
userKeyEncryptedAccountPrivateKey: string; | ||
accountPublicKey: string; | ||
signedPublicKeyOwnershipClaim: string | null; | ||
|
||
userKeyEncryptedSigningKey: string | null; | ||
verifyingKey: string | null; | ||
signingKeyType: SigningKeyType | null; | ||
|
||
constructor(userKeyEncryptedAccountPrivateKey: string, accountPublicKey: string) { | ||
constructor( | ||
userKeyEncryptedAccountPrivateKey: string, | ||
accountPublicKey: string, | ||
signedPublicKeyOwnershipClaim: string | null, | ||
userKeyEncryptedSigningKey: string | null, | ||
verifyingKey: string | null, | ||
signingKeyType: SigningKeyType | null, | ||
) { | ||
this.userKeyEncryptedAccountPrivateKey = userKeyEncryptedAccountPrivateKey; | ||
this.accountPublicKey = accountPublicKey; | ||
this.signedPublicKeyOwnershipClaim = signedPublicKeyOwnershipClaim; | ||
this.userKeyEncryptedSigningKey = userKeyEncryptedSigningKey; | ||
this.verifyingKey = verifyingKey; | ||
this.signingKeyType = signingKeyType; | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: This tool seems useful to keep around; it is compile-time enabled in dev-mode only, so there is no i18n or design input needed here.
The main purpose is to make debugging key management issues (getting keys from users, verifying them), and crypto state issues, easy to debug.