diff --git a/.github/workflows/brew-bump-cli.yml b/.github/workflows/brew-bump-cli.yml index cae9db880e..d45e85ea15 100644 --- a/.github/workflows/brew-bump-cli.yml +++ b/.github/workflows/brew-bump-cli.yml @@ -23,7 +23,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "brew-bump-workflow-pat" diff --git a/.github/workflows/brew-bump-desktop.yml b/.github/workflows/brew-bump-desktop.yml index 43b24f4553..b7bb726722 100644 --- a/.github/workflows/brew-bump-desktop.yml +++ b/.github/workflows/brew-bump-desktop.yml @@ -23,7 +23,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "brew-bump-workflow-pat" diff --git a/.github/workflows/build-browser.yml b/.github/workflows/build-browser.yml index 89fa40a53f..4e9a15fbfa 100644 --- a/.github/workflows/build-browser.yml +++ b/.github/workflows/build-browser.yml @@ -354,7 +354,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "crowdin-api-token" @@ -416,7 +416,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets if: failure() - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "devops-alerts-slack-webhook-url" diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index bc33a4ccd0..c047133e1c 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -404,7 +404,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets if: failure() - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "devops-alerts-slack-webhook-url" diff --git a/.github/workflows/build-desktop.yml b/.github/workflows/build-desktop.yml index b5da80f7f7..d00551ca36 100644 --- a/.github/workflows/build-desktop.yml +++ b/.github/workflows/build-desktop.yml @@ -277,7 +277,7 @@ jobs: node-gyp install $(node -v) - name: Install AST - uses: bitwarden/gh-actions/install-ast@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/install-ast@37ffa14164a7308bc273829edfe75c97cd562375 - name: Set up environmentF run: choco install checksum --no-progress @@ -302,7 +302,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "code-signing-vault-url, @@ -1190,7 +1190,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "crowdin-api-token" @@ -1269,7 +1269,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets if: failure() - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "devops-alerts-slack-webhook-url" diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml index fd4a700131..4a7918a81b 100644 --- a/.github/workflows/build-web.yml +++ b/.github/workflows/build-web.yml @@ -235,7 +235,7 @@ jobs: - name: Retrieve github PAT secrets id: retrieve-secret-pat - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "github-pat-bitwarden-devops-bot-repo-scope" @@ -243,7 +243,7 @@ jobs: - name: Setup DCT if: ${{ env.is_publish_branch == 'true' }} id: setup-dct - uses: bitwarden/gh-actions/setup-docker-trust@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/setup-docker-trust@37ffa14164a7308bc273829edfe75c97cd562375 with: azure-creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} azure-keyvault-name: "bitwarden-ci" @@ -291,7 +291,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "crowdin-api-token" @@ -352,7 +352,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets if: failure() - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "devops-alerts-slack-webhook-url" diff --git a/.github/workflows/crowdin-pull.yml b/.github/workflows/crowdin-pull.yml index f058c71203..44c753582c 100644 --- a/.github/workflows/crowdin-pull.yml +++ b/.github/workflows/crowdin-pull.yml @@ -32,13 +32,13 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase" - name: Download translations - uses: bitwarden/gh-actions/crowdin@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/crowdin@37ffa14164a7308bc273829edfe75c97cd562375 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} diff --git a/.github/workflows/deploy-eu-prod-web.yml b/.github/workflows/deploy-eu-prod-web.yml index 282cea9663..55cc10825b 100644 --- a/.github/workflows/deploy-eu-prod-web.yml +++ b/.github/workflows/deploy-eu-prod-web.yml @@ -1,8 +1,14 @@ --- -name: Deploy Web - EU Prod +name: Deploy Web to EU-PRD Cloud on: workflow_dispatch: + inputs: + tag: + description: "Branch name to deploy (examples: 'master', 'feature/sm')" + required: true + type: string + default: master jobs: azure-deploy: @@ -18,18 +24,18 @@ jobs: - name: Retrieve Storage Account connection string id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: webvault-westeurope-prod secrets: "sa-bitwarden-web-vault-dev-key-temp" - name: Download latest cloud asset - uses: bitwarden/gh-actions/download-artifacts@850faad0cf6c02a8c0dc46eddde2363fbd6c373a + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-web.yml path: apps/web workflow_conclusion: success - branch: ${{ github.ref_name }} + branch: ${{ github.event.inputs.tag }} artifacts: ${{ env._WEB_ARTIFACT }} - name: Unzip build asset diff --git a/.github/workflows/deploy-non-prod-web.yml b/.github/workflows/deploy-non-prod-web.yml index e0b6977a78..d041369d84 100644 --- a/.github/workflows/deploy-non-prod-web.yml +++ b/.github/workflows/deploy-non-prod-web.yml @@ -64,7 +64,7 @@ jobs: uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - name: Download latest cloud asset - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-web.yml path: apps/web diff --git a/.github/workflows/release-browser.yml b/.github/workflows/release-browser.yml index c9f9b20c62..1aebc9722c 100644 --- a/.github/workflows/release-browser.yml +++ b/.github/workflows/release-browser.yml @@ -41,7 +41,7 @@ jobs: - name: Check Release Version id: version - uses: bitwarden/gh-actions/release-version-check@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/release-version-check@37ffa14164a7308bc273829edfe75c97cd562375 with: release-type: ${{ github.event.inputs.release_type }} project-type: ts @@ -103,7 +103,7 @@ jobs: - name: Download latest Release build artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-browser.yml workflow_conclusion: success @@ -116,7 +116,7 @@ jobs: - name: Dry Run - Download latest master build artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-browser.yml workflow_conclusion: success diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index 406b345c2f..76b4915dbd 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -57,7 +57,7 @@ jobs: - name: Check Release Version id: version - uses: bitwarden/gh-actions/release-version-check@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/release-version-check@37ffa14164a7308bc273829edfe75c97cd562375 with: release-type: ${{ github.event.inputs.release_type }} project-type: ts @@ -78,7 +78,7 @@ jobs: - name: Download all Release artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-cli.yml path: apps/cli @@ -87,7 +87,7 @@ jobs: - name: Dry Run - Download all artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-cli.yml path: apps/cli @@ -150,7 +150,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "snapcraft-store-token" @@ -162,7 +162,7 @@ jobs: - name: Download artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-cli.yml path: apps/cli @@ -172,7 +172,7 @@ jobs: - name: Dry Run - Download artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-cli.yml path: apps/cli @@ -204,7 +204,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "cli-choco-api-key" @@ -220,7 +220,7 @@ jobs: - name: Download artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-cli.yml path: apps/cli/dist @@ -230,7 +230,7 @@ jobs: - name: Dry Run - Download artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-cli.yml path: apps/cli/dist @@ -263,14 +263,14 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "npm-api-key" - name: Download artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-cli.yml path: apps/cli/build @@ -280,7 +280,7 @@ jobs: - name: Dry Run - Download artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-cli.yml path: apps/cli/build diff --git a/.github/workflows/release-desktop-beta.yml b/.github/workflows/release-desktop-beta.yml index f9a5e4d5ad..87f188e9b1 100644 --- a/.github/workflows/release-desktop-beta.yml +++ b/.github/workflows/release-desktop-beta.yml @@ -47,7 +47,7 @@ jobs: - name: Check Release Version id: version - uses: bitwarden/gh-actions/release-version-check@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/release-version-check@37ffa14164a7308bc273829edfe75c97cd562375 with: release-type: 'Initial Release' project-type: ts @@ -231,7 +231,7 @@ jobs: node-gyp install $(node -v) - name: Install AST - uses: bitwarden/gh-actions/install-ast@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/install-ast@37ffa14164a7308bc273829edfe75c97cd562375 - name: Set up environment run: choco install checksum --no-progress @@ -249,7 +249,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "code-signing-vault-url, @@ -932,7 +932,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "aws-electron-access-id, diff --git a/.github/workflows/release-desktop.yml b/.github/workflows/release-desktop.yml index 796b72909a..4ad9083683 100644 --- a/.github/workflows/release-desktop.yml +++ b/.github/workflows/release-desktop.yml @@ -67,7 +67,7 @@ jobs: - name: Check Release Version id: version - uses: bitwarden/gh-actions/release-version-check@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/release-version-check@37ffa14164a7308bc273829edfe75c97cd562375 with: release-type: ${{ github.event.inputs.release_type }} project-type: ts @@ -110,7 +110,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "aws-electron-access-id, @@ -123,7 +123,7 @@ jobs: - name: Download all artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-desktop.yml workflow_conclusion: success @@ -132,7 +132,7 @@ jobs: - name: Dry Run - Download all artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-desktop.yml workflow_conclusion: success @@ -185,7 +185,7 @@ jobs: --endpoint-url https://${CF_ACCOUNT}.r2.cloudflarestorage.com - name: Get checksum files - uses: bitwarden/gh-actions/get-checksum@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-checksum@37ffa14164a7308bc273829edfe75c97cd562375 with: packages_dir: "apps/desktop/artifacts" file_path: "apps/desktop/artifacts/sha256-checksums.txt" @@ -263,7 +263,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "snapcraft-store-token" @@ -279,7 +279,7 @@ jobs: - name: Download Snap artifact if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-desktop.yml workflow_conclusion: success @@ -289,7 +289,7 @@ jobs: - name: Dry Run - Download Snap artifact if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-desktop.yml workflow_conclusion: success @@ -329,7 +329,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "cli-choco-api-key" @@ -347,7 +347,7 @@ jobs: - name: Download choco artifact if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-desktop.yml workflow_conclusion: success @@ -357,7 +357,7 @@ jobs: - name: Dry Run - Download choco artifact if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-desktop.yml workflow_conclusion: success diff --git a/.github/workflows/release-qa-web.yml b/.github/workflows/release-qa-web.yml index 60f38e9d32..044099052b 100644 --- a/.github/workflows/release-qa-web.yml +++ b/.github/workflows/release-qa-web.yml @@ -23,7 +23,7 @@ jobs: uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - name: Download latest cloud asset - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-web.yml path: apps/web diff --git a/.github/workflows/release-web.yml b/.github/workflows/release-web.yml index 1ba24a8369..391f0f8715 100644 --- a/.github/workflows/release-web.yml +++ b/.github/workflows/release-web.yml @@ -38,7 +38,7 @@ jobs: - name: Check Release Version id: version - uses: bitwarden/gh-actions/release-version-check@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/release-version-check@37ffa14164a7308bc273829edfe75c97cd562375 with: release-type: ${{ github.event.inputs.release_type }} project-type: ts @@ -70,7 +70,7 @@ jobs: ########## DockerHub ########## - name: Setup DCT id: setup-dct - uses: bitwarden/gh-actions/setup-docker-trust@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/setup-docker-trust@37ffa14164a7308bc273829edfe75c97cd562375 with: azure-creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} azure-keyvault-name: "bitwarden-ci" @@ -156,7 +156,7 @@ jobs: - name: Retrieve bot secrets id: retrieve-bot-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: bitwarden-ci secrets: "github-pat-bitwarden-devops-bot-repo-scope" @@ -170,7 +170,7 @@ jobs: - name: Download latest cloud asset if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-web.yml path: assets @@ -180,7 +180,7 @@ jobs: - name: Dry Run - Download latest cloud asset if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-web.yml path: assets @@ -253,7 +253,7 @@ jobs: - name: Download latest build artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-web.yml path: apps/web/artifacts @@ -264,7 +264,7 @@ jobs: - name: Dry Run - Download latest build artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375 with: workflow: build-web.yml path: apps/web/artifacts diff --git a/.github/workflows/staged-rollout-desktop.yml b/.github/workflows/staged-rollout-desktop.yml index 7221028df2..a21413dcc6 100644 --- a/.github/workflows/staged-rollout-desktop.yml +++ b/.github/workflows/staged-rollout-desktop.yml @@ -26,7 +26,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "aws-electron-access-id, diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index cebe740b9d..1c3e2c7064 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -49,7 +49,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375 with: keyvault: "bitwarden-ci" secrets: "github-gpg-private-key, github-gpg-private-key-passphrase" @@ -86,14 +86,14 @@ jobs: - name: Bump Browser Version - Manifest if: ${{ github.event.inputs.client == 'Browser' || github.event.inputs.client == 'All' }} - uses: bitwarden/gh-actions/version-bump@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/version-bump@37ffa14164a7308bc273829edfe75c97cd562375 with: version: ${{ github.event.inputs.version_number }} file_path: "apps/browser/src/manifest.json" - name: Bump Browser Version - Manifest v3 if: ${{ github.event.inputs.client == 'Browser' || github.event.inputs.client == 'All' }} - uses: bitwarden/gh-actions/version-bump@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/version-bump@37ffa14164a7308bc273829edfe75c97cd562375 with: version: ${{ github.event.inputs.version_number }} file_path: "apps/browser/src/manifest.v3.json" diff --git a/.github/workflows/workflow-linter.yml b/.github/workflows/workflow-linter.yml index 20525879d5..9fe167ad72 100644 --- a/.github/workflows/workflow-linter.yml +++ b/.github/workflows/workflow-linter.yml @@ -8,4 +8,4 @@ on: jobs: call-workflow: - uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@72594be690a4e7bfa87b1402b2aedc75acdbff12 + uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@37ffa14164a7308bc273829edfe75c97cd562375 diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json index 40b929ed15..498f41bde6 100644 --- a/apps/browser/src/_locales/en/messages.json +++ b/apps/browser/src/_locales/en/messages.json @@ -1599,6 +1599,12 @@ "biometricsNotSupportedDesc": { "message": "Browser biometrics is not supported on this device." }, + "biometricsFailedTitle": { + "message": "Biometrics failed" + }, + "biometricsFailedDesc": { + "message": "Biometrics cannot be completed, consider using a master password or logging out. If this persists, please contact Bitwarden support." + }, "nativeMessaginPermissionErrorTitle": { "message": "Permission not provided" }, diff --git a/apps/browser/src/background/nativeMessaging.background.ts b/apps/browser/src/background/nativeMessaging.background.ts index 90c114a865..25c690ad7f 100644 --- a/apps/browser/src/background/nativeMessaging.background.ts +++ b/apps/browser/src/background/nativeMessaging.background.ts @@ -10,7 +10,11 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { EncString } from "@bitwarden/common/platform/models/domain/enc-string"; -import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; +import { + MasterKey, + SymmetricCryptoKey, + UserKey, +} from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { BrowserApi } from "../platform/browser/browser-api"; @@ -42,6 +46,7 @@ type ReceiveMessage = { // Unlock key keyB64?: string; + userKeyB64?: string; }; type ReceiveMessageOuter = { @@ -320,16 +325,54 @@ export class NativeMessagingBackground { } if (message.response === "unlocked") { - await this.cryptoService.setKey( - new SymmetricCryptoKey(Utils.fromB64ToArray(message.keyB64).buffer) - ); + try { + if (message.userKeyB64) { + const userKey = new SymmetricCryptoKey( + Utils.fromB64ToArray(message.userKeyB64).buffer + ) as UserKey; + await this.cryptoService.setUserKey(userKey); + } else if (message.keyB64) { + // backwards compatibility + let encUserKey = await this.stateService.getEncryptedCryptoSymmetricKey(); + encUserKey ||= await this.stateService.getUserKeyMasterKey(); + if (!encUserKey) { + throw new Error("No encrypted user key found"); + } + const masterKey = new SymmetricCryptoKey( + Utils.fromB64ToArray(message.keyB64).buffer + ) as MasterKey; + const userKey = await this.cryptoService.decryptUserKeyWithMasterKey( + masterKey, + new EncString(encUserKey) + ); + await this.cryptoService.setMasterKey(masterKey); + await this.cryptoService.setUserKey(userKey); + } else { + throw new Error("No key received"); + } + } catch (e) { + this.logService.error("Unable to set key: " + e); + this.messagingService.send("showDialog", { + title: { key: "biometricsFailedTitle" }, + content: { key: "biometricsFailedDesc" }, + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + type: "danger", + }); + + // Exit early + if (this.resolver) { + this.resolver(message); + } + return; + } // Verify key is correct by attempting to decrypt a secret try { await this.cryptoService.getFingerprint(await this.stateService.getUserId()); } catch (e) { this.logService.error("Unable to verify key: " + e); - await this.cryptoService.clearKey(); + await this.cryptoService.clearKeys(); this.showWrongUserDialog(); // Exit early diff --git a/apps/browser/src/platform/services/browser-crypto.service.ts b/apps/browser/src/platform/services/browser-crypto.service.ts index 1018c270cb..8ade200ec4 100644 --- a/apps/browser/src/platform/services/browser-crypto.service.ts +++ b/apps/browser/src/platform/services/browser-crypto.service.ts @@ -1,13 +1,23 @@ import { KeySuffixOptions } from "@bitwarden/common/enums"; +import { Utils } from "@bitwarden/common/platform/misc/utils"; +import { + SymmetricCryptoKey, + UserKey, +} from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { CryptoService } from "@bitwarden/common/platform/services/crypto.service"; export class BrowserCryptoService extends CryptoService { - protected async retrieveKeyFromStorage(keySuffix: KeySuffixOptions) { - if (keySuffix === "biometric") { + protected override async retrieveUserKeyFromStorage( + keySuffix: KeySuffixOptions + ): Promise { + if (keySuffix === KeySuffixOptions.Biometric) { await this.platformUtilService.authenticateBiometric(); - return (await this.getKey())?.keyB64; + const userKey = await this.getUserKeyFromMemory(); + if (userKey) { + return new SymmetricCryptoKey(Utils.fromB64ToArray(userKey.keyB64).buffer) as UserKey; + } } - return await super.retrieveKeyFromStorage(keySuffix); + return await super.retrieveUserKeyFromStorage(keySuffix); } } diff --git a/apps/browser/src/platform/services/browser-state.service.ts b/apps/browser/src/platform/services/browser-state.service.ts index 37f50d6dc7..9d6b770457 100644 --- a/apps/browser/src/platform/services/browser-state.service.ts +++ b/apps/browser/src/platform/services/browser-state.service.ts @@ -1,5 +1,12 @@ -import { BehaviorSubject } from "rxjs"; +import { BehaviorSubject, Observable } from "rxjs"; +import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; +import { StateMigrationService } from "@bitwarden/common/platform/abstractions/state-migration.service"; +import { + AbstractStorageService, + AbstractMemoryStorageService, +} from "@bitwarden/common/platform/abstractions/storage.service"; +import { StateFactory } from "@bitwarden/common/platform/factories/state-factory"; import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state"; import { StorageOptions } from "@bitwarden/common/platform/models/domain/storage-options"; import { StateService as BaseStateService } from "@bitwarden/common/platform/services/state.service"; @@ -26,14 +33,36 @@ export class BrowserStateService protected activeAccountSubject: BehaviorSubject; @sessionSync({ initializer: (b: boolean) => b }) protected activeAccountUnlockedSubject: BehaviorSubject; - @sessionSync({ - initializer: Account.fromJSON as any, // TODO: Remove this any when all any types are removed from Account - initializeAs: "record", - }) - protected accountDiskCache: BehaviorSubject>; protected accountDeserializer = Account.fromJSON; + constructor( + storageService: AbstractStorageService, + secureStorageService: AbstractStorageService, + memoryStorageService: AbstractMemoryStorageService, + logService: LogService, + stateMigrationService: StateMigrationService, + stateFactory: StateFactory, + useAccountCache = true, + accountCache: Observable> = null + ) { + super( + storageService, + secureStorageService, + memoryStorageService, + logService, + stateMigrationService, + stateFactory, + useAccountCache + ); + + // Hack to allow shared disk cache between contexts on browser + // TODO: Remove when services are consolidated to a single context + if (useAccountCache && accountCache) { + accountCache.subscribe(this.accountDiskCacheSubject); + } + } + async addAccount(account: Account) { // Apply browser overrides to default account values account = new Account(account); diff --git a/apps/browser/src/popup/services/services.module.ts b/apps/browser/src/popup/services/services.module.ts index 1b3244064b..e71bdd1c08 100644 --- a/apps/browser/src/popup/services/services.module.ts +++ b/apps/browser/src/popup/services/services.module.ts @@ -440,13 +440,20 @@ function getBgService(service: keyof MainBackground) { logService: LogServiceAbstraction, stateMigrationService: StateMigrationService ) => { + // hack to share the disk cache between the two contexts. + // TODO: we need to figure out a better way of sharing/syncing + // the disk cache + const bgStateService = getBgService("stateService"); + const bgDiskCache = bgStateService().accountDiskCache$; return new BrowserStateService( storageService, secureStorageService, memoryStorageService, logService, stateMigrationService, - new StateFactory(GlobalState, Account) + new StateFactory(GlobalState, Account), + true, + bgDiskCache ); }, deps: [ diff --git a/apps/browser/src/safari/safari/SafariWebExtensionHandler.swift b/apps/browser/src/safari/safari/SafariWebExtensionHandler.swift index 80ea214b4b..b0688e3beb 100644 --- a/apps/browser/src/safari/safari/SafariWebExtensionHandler.swift +++ b/apps/browser/src/safari/safari/SafariWebExtensionHandler.swift @@ -19,11 +19,11 @@ class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { os_log(.default, "Received message from browser.runtime.sendNativeMessage: %@", message as! CVarArg) let response = NSExtensionItem() - + guard let command = message?["command"] as? String else { return } - + switch (command) { case "readFromClipboard": let pasteboard = NSPasteboard.general @@ -59,12 +59,12 @@ class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { guard let data = blobData else { return } - + let panel = NSSavePanel() panel.canCreateDirectories = true panel.nameFieldStringValue = dlMsg.fileName let response = panel.runModal(); - + if response == NSApplication.ModalResponse.OK { if let url = panel.url { do { @@ -87,12 +87,12 @@ class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { } return case "biometricUnlock": - + var error: NSError? let laContext = LAContext() - + laContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) - + if let e = error, e.code != kLAErrorBiometryLockout { response.userInfo = [ SFExtensionMessageKey: [ @@ -123,26 +123,26 @@ class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { guard let userId = message?["userId"] as? String else { return } - let passwordName = userId + "_masterkey_biometric" + let passwordName = userId + "_user_biometric" var passwordLength: UInt32 = 0 var passwordPtr: UnsafeMutableRawPointer? = nil - + var status = SecKeychainFindGenericPassword(nil, UInt32(ServiceNameBiometric.utf8.count), ServiceNameBiometric, UInt32(passwordName.utf8.count), passwordName, &passwordLength, &passwordPtr, nil) if status != errSecSuccess { let fallbackName = "key" status = SecKeychainFindGenericPassword(nil, UInt32(ServiceNameBiometric.utf8.count), ServiceNameBiometric, UInt32(fallbackName.utf8.count), fallbackName, &passwordLength, &passwordPtr, nil) } - + if status == errSecSuccess { let result = NSString(bytes: passwordPtr!, length: Int(passwordLength), encoding: String.Encoding.utf8.rawValue) as String? SecKeychainItemFreeContent(nil, passwordPtr) - + response.userInfo = [ SFExtensionMessageKey: [ "message": [ "command": "biometricUnlock", "response": "unlocked", "timestamp": Int64(NSDate().timeIntervalSince1970 * 1000), - "keyB64": result!.replacingOccurrences(of: "\"", with: ""), + "userKeyB64": result!.replacingOccurrences(of: "\"", with: ""), ], ]] } else { @@ -157,10 +157,10 @@ class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { ] } } - + context.completeRequest(returningItems: [response], completionHandler: nil) } - + return default: return diff --git a/apps/cli/src/auth/commands/login.command.ts b/apps/cli/src/auth/commands/login.command.ts index fe9284e2e8..0f53d9795c 100644 --- a/apps/cli/src/auth/commands/login.command.ts +++ b/apps/cli/src/auth/commands/login.command.ts @@ -406,7 +406,7 @@ export class LoginCommand { } try { - const { newPasswordHash, newEncKey, hint } = await this.collectNewMasterPasswordDetails( + const { newPasswordHash, newUserKey, hint } = await this.collectNewMasterPasswordDetails( "Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now." ); @@ -414,7 +414,7 @@ export class LoginCommand { request.masterPasswordHash = await this.cryptoService.hashPassword(currentPassword, null); request.masterPasswordHint = hint; request.newMasterPasswordHash = newPasswordHash; - request.key = newEncKey[1].encryptedString; + request.key = newUserKey[1].encryptedString; await this.apiService.postPassword(request); @@ -444,12 +444,12 @@ export class LoginCommand { } try { - const { newPasswordHash, newEncKey, hint } = await this.collectNewMasterPasswordDetails( + const { newPasswordHash, newUserKey, hint } = await this.collectNewMasterPasswordDetails( "An organization administrator recently changed your master password. In order to access the vault, you must update your master password now." ); const request = new UpdateTempPasswordRequest(); - request.key = newEncKey[1].encryptedString; + request.key = newUserKey[1].encryptedString; request.newMasterPasswordHash = newPasswordHash; request.masterPasswordHint = hint; @@ -467,8 +467,8 @@ export class LoginCommand { /** * Collect new master password and hint from the CLI. The collected password - * is validated against any applicable master password policies and a new encryption - * key is generated + * is validated against any applicable master password policies, a new master + * key is generated, and we use it to re-encrypt the user key * @param prompt - Message that is displayed during the initial prompt * @param error */ @@ -477,7 +477,7 @@ export class LoginCommand { error?: string ): Promise<{ newPasswordHash: string; - newEncKey: [SymmetricCryptoKey, EncString]; + newUserKey: [SymmetricCryptoKey, EncString]; hint?: string; }> { if (this.email == null || this.email === "undefined") { @@ -559,21 +559,24 @@ export class LoginCommand { const kdfConfig = await this.stateService.getKdfConfig(); // Create new key and hash new password - const newKey = await this.cryptoService.makeKey( + const newMasterKey = await this.cryptoService.makeMasterKey( masterPassword, this.email.trim().toLowerCase(), kdf, kdfConfig ); - const newPasswordHash = await this.cryptoService.hashPassword(masterPassword, newKey); + const newPasswordHash = await this.cryptoService.hashPassword(masterPassword, newMasterKey); - // Grab user's current enc key - const userEncKey = await this.cryptoService.getEncKey(); + // Grab user key + const userKey = await this.cryptoService.getUserKeyFromMemory(); + if (!userKey) { + throw new Error("User key not found."); + } - // Create new encKey for the User - const newEncKey = await this.cryptoService.remakeEncKey(newKey, userEncKey); + // Re-encrypt user key with new master key + const newUserKey = await this.cryptoService.encryptUserKeyWithMasterKey(newMasterKey, userKey); - return { newPasswordHash, newEncKey, hint: masterPasswordHint }; + return { newPasswordHash, newUserKey: newUserKey, hint: masterPasswordHint }; } private async handleCaptchaRequired( diff --git a/apps/cli/src/auth/commands/unlock.command.ts b/apps/cli/src/auth/commands/unlock.command.ts index 3062567212..17af74ebe3 100644 --- a/apps/cli/src/auth/commands/unlock.command.ts +++ b/apps/cli/src/auth/commands/unlock.command.ts @@ -44,17 +44,17 @@ export class UnlockCommand { const email = await this.stateService.getEmail(); const kdf = await this.stateService.getKdfType(); const kdfConfig = await this.stateService.getKdfConfig(); - const key = await this.cryptoService.makeKey(password, email, kdf, kdfConfig); + const masterKey = await this.cryptoService.makeMasterKey(password, email, kdf, kdfConfig); const storedKeyHash = await this.cryptoService.getKeyHash(); let passwordValid = false; - if (key != null) { + if (masterKey != null) { if (storedKeyHash != null) { - passwordValid = await this.cryptoService.compareAndUpdateKeyHash(password, key); + passwordValid = await this.cryptoService.compareAndUpdateKeyHash(password, masterKey); } else { const serverKeyHash = await this.cryptoService.hashPassword( password, - key, + masterKey, HashPurpose.ServerAuthorization ); const request = new SecretVerificationRequest(); @@ -64,7 +64,7 @@ export class UnlockCommand { passwordValid = true; const localKeyHash = await this.cryptoService.hashPassword( password, - key, + masterKey, HashPurpose.LocalAuthorization ); await this.cryptoService.setKeyHash(localKeyHash); @@ -75,7 +75,9 @@ export class UnlockCommand { } if (passwordValid) { - await this.cryptoService.setKey(key); + await this.cryptoService.setMasterKey(masterKey); + const userKey = await this.cryptoService.decryptUserKeyWithMasterKey(masterKey); + await this.cryptoService.setUserKey(userKey); if (await this.keyConnectorService.getConvertAccountRequired()) { const convertToKeyConnectorCommand = new ConvertToKeyConnectorCommand( diff --git a/apps/cli/src/bw.ts b/apps/cli/src/bw.ts index 29c1443a71..b19f367ae4 100644 --- a/apps/cli/src/bw.ts +++ b/apps/cli/src/bw.ts @@ -334,7 +334,7 @@ export class Main { ); const lockedCallback = async () => - await this.cryptoService.clearStoredKey(KeySuffixOptions.Auto); + await this.cryptoService.clearStoredUserKey(KeySuffixOptions.Auto); this.vaultTimeoutSettingsService = new VaultTimeoutSettingsService( this.cryptoService, diff --git a/apps/cli/src/commands/serve.command.ts b/apps/cli/src/commands/serve.command.ts index 8808dcaafb..fdd8adfb9f 100644 --- a/apps/cli/src/commands/serve.command.ts +++ b/apps/cli/src/commands/serve.command.ts @@ -425,11 +425,14 @@ export class ServeCommand { this.processResponse(res, Response.error("You are not logged in.")); return true; } - if (await this.main.cryptoService.hasKeyInMemory()) { + if (await this.main.cryptoService.hasUserKeyInMemory()) { return false; - } else if (await this.main.cryptoService.hasKeyStored(KeySuffixOptions.Auto)) { + } else if (await this.main.cryptoService.hasUserKeyStored(KeySuffixOptions.Auto)) { // load key into memory - await this.main.cryptoService.getKey(); + const userAutoKey = await this.main.cryptoService.getUserKeyFromStorage( + KeySuffixOptions.Auto + ); + await this.main.cryptoService.setUserKey(userAutoKey); return false; } this.processResponse(res, Response.error("Vault is locked.")); diff --git a/apps/cli/src/program.ts b/apps/cli/src/program.ts index 700a31b3c6..9ca99b937d 100644 --- a/apps/cli/src/program.ts +++ b/apps/cli/src/program.ts @@ -597,11 +597,14 @@ export class Program { protected async exitIfLocked() { await this.exitIfNotAuthed(); - if (await this.main.cryptoService.hasKeyInMemory()) { + if (await this.main.cryptoService.hasUserKeyInMemory()) { return; - } else if (await this.main.cryptoService.hasKeyStored(KeySuffixOptions.Auto)) { + } else if (await this.main.cryptoService.hasUserKeyStored(KeySuffixOptions.Auto)) { // load key into memory - await this.main.cryptoService.getKey(); + const userAutoKey = await this.main.cryptoService.getUserKeyFromStorage( + KeySuffixOptions.Auto + ); + await this.main.cryptoService.setUserKey(userAutoKey); } else if (process.env.BW_NOINTERACTION !== "true") { // must unlock if (await this.main.keyConnectorService.getUsesKeyConnector()) { diff --git a/apps/cli/src/vault/create.command.ts b/apps/cli/src/vault/create.command.ts index 49a61e6e59..1007eebcad 100644 --- a/apps/cli/src/vault/create.command.ts +++ b/apps/cli/src/vault/create.command.ts @@ -126,8 +126,8 @@ export class CreateCommand { return Response.error("Premium status is required to use this feature."); } - const encKey = await this.cryptoService.getEncKey(); - if (encKey == null) { + const userKey = await this.cryptoService.getUserKeyFromMemory(); + if (userKey == null) { return Response.error( "You must update your encryption key before you can use this feature. " + "See https://help.bitwarden.com/article/update-encryption-key/" diff --git a/apps/desktop/src/app/accounts/settings.component.ts b/apps/desktop/src/app/accounts/settings.component.ts index 162cb338bc..5631fb500e 100644 --- a/apps/desktop/src/app/accounts/settings.component.ts +++ b/apps/desktop/src/app/accounts/settings.component.ts @@ -404,7 +404,7 @@ export class SettingsComponent implements OnInit { await this.cryptoService.toggleKey(); // Validate the key is stored in case biometrics fail. - const biometricSet = await this.cryptoService.hasKeyStored(KeySuffixOptions.Biometric); + const biometricSet = await this.cryptoService.hasUserKeyStored(KeySuffixOptions.Biometric); this.form.controls.biometric.setValue(biometricSet); if (!biometricSet) { await this.stateService.setBiometricUnlock(null); diff --git a/apps/desktop/src/locales/eo/messages.json b/apps/desktop/src/locales/eo/messages.json index b230e75302..1ece91c1e1 100644 --- a/apps/desktop/src/locales/eo/messages.json +++ b/apps/desktop/src/locales/eo/messages.json @@ -6,13 +6,13 @@ "message": "Filtriloj" }, "allItems": { - "message": "All items" + "message": "Ĉiuj Eroj" }, "favorites": { - "message": "Favorites" + "message": "Plej ŝatataj" }, "types": { - "message": "Types" + "message": "Tipoj" }, "typeLogin": { "message": "Saluto" @@ -21,7 +21,7 @@ "message": "Karto" }, "typeIdentity": { - "message": "Identity" + "message": "Idento" }, "typeSecureNote": { "message": "Sekura noto" @@ -30,10 +30,10 @@ "message": "Dosierujoj" }, "collections": { - "message": "Collections" + "message": "Kolektoj" }, "searchVault": { - "message": "Search vault" + "message": "Traserĉu trezorejon" }, "addItem": { "message": "Aldoni elementon" @@ -45,10 +45,10 @@ "message": "Kundividi" }, "moveToOrganization": { - "message": "Move to organization" + "message": "Movu al organizo" }, "movedItemToOrg": { - "message": "$ITEMNAME$ moved to $ORGNAME$", + "message": "$ITEMNAME$ moviĝis al $ORGNAME$", "placeholders": { "itemname": { "content": "$1", @@ -61,7 +61,7 @@ } }, "moveToOrgDesc": { - "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + "message": "Elektu organizon kun kiu vi volas dividi ĉi tiun eron. Dividado transdonas posedon de la ero al la organizo. Vi ne plu estos la rekta posedanto de ĉi tiu ero post kiam ĝi estos dividita." }, "attachments": { "message": "Aldonaĵoj" @@ -104,10 +104,10 @@ "message": "Retpoŝta adreso" }, "verificationCodeTotp": { - "message": "Verification code (TOTP)" + "message": "Kontrola kodo (TOTP)" }, "website": { - "message": "Website" + "message": "Retejo" }, "notes": { "message": "Notoj" @@ -116,10 +116,10 @@ "message": "Propraj kampoj" }, "launch": { - "message": "Launch" + "message": "Lanĉo" }, "copyValue": { - "message": "Copy value", + "message": "Kopii valoron", "description": "Copy value to clipboard" }, "minimizeOnCopyToClipboard": { diff --git a/apps/desktop/src/locales/fi/messages.json b/apps/desktop/src/locales/fi/messages.json index 96b7282f13..4372bf8635 100644 --- a/apps/desktop/src/locales/fi/messages.json +++ b/apps/desktop/src/locales/fi/messages.json @@ -962,7 +962,7 @@ "message": "Käynnistä automaattisesti kirjauduttaessa" }, "openAtLoginDesc": { - "message": "Käynnistä sovellus automaattisesti kirjautumisen yhteydessä." + "message": "Käynnistä Bitwarden-sovellus automaattisesti kirjautumisen yhteydessä." }, "alwaysShowDock": { "message": "Näytä aina Dockissa" diff --git a/apps/desktop/src/platform/services/electron-crypto.service.ts b/apps/desktop/src/platform/services/electron-crypto.service.ts index 1fb90e52ca..d9a0f2d7a7 100644 --- a/apps/desktop/src/platform/services/electron-crypto.service.ts +++ b/apps/desktop/src/platform/services/electron-crypto.service.ts @@ -4,7 +4,12 @@ import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt. import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; -import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; +import { EncString } from "@bitwarden/common/platform/models/domain/enc-string"; +import { + MasterKey, + SymmetricCryptoKey, + UserKey, +} from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { CryptoService } from "@bitwarden/common/platform/services/crypto.service"; import { CsprngString } from "@bitwarden/common/types/csprng"; @@ -21,24 +26,36 @@ export class ElectronCryptoService extends CryptoService { super(cryptoFunctionService, encryptService, platformUtilsService, logService, stateService); } - protected override async storeKey(key: SymmetricCryptoKey, userId?: string) { - await super.storeKey(key, userId); + protected override async storeAdditionalKeys(key: UserKey, userId?: string) { + await super.storeAdditionalKeys(key, userId); const storeBiometricKey = await this.shouldStoreKey(KeySuffixOptions.Biometric, userId); if (storeBiometricKey) { await this.storeBiometricKey(key, userId); } else { - await this.stateService.setCryptoMasterKeyBiometric(null, { userId: userId }); + await this.stateService.setUserKeyBiometric(null, { userId: userId }); } } - protected async storeBiometricKey(key: SymmetricCryptoKey, userId?: string): Promise { + protected override async retrieveUserKeyFromStorage( + keySuffix: KeySuffixOptions, + userId?: string + ): Promise { + if (keySuffix === KeySuffixOptions.Biometric) { + await this.migrateBiometricKeyIfNeeded(userId); + const userKey = await this.stateService.getUserKeyBiometric({ userId: userId }); + return new SymmetricCryptoKey(Utils.fromB64ToArray(userKey).buffer) as UserKey; + } + return await super.retrieveUserKeyFromStorage(keySuffix, userId); + } + + protected async storeBiometricKey(key: UserKey, userId?: string): Promise { let clientEncKeyHalf: CsprngString = null; if (await this.stateService.getBiometricRequirePasswordOnStart({ userId })) { clientEncKeyHalf = await this.getBiometricEncryptionClientKeyHalf(userId); } - await this.stateService.setCryptoMasterKeyBiometric( + await this.stateService.setUserKeyBiometric( { key: key.keyB64, clientEncKeyHalf }, { userId: userId } ); @@ -63,4 +80,21 @@ export class ElectronCryptoService extends CryptoService { return null; } } + + private async migrateBiometricKeyIfNeeded(userId?: string) { + if (await this.stateService.hasCryptoMasterKeyBiometric({ userId })) { + const oldBiometricKey = await this.stateService.getCryptoMasterKeyBiometric({ userId }); + // decrypt + const masterKey = new SymmetricCryptoKey(Utils.fromB64ToArray(oldBiometricKey)) as MasterKey; + let encUserKey = await this.stateService.getEncryptedCryptoSymmetricKey(); + encUserKey = encUserKey ?? (await this.stateService.getUserKeyMasterKey()); + if (!encUserKey) { + throw new Error("No user key found during biometric migration"); + } + const userKey = await this.decryptUserKeyWithMasterKey(masterKey, new EncString(encUserKey)); + // migrate + await this.storeBiometricKey(userKey, userId); + await this.stateService.setCryptoMasterKeyBiometric(null, { userId }); + } + } } diff --git a/apps/desktop/src/services/native-message-handler.service.ts b/apps/desktop/src/services/native-message-handler.service.ts index 1921ea5fa0..c842e698d2 100644 --- a/apps/desktop/src/services/native-message-handler.service.ts +++ b/apps/desktop/src/services/native-message-handler.service.ts @@ -8,7 +8,7 @@ import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.se import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; -import { EncString } from "@bitwarden/common/platform/models/domain/enc-string"; +import { EncryptedString, EncString } from "@bitwarden/common/platform/models/domain/enc-string"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { StateService } from "@bitwarden/common/platform/services/state.service"; @@ -144,7 +144,9 @@ export class NativeMessageHandlerService { } private async handleEncryptedMessage(message: EncryptedMessage) { - message.encryptedCommand = EncString.fromJSON(message.encryptedCommand.toString()); + message.encryptedCommand = EncString.fromJSON( + message.encryptedCommand.toString() as EncryptedString + ); const decryptedCommandData = await this.decryptPayload(message); const { command } = decryptedCommandData; diff --git a/apps/desktop/src/services/native-messaging.service.ts b/apps/desktop/src/services/native-messaging.service.ts index 494a65b670..2b4950f7e0 100644 --- a/apps/desktop/src/services/native-messaging.service.ts +++ b/apps/desktop/src/services/native-messaging.service.ts @@ -136,14 +136,22 @@ export class NativeMessagingService { }); } - const key = await this.cryptoService.getKeyFromStorage( + const userKey = await this.cryptoService.getUserKeyFromStorage( KeySuffixOptions.Biometric, message.userId ); + const masterKey = await this.cryptoService.getMasterKey(message.userId); - if (key != null) { + if (userKey != null) { + // we send the master key still for backwards compatibility + // with older browser extensions this.send( - { command: "biometricUnlock", response: "unlocked", keyB64: key.keyB64 }, + { + command: "biometricUnlock", + response: "unlocked", + keyB64: masterKey.keyB64, + userKeyB64: userKey.keyB64, + }, appId ); } else { diff --git a/apps/web/config/euprd.json b/apps/web/config/euprd.json index 3813074b7c..db3568acc6 100644 --- a/apps/web/config/euprd.json +++ b/apps/web/config/euprd.json @@ -1,8 +1,8 @@ { "urls": { "icons": "https://icons.bitwarden.net", - "notifications": "https://notifications.bitwarden.net", - "scim": "https://scim.bitwarden.net" + "notifications": "https://notifications.beta.bitwarden.net", + "scim": "https://scim.beta.bitwarden.net" }, "flags": { "secretsManager": true, diff --git a/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-confirm.component.ts b/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-confirm.component.ts index 669a8954ee..88eeb6036c 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-confirm.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-confirm.component.ts @@ -7,6 +7,7 @@ import { OrganizationUserStatusType } from "@bitwarden/common/admin-console/enum import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; +import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { BulkUserDetails } from "./bulk-status.component"; @@ -98,7 +99,7 @@ export class BulkConfirmComponent implements OnInit { ); } - protected getCryptoKey() { + protected getCryptoKey(): Promise { return this.cryptoService.getOrgKey(this.organizationId); } diff --git a/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.ts b/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.ts index 55f935c575..ce6d3e37f7 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.ts @@ -23,7 +23,10 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service" import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { EncString } from "@bitwarden/common/platform/models/domain/enc-string"; -import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; +import { + SymmetricCryptoKey, + UserKey, +} from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password"; @Component({ @@ -171,25 +174,31 @@ export class ResetPasswordComponent implements OnInit, OnDestroy { orgSymKey ); - // Decrypt User's Reset Password Key to get EncKey + // Decrypt User's Reset Password Key to get UserKey const decValue = await this.cryptoService.rsaDecrypt(resetPasswordKey, decPrivateKey); - const userEncKey = new SymmetricCryptoKey(decValue); + const existingUserKey = new SymmetricCryptoKey(decValue) as UserKey; - // Create new key and hash new password - const newKey = await this.cryptoService.makeKey( + // Create new master key and hash new password + const newMasterKey = await this.cryptoService.makeMasterKey( this.newPassword, this.email.trim().toLowerCase(), kdfType, new KdfConfig(kdfIterations, kdfMemory, kdfParallelism) ); - const newPasswordHash = await this.cryptoService.hashPassword(this.newPassword, newKey); + const newPasswordHash = await this.cryptoService.hashPassword( + this.newPassword, + newMasterKey + ); - // Create new encKey for the User - const newEncKey = await this.cryptoService.remakeEncKey(newKey, userEncKey); + // Create new encrypted user key for the User + const newUserKey = await this.cryptoService.encryptUserKeyWithMasterKey( + newMasterKey, + existingUserKey + ); // Create request const request = new OrganizationUserResetPasswordRequest(); - request.key = newEncKey[1].encryptedString; + request.key = newUserKey[1].encryptedString; request.newMasterPasswordHash = newPasswordHash; // Change user's password diff --git a/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts b/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts index 68203033ee..45b0cc318f 100644 --- a/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts +++ b/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts @@ -58,8 +58,8 @@ export class EnrollMasterPasswordReset { const publicKey = Utils.fromB64ToArray(orgKeys.publicKey); // RSA Encrypt user's encKey.key with organization public key - const encKey = await this.cryptoService.getEncKey(); - const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey.buffer); + const userKey = await this.cryptoService.getUserKeyFromMemory(); + const encryptedKey = await this.cryptoService.rsaEncrypt(userKey.key, publicKey.buffer); keyString = encryptedKey.encryptedString; toastStringRef = "enrollPasswordResetSuccess"; diff --git a/apps/web/src/app/auth/accept-organization.component.ts b/apps/web/src/app/auth/accept-organization.component.ts index 291cea09a4..c27db602ae 100644 --- a/apps/web/src/app/auth/accept-organization.component.ts +++ b/apps/web/src/app/auth/accept-organization.component.ts @@ -141,8 +141,8 @@ export class AcceptOrganizationComponent extends BaseAcceptComponent { const publicKey = Utils.fromB64ToArray(response.publicKey); // RSA Encrypt user's encKey.key with organization public key - const encKey = await this.cryptoService.getEncKey(); - const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey.buffer); + const userKey = await this.cryptoService.getUserKeyFromMemory(); + const encryptedKey = await this.cryptoService.rsaEncrypt(userKey.key, publicKey.buffer); // Add reset password key to accept request request.resetPasswordKey = encryptedKey.encryptedString; diff --git a/apps/web/src/app/auth/settings/emergency-access/emergency-access-takeover.component.ts b/apps/web/src/app/auth/settings/emergency-access/emergency-access-takeover.component.ts index 026529dc11..cc1aa71c6c 100644 --- a/apps/web/src/app/auth/settings/emergency-access/emergency-access-takeover.component.ts +++ b/apps/web/src/app/auth/settings/emergency-access/emergency-access-takeover.component.ts @@ -17,7 +17,10 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service" import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; -import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; +import { + SymmetricCryptoKey, + UserKey, +} from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password"; @Component({ @@ -91,9 +94,9 @@ export class EmergencyAccessTakeoverComponent ); const oldKeyBuffer = await this.cryptoService.rsaDecrypt(takeoverResponse.keyEncrypted); - const oldEncKey = new SymmetricCryptoKey(oldKeyBuffer); + const oldUserKey = new SymmetricCryptoKey(oldKeyBuffer) as UserKey; - if (oldEncKey == null) { + if (oldUserKey == null) { this.platformUtilsService.showToast( "error", this.i18nService.t("errorOccurred"), @@ -102,7 +105,7 @@ export class EmergencyAccessTakeoverComponent return; } - const key = await this.cryptoService.makeKey( + const masterKey = await this.cryptoService.makeMasterKey( this.masterPassword, this.email, takeoverResponse.kdf, @@ -112,9 +115,12 @@ export class EmergencyAccessTakeoverComponent takeoverResponse.kdfParallelism ) ); - const masterPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, key); + const masterPasswordHash = await this.cryptoService.hashPassword( + this.masterPassword, + masterKey + ); - const encKey = await this.cryptoService.remakeEncKey(key, oldEncKey); + const encKey = await this.cryptoService.encryptUserKeyWithMasterKey(masterKey, oldUserKey); const request = new EmergencyAccessPasswordRequest(); request.newMasterPasswordHash = masterPasswordHash; diff --git a/apps/web/src/app/auth/settings/emergency-access/emergency-access-view.component.ts b/apps/web/src/app/auth/settings/emergency-access/emergency-access-view.component.ts index 9507980248..f7936d361b 100644 --- a/apps/web/src/app/auth/settings/emergency-access/emergency-access-view.component.ts +++ b/apps/web/src/app/auth/settings/emergency-access/emergency-access-view.component.ts @@ -5,7 +5,10 @@ import { ModalService } from "@bitwarden/angular/services/modal.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { EmergencyAccessViewResponse } from "@bitwarden/common/auth/models/response/emergency-access.response"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; -import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; +import { + SymmetricCryptoKey, + UserKey, +} from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { CipherData } from "@bitwarden/common/vault/models/data/cipher.data"; import { Cipher } from "@bitwarden/common/vault/models/domain/cipher"; @@ -87,13 +90,13 @@ export class EmergencyAccessViewComponent implements OnInit { const decCiphers: CipherView[] = []; const oldKeyBuffer = await this.cryptoService.rsaDecrypt(response.keyEncrypted); - const oldEncKey = new SymmetricCryptoKey(oldKeyBuffer); + const oldUserKey = new SymmetricCryptoKey(oldKeyBuffer) as UserKey; const promises: any[] = []; ciphers.forEach((cipherResponse) => { const cipherData = new CipherData(cipherResponse); const cipher = new Cipher(cipherData); - promises.push(cipher.decrypt(oldEncKey).then((c) => decCiphers.push(c))); + promises.push(cipher.decrypt(oldUserKey).then((c) => decCiphers.push(c))); }); await Promise.all(promises); diff --git a/apps/web/src/app/auth/settings/emergency-access/emergency-access.component.ts b/apps/web/src/app/auth/settings/emergency-access/emergency-access.component.ts index 73f8f1f653..a6c5c0dab0 100644 --- a/apps/web/src/app/auth/settings/emergency-access/emergency-access.component.ts +++ b/apps/web/src/app/auth/settings/emergency-access/emergency-access.component.ts @@ -300,9 +300,9 @@ export class EmergencyAccessComponent implements OnInit { } } - // Encrypt the master password hash using the grantees public key, and send it to bitwarden for escrow. + // Encrypt the user key with the grantees public key, and send it to bitwarden for escrow. private async doConfirmation(details: EmergencyAccessGranteeDetailsResponse) { - const encKey = await this.cryptoService.getEncKey(); + const userKey = await this.cryptoService.getUserKeyFromMemory(); const publicKeyResponse = await this.apiService.getUserPublicKey(details.granteeId); const publicKey = Utils.fromB64ToArray(publicKeyResponse.publicKey); @@ -315,7 +315,7 @@ export class EmergencyAccessComponent implements OnInit { // Ignore errors since it's just a debug message } - const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey.buffer); + const encryptedKey = await this.cryptoService.rsaEncrypt(userKey.key, publicKey.buffer); const request = new EmergencyAccessConfirmRequest(); request.key = encryptedKey.encryptedString; await this.apiService.postEmergencyAccessConfirm(details.id, request); diff --git a/apps/web/src/app/settings/change-email.component.ts b/apps/web/src/app/settings/change-email.component.ts index c28bf3dcfd..138d0f9241 100644 --- a/apps/web/src/app/settings/change-email.component.ts +++ b/apps/web/src/app/settings/change-email.component.ts @@ -42,8 +42,8 @@ export class ChangeEmailComponent implements OnInit { } async submit() { - const hasEncKey = await this.cryptoService.hasEncKey(); - if (!hasEncKey) { + const hasUserKey = await this.cryptoService.hasUserKey(); + if (!hasUserKey) { this.platformUtilsService.showToast("error", null, this.i18nService.t("updateKey")); return; } @@ -67,7 +67,7 @@ export class ChangeEmailComponent implements OnInit { request.masterPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, null); const kdf = await this.stateService.getKdfType(); const kdfConfig = await this.stateService.getKdfConfig(); - const newKey = await this.cryptoService.makeKey( + const newMasterKey = await this.cryptoService.makeMasterKey( this.masterPassword, this.newEmail, kdf, @@ -75,10 +75,10 @@ export class ChangeEmailComponent implements OnInit { ); request.newMasterPasswordHash = await this.cryptoService.hashPassword( this.masterPassword, - newKey + newMasterKey ); - const newEncKey = await this.cryptoService.remakeEncKey(newKey); - request.key = newEncKey[1].encryptedString; + const newUserKey = await this.cryptoService.encryptUserKeyWithMasterKey(newMasterKey); + request.key = newUserKey[1].encryptedString; try { this.formPromise = this.apiService.postEmail(request); await this.formPromise; diff --git a/apps/web/src/app/settings/change-kdf/change-kdf-confirmation.component.ts b/apps/web/src/app/settings/change-kdf/change-kdf-confirmation.component.ts index ebf74f4457..58516b2640 100644 --- a/apps/web/src/app/settings/change-kdf/change-kdf-confirmation.component.ts +++ b/apps/web/src/app/settings/change-kdf/change-kdf-confirmation.component.ts @@ -46,8 +46,8 @@ export class ChangeKdfConfirmationComponent { async submit() { this.loading = true; - const hasEncKey = await this.cryptoService.hasEncKey(); - if (!hasEncKey) { + const hasUserKey = await this.cryptoService.hasUserKey(); + if (!hasUserKey) { this.platformUtilsService.showToast("error", null, this.i18nService.t("updateKey")); return; } @@ -77,15 +77,18 @@ export class ChangeKdfConfirmationComponent { request.kdfParallelism = this.kdfConfig.parallelism; request.masterPasswordHash = await this.cryptoService.hashPassword(masterPassword, null); const email = await this.stateService.getEmail(); - const newKey = await this.cryptoService.makeKey( + const newMasterKey = await this.cryptoService.makeMasterKey( masterPassword, email, this.kdf, this.kdfConfig ); - request.newMasterPasswordHash = await this.cryptoService.hashPassword(masterPassword, newKey); - const newEncKey = await this.cryptoService.remakeEncKey(newKey); - request.key = newEncKey[1].encryptedString; + request.newMasterPasswordHash = await this.cryptoService.hashPassword( + masterPassword, + newMasterKey + ); + const newUserKey = await this.cryptoService.encryptUserKeyWithMasterKey(newMasterKey); + request.key = newUserKey[1].encryptedString; await this.apiService.postAccountKdf(request); } diff --git a/apps/web/src/app/settings/change-password.component.html b/apps/web/src/app/settings/change-password.component.html index 3321b8f9df..7088cb5a68 100644 --- a/apps/web/src/app/settings/change-password.component.html +++ b/apps/web/src/app/settings/change-password.component.html @@ -89,12 +89,12 @@ -