From 11a0924eb35f0e9b7392d028d2133dfca9a77615 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Mon, 30 Mar 2026 19:19:57 +0200 Subject: [PATCH 1/3] Add workflow to update windows cert thumbprint also switches from cert serial numbers to thumbprints --- .github/workflows/update-windows-info.yml | 100 ++++++++++++++++++++++ docs/security/verify-installers.md | 54 +++++++++--- 2 files changed, 141 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/update-windows-info.yml diff --git a/.github/workflows/update-windows-info.yml b/.github/workflows/update-windows-info.yml new file mode 100644 index 0000000..9aea97c --- /dev/null +++ b/.github/workflows/update-windows-info.yml @@ -0,0 +1,100 @@ +name: Updates verify-installers.md after desktop release + +on: + repository_dispatch: + types: [desktop-release] + +defaults: + run: + shell: bash + + +jobs: + create-pr: + name: Create PR to update windows signing cert + runs-on: windows-latest + permissions: + contents: write + env: + DESKTOP_VERSION: ${{ github.event.client_payload.version }} + steps: + - name: Checkout repo + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Create new branch + run: | + git config --global --add safe.directory "$GITHUB_WORKSPACE" + if [[ ! "$DESKTOP_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z]+)*$ ]]; then + echo "Invalid version in payload: $DESKTOP_VERSION" >&2 + exit 1; + fi + git checkout -b "feature/desktop-${DESKTOP_VERSION}" + - name: Download MSI + run: | + MSI_URL=$(jq -r '[.[] | select(.name | endswith(".msi"))][0].browser_download_url // "null"' <<< "$ASSETS_JSON") + curl --silent --fail-with-body --proto "=https" -L -H "Accept: application/vnd.github+json" $MSI_URL --output cryptomator.msi + env: + ASSETS_JSON: ${{ toJson(github.event.client_payload.release.assets ) }} + - name: Update verify-installers.md + shell: pwsh + run: | + $Thumbprint = (Get-AuthenticodeSignature -FilePath 'cryptomator.msi' -ErrorAction Stop).SignerCertificate.Thumbprint + + $DocPath = 'docs/security/verify-installers.md' + $Content = Get-Content -Path $DocPath -Raw + + $CurrentThumbprintRegex = [regex] ([regex]::Escape($env:AUTOMATION_MARKER) + '`[A-F0-9]+`') + $UpdatedContent = $CurrentThumbprintRegex.Replace($Content, ($env:AUTOMATION_MARKER + '`' + $Thumbprint + '`'), 1) + if ($UpdatedContent -eq $Content) { + throw 'Failed to update the current Windows thumbprint in verify-installers.md.' + } + $Content = $UpdatedContent + + $MarkedRow = (Get-Content -Path $DocPath | Where-Object { $_.TrimStart().StartsWith('|') -and $_.EndsWith($env:AUTOMATION_MARKER) } | Select-Object -First 1) + if ($null -eq $MarkedRow) { + throw 'Failed to find the marked Windows certificate table row in verify-installers.md.' + } + + $PreviousRow = $MarkedRow.Substring(0, $MarkedRow.IndexOf($env:AUTOMATION_MARKER)).TrimEnd() + $NewRow = '| ' + $env:DESKTOP_VERSION + ' | `' + $Thumbprint + '` | ' + $env:AUTOMATION_MARKER + $Content = $Content.Replace($MarkedRow, $NewRow + "`r`n" + $PreviousRow) + + Set-Content -Path $DocPath -Value $Content + env: + AUTOMATION_MARKER: '' + - name: Commit and push + id: commit-and-push + run: | + git config user.name "cryptobot" + git config user.email "cryptobot@users.noreply.github.com" + git config push.autoSetupRemote true + git stage docs/security/verify-installers.md + if git diff --cached --quiet; then + echo "No changes to commit" + echo "changed=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + git commit -m "Update Windows section for verifying installers for release ${DESKTOP_VERSION}" + git push + echo "changed=true" >> "$GITHUB_OUTPUT" + - name: Create pull request + id: create-pr + if: steps.commit-and-push.outputs.changed == 'true' + run: | + printf "Created by $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" > pr_body.md + PR_URL=$(gh pr create --title "Desktop release ${DESKTOP_VERSION}" --body-file pr_body.md) + echo "url=$PR_URL" >> "$GITHUB_OUTPUT" + env: + GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }} + - name: Slack Notification + if: steps.commit-and-push.outputs.changed == 'true' + uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3 + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }} + SLACK_USERNAME: 'Cryptobot' + SLACK_ICON: false + SLACK_ICON_EMOJI: ':bot:' + SLACK_CHANNEL: 'cryptomator-desktop' + SLACK_TITLE: "Docs update PR created for release ${{ github.event.client_payload.version }} ." + SLACK_MESSAGE: "See <${{ steps.create-pr.outputs.url }}|PR> on how to proceed." + SLACK_FOOTER: false + MSG_MINIMAL: true diff --git a/docs/security/verify-installers.md b/docs/security/verify-installers.md index 608067c..4adcee3 100644 --- a/docs/security/verify-installers.md +++ b/docs/security/verify-installers.md @@ -28,24 +28,52 @@ If shown, you can ignore the following warning: ## Windows (exe, msi) {#windows} -Our Windows installers are signed using a code signing certificate. You can verify the signature in five simple steps: +Our Windows installers are signed using a code signing certificate. You can verify the signature in three simple steps: -How to check the code signing certificate on Windows +1. Open Terminal or PowerShell (found in Windows Start menu). +2. Run either of the following commands to check the signature of the corresponding file: + ``` + Get-AuthenticodeSignature -FilePath "~\Downloads\Cryptomator-*.msi" + Get-AuthenticodeSignature -FilePath "~\Downloads\Cryptomator-*.exe" + ``` +3. Verify that the output includes: + - Column `SignerCertificate` with value `20F30D7C5B1AB3ACAFA4AB27874ACBC4B47B0697`(*) + - Column `Status` with value `Valid` + - no errors + +*for older releases, see [below](#windows-all-versions). -1. Right-click on the file and click on Properties. +If the installer is properly signed, you should see output similar to: +``` +SignerCertificate Status StatusMessage Path +----------------- ------ ------------- ---- +BB0E... Valid Signature verified. Cryptomator-1.19.1-x64.msi +``` + +You can also inspect the certificate manually: +1. Right-click on the cryptomator installer file and click on Properties. 2. Select the Digital Signatures tab: It should show one or more signatures by `Skymatic GmbH` under Embedded Signatures. - For releases since 1.18.0, the `exe` release artifact will have two signatures, and the `msi` release artifact will have one signature. 3. Click on the first signature, and then click Details. -4. Click on View Certificates. -5. Click the Details tab. Different Cryptomator versions are signed with different certificates. The following list shows for each version the certificate serial number: - - Version 1.19.2: `33000890b1b9dff7ee6e525b2d0000000890b1` - - Version 1.19.1: `33000852bd6c3a151ff92180ee0000000852bd` - - Version 1.19.0: `3300083c47651e1daeb99b00eb000000083c47` - - Version 1.18.1: `330007d28ad57305892a81cac600000007d28a` - - Version 1.18.0: `3300052c3561155e2baf361702000000052c35` - - Versions 1.6.11 to 1.17.1: `00d77e4f8b938f56ae265cd08e9193490c` - - Versions 1.4.12 to 1.6.10: `63c45bff1a148d60ed2994d3a2639034` - - Versions up to 1.4.11: `1a360f3933964c71f14e8754d94615d4` +4. Click on View Certificates and select the field `Thumbprint`. + +How to check the code signing certificate on Windows + +### Certificate thumbprints for all Cryptomator versions {#windows-all-versions} + +Every Cryptomator installer is signed with a certificate. A certificate is identified by its thumbprint. The signing certificate changed over time and the following table shows for each version the certificate thumbprint: +| Version(s) | Certificate Thumbprint | +|---------------------|--------------------------------------------| +| 1.19.2 | `20F30D7C5B1AB3ACAFA4AB27874ACBC4B47B0697` | +| 1.19.1 | `BB0EEBF8E92E4584DF4B6AE4F9577B60BEB5DF4C` | +| 1.19.0 | `14524B1F8A3A1CA8B24B769C7C6DC92851120B22` | +| 1.18.1 | `53FA929F6D50D5E2AE59A7C9A9750D373AFF7D40` | +| 1.18.0 | `4DC9A70B94F731562A9C37B4391C4FD5BEC72C94` | +| 1.6.11 to 1.17.1 | `5FC94CE149E5B511E621F53A060AC67CBD446B3A` | +| 1.4.12 to 1.6.10 | `FF52240075AD7D14AF25629FDF69635357C7D14B` | +| up to 1.4.11 | `6FDEC9DFCFE59E6BAEE64B7ED97F00E120E70D97` | + + ## macOS (app) {#macos} From cff6da471df9a663db0461c8e82ab82a89d8db9b Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 31 Mar 2026 15:28:44 +0200 Subject: [PATCH 2/3] Apply suggestions from code review --- .github/workflows/update-windows-info.yml | 12 ++++++++---- docs/security/verify-installers.md | 6 +++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/update-windows-info.yml b/.github/workflows/update-windows-info.yml index 9aea97c..55ee542 100644 --- a/.github/workflows/update-windows-info.yml +++ b/.github/workflows/update-windows-info.yml @@ -31,6 +31,10 @@ jobs: - name: Download MSI run: | MSI_URL=$(jq -r '[.[] | select(.name | endswith(".msi"))][0].browser_download_url // "null"' <<< "$ASSETS_JSON") + if [[ "$MSI_URL" == "null" || -z "$MSI_URL" ]]; then + echo "No MSI asset found in repository_dispatch payload." >&2 + exit 1 + fi curl --silent --fail-with-body --proto "=https" -L -H "Accept: application/vnd.github+json" $MSI_URL --output cryptomator.msi env: ASSETS_JSON: ${{ toJson(github.event.client_payload.release.assets ) }} @@ -49,18 +53,18 @@ jobs: } $Content = $UpdatedContent - $MarkedRow = (Get-Content -Path $DocPath | Where-Object { $_.TrimStart().StartsWith('|') -and $_.EndsWith($env:AUTOMATION_MARKER) } | Select-Object -First 1) + $MarkedRow = (Get-Content -Path $DocPath | Where-Object { $_.TrimStart().StartsWith('|') -and $_.Contains($env:AUTOMATION_MARKER) } | Select-Object -First 1) if ($null -eq $MarkedRow) { throw 'Failed to find the marked Windows certificate table row in verify-installers.md.' } - $PreviousRow = $MarkedRow.Substring(0, $MarkedRow.IndexOf($env:AUTOMATION_MARKER)).TrimEnd() - $NewRow = '| ' + $env:DESKTOP_VERSION + ' | `' + $Thumbprint + '` | ' + $env:AUTOMATION_MARKER + $PreviousRow = $MarkedRow.Substring(0, $MarkedRow.IndexOf($env:AUTOMATION_MARKER)).TrimEnd() + " |" + $NewRow = "| $env:DESKTOP_VERSION |" + '`' + $Thumbprint + '`' + "$env:AUTOMATION_MARKER |" $Content = $Content.Replace($MarkedRow, $NewRow + "`r`n" + $PreviousRow) Set-Content -Path $DocPath -Value $Content env: - AUTOMATION_MARKER: '' + AUTOMATION_MARKER: '' - name: Commit and push id: commit-and-push run: | diff --git a/docs/security/verify-installers.md b/docs/security/verify-installers.md index 4adcee3..d8316a7 100644 --- a/docs/security/verify-installers.md +++ b/docs/security/verify-installers.md @@ -32,12 +32,12 @@ Our Windows installers are signed using a code signing certificate. You can veri 1. Open Terminal or PowerShell (found in Windows Start menu). 2. Run either of the following commands to check the signature of the corresponding file: - ``` + ```powershell Get-AuthenticodeSignature -FilePath "~\Downloads\Cryptomator-*.msi" Get-AuthenticodeSignature -FilePath "~\Downloads\Cryptomator-*.exe" ``` 3. Verify that the output includes: - - Column `SignerCertificate` with value `20F30D7C5B1AB3ACAFA4AB27874ACBC4B47B0697`(*) + - Column `SignerCertificate` with value `20F30D7C5B1AB3ACAFA4AB27874ACBC4B47B0697`(*) - Column `Status` with value `Valid` - no errors @@ -64,7 +64,7 @@ You can also inspect the certificate manually: Every Cryptomator installer is signed with a certificate. A certificate is identified by its thumbprint. The signing certificate changed over time and the following table shows for each version the certificate thumbprint: | Version(s) | Certificate Thumbprint | |---------------------|--------------------------------------------| -| 1.19.2 | `20F30D7C5B1AB3ACAFA4AB27874ACBC4B47B0697` | +| 1.19.2 | `20F30D7C5B1AB3ACAFA4AB27874ACBC4B47B0697` | | 1.19.1 | `BB0EEBF8E92E4584DF4B6AE4F9577B60BEB5DF4C` | | 1.19.0 | `14524B1F8A3A1CA8B24B769C7C6DC92851120B22` | | 1.18.1 | `53FA929F6D50D5E2AE59A7C9A9750D373AFF7D40` | From 8f325e92830b17b12e522c2a19c0465b7ca5a9c4 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 31 Mar 2026 15:35:28 +0200 Subject: [PATCH 3/3] minor fixes --- docs/security/verify-installers.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/security/verify-installers.md b/docs/security/verify-installers.md index d8316a7..9bd86d5 100644 --- a/docs/security/verify-installers.md +++ b/docs/security/verify-installers.md @@ -32,7 +32,7 @@ Our Windows installers are signed using a code signing certificate. You can veri 1. Open Terminal or PowerShell (found in Windows Start menu). 2. Run either of the following commands to check the signature of the corresponding file: - ```powershell + ```pwsh Get-AuthenticodeSignature -FilePath "~\Downloads\Cryptomator-*.msi" Get-AuthenticodeSignature -FilePath "~\Downloads\Cryptomator-*.exe" ``` @@ -44,7 +44,7 @@ Our Windows installers are signed using a code signing certificate. You can veri *for older releases, see [below](#windows-all-versions). If the installer is properly signed, you should see output similar to: -``` +```text SignerCertificate Status StatusMessage Path ----------------- ------ ------------- ---- BB0E... Valid Signature verified. Cryptomator-1.19.1-x64.msi @@ -62,6 +62,7 @@ You can also inspect the certificate manually: ### Certificate thumbprints for all Cryptomator versions {#windows-all-versions} Every Cryptomator installer is signed with a certificate. A certificate is identified by its thumbprint. The signing certificate changed over time and the following table shows for each version the certificate thumbprint: + | Version(s) | Certificate Thumbprint | |---------------------|--------------------------------------------| | 1.19.2 | `20F30D7C5B1AB3ACAFA4AB27874ACBC4B47B0697` |