From 9eec9e1d9dddf3d5b60abd03ef49230ce4c7df45 Mon Sep 17 00:00:00 2001 From: "propr-dev[bot]" <1316198+propr-dev[bot]@users.noreply.github.com> Date: Mon, 19 Oct 2026 14:19:49 +0000 Subject: [PATCH] I've rotated the Linux release signing pin to the new owner key (`80FE0A7667A92A0AD3CEAE6D4C2FF8C3CC4E1599`). The focused signing, release and workflow tests pass with real GnuPG and RPM tools, none skipped. Checking the key: before using the public key from the issue, I inspected it myself with GnuPG 2.2.40. It is a single RSA4096 primary key that can sign, with no subkeys. The user ID is exactly `ProPR Desktop Release Signing`, it was issued 2026-10-19 and expires 2028-10-18. Its self-signature is valid, and it contains no private key material. Changes - Pin: `apps/desktop/scripts/rpm-signing.mjs` now pins the new fingerprint. Nothing else in the signing code changed: the existing checks and the 13-asset allowlist are as before, with no broader signer list and no fallback. - Public keys: `docs/static/keys/propr-desktop-release.asc` is now the exact export from the issue. The old export is kept byte-for-byte as `propr-desktop-release-historical-DD4E7F65CE2345A1F4597D643CF856B53093D3A3.asc`. - `linux-release-key.md`: - New key: the new identity, its effective date and download, and what it signs (RPMs, `SHA256SUMS` and the APT metadata). DEB files are unchanged and get no embedded-signature claim. - Rotation and old key: the rotation is not cross-signed by the old key and is backed only by the reviewed docs and the repository. The notice says no compromise was reported and the old key is not revoked, and gives its fingerprint and dates. - Older releases: they keep their original signing and trust classification, and the new pin does not authenticate them. - Consumer steps: for RPM, import the new key and expect key ID `cc4e1599`. For APT, replace the keyring the repository line points to. - `linux-rpm-signing.md`: the same identity change. It also explains that signing fails closed until an administrator sets the replacement secrets and public settings to match the pin. The fingerprint in the acceptance example is updated. Tests - I updated the test fixture fingerprint in `linux-preview-release.test.mjs` and rewrote the owner-key test in `rpm-signing.test.mjs`. It checks the new key's identity and dates and the old key's identity and dates. It also checks that each key file is rejected under the other's fingerprint. - A new test covers the production environment pin. It rejects the old fingerprint, a throwaway wrong signer, a lowercase or short fingerprint, and a missing one. It accepts only the new fingerprint with the new key file, and rejects the new fingerprint paired with the old key or a wrong key. - The required command (`rpm-signing`, `linux-preview-release` and `linux-preview-workflow` tests with `PROPR_REQUIRE_RPM_TESTS=1`): 29 of 29 pass, 0 skipped. - The other related acceptance and smoke tests: 44 pass. One existing test skipped because it needs root, and it is unrelated to signing. - ESLint is clean, and the docs build succeeds with both key files served under `/keys/`. The container had no GnuPG or RPM tools, so I unpacked the Debian bookworm packages into `/tmp/tools` without installing anything system-wide. I did not touch GitHub secrets or variables, permissions, deployments, publishing, PR3256 or the existing release validation. No private keys were handled; the tests use throwaway keys only. These are documentation and signing-script changes with nothing visual, so I made no preview. Before the next signing run, an administrator still needs to replace the protected private key and passphrase secrets. They must also set `PROPR_DESKTOP_RPM_FINGERPRINT` and `PROPR_DESKTOP_RPM_PUBLIC_KEY` to the new fingerprint and key file. Until then, signing will refuse to run. --- .../scripts/linux-preview-release.test.mjs | 2 +- apps/desktop/scripts/rpm-signing.mjs | 3 +- apps/desktop/scripts/rpm-signing.test.mjs | 75 +++++++++++-- docs/docs/operations/linux-release-key.md | 102 ++++++++++++++---- docs/docs/operations/linux-rpm-signing.md | 35 +++++- ...4E7F65CE2345A1F4597D643CF856B53093D3A3.asc | 29 +++++ docs/static/keys/propr-desktop-release.asc | 52 ++++----- 7 files changed, 236 insertions(+), 62 deletions(-) create mode 100644 docs/static/keys/propr-desktop-release-historical-DD4E7F65CE2345A1F4597D643CF856B53093D3A3.asc diff --git a/apps/desktop/scripts/linux-preview-release.test.mjs b/apps/desktop/scripts/linux-preview-release.test.mjs index 942fb5e6c..a67e5d679 100644 --- a/apps/desktop/scripts/linux-preview-release.test.mjs +++ b/apps/desktop/scripts/linux-preview-release.test.mjs @@ -435,7 +435,7 @@ process.exit(42); encoding: 'utf8', env: { ...process.env, PATH: bin, PROPR_DESKTOP_RPM_PRIVATE_KEY: 'private-test-sentinel', PROPR_DESKTOP_RPM_PASSPHRASE: 'password-test-sentinel', PROPR_DESKTOP_RPM_PUBLIC_KEY: '-----BEGIN PGP PUBLIC KEY BLOCK-----', - PROPR_DESKTOP_RPM_FINGERPRINT: 'DD4E7F65CE2345A1F4597D643CF856B53093D3A3' }, + PROPR_DESKTOP_RPM_FINGERPRINT: '80FE0A7667A92A0AD3CEAE6D4C2FF8C3CC4E1599' }, }); assert.equal(result.status, 1); assert.deepEqual(JSON.parse(await readFile(evidence, 'utf8')), { key: false, passphrase: false }); diff --git a/apps/desktop/scripts/rpm-signing.mjs b/apps/desktop/scripts/rpm-signing.mjs index 2851118cd..aae5d600c 100644 --- a/apps/desktop/scripts/rpm-signing.mjs +++ b/apps/desktop/scripts/rpm-signing.mjs @@ -8,7 +8,8 @@ import { promisify } from 'node:util'; import { pathToFileURL } from 'node:url'; const execFile = promisify(execFileCallback); -export const OWNER_FINGERPRINT = 'DD4E7F65CE2345A1F4597D643CF856B53093D3A3'; +// Owner replacement key effective 2026-10-19; the previous key is historical, not cross-signed. +export const OWNER_FINGERPRINT = '80FE0A7667A92A0AD3CEAE6D4C2FF8C3CC4E1599'; const fingerprintPattern = /^[A-F0-9]{40}$/; export function requireRpmIdentity(identity) { diff --git a/apps/desktop/scripts/rpm-signing.test.mjs b/apps/desktop/scripts/rpm-signing.test.mjs index 347d9ca09..99e1f1c37 100644 --- a/apps/desktop/scripts/rpm-signing.test.mjs +++ b/apps/desktop/scripts/rpm-signing.test.mjs @@ -7,7 +7,7 @@ import { tmpdir } from 'node:os'; import { dirname, join, resolve } from 'node:path'; import { test } from 'node:test'; import { inspectSignedPreviewPayload } from './rpm-preview-payload.mjs'; -import { OWNER_FINGERPRINT, withKey, assertRpmSignatures, requireRpmIdentity, rpmContentDigest, signRpm, verifyRpm } from './rpm-signing.mjs'; +import { OWNER_FINGERPRINT, rpmIdentityFromEnvironment, withKey, assertRpmSignatures, requireRpmIdentity, rpmContentDigest, signRpm, verifyRpm } from './rpm-signing.mjs'; import { linuxPreviewTag, prepareLinuxPreview, readLinuxPreviewBundle, signLinuxPreviewBundle, stageLinuxPreviewDraft, publishLinuxPreviewDraft } from './linux-preview-release.mjs'; import { aptAcceptance } from './apt-auth-acceptance.mjs'; import { authAssets, aptAssets, signMetadata, verifyMetadata, verifyApt } from './linux-package-auth.mjs'; @@ -138,17 +138,76 @@ test('signed mode requires exact public identity inputs', async () => { } }); -test('documented owner public export has the exact complete RSA4096 identity and expiry', { - skip: missing.length ? `Missing tools: ${missing}` : false, -}, async () => { - const publicKey = await readFile(join(repositoryRoot, 'docs/static/keys/propr-desktop-release.asc'), 'utf8'); - await withKey({ fingerprint: OWNER_FINGERPRINT, publicKey }, async home => { +const PREVIOUS_FINGERPRINT = 'DD4E7F65CE2345A1F4597D643CF856B53093D3A3'; +const ownerExport = 'docs/static/keys/propr-desktop-release.asc'; +const historicalExport = `docs/static/keys/propr-desktop-release-historical-${PREVIOUS_FINGERPRINT}.asc`; + +async function inspectExport(path, fingerprint) { + const publicKey = await readFile(join(repositoryRoot, path), 'utf8'); + assert.doesNotMatch(publicKey, /PRIVATE KEY/); + return withKey({ fingerprint, publicKey }, async home => { const records = run('gpg', ['--homedir', home, '--with-colons', '--list-keys']).split('\n').map(l => l.split(':')); + assert.equal(records.filter(r => r[0] === 'pub').length, 1); + assert.equal(records.filter(r => r[0] === 'sub').length, 0); + assert.equal(run('gpg', ['--homedir', home, '--with-colons', '--list-secret-keys']).trim(), ''); const primary = records.find(r => r[0] === 'pub'); assert.equal(primary[2], '4096'); - assert.equal(new Date(Number(primary[5]) * 1000).toISOString(), '2026-10-12T13:07:27.000Z'); - assert.equal(new Date(Number(primary[6]) * 1000).toISOString(), '2028-10-11T13:11:25.000Z'); + assert.equal(primary[3], '1'); + return { publicKey, created: new Date(Number(primary[5]) * 1000).toISOString(), + expires: new Date(Number(primary[6]) * 1000).toISOString(), uids: records.filter(r => r[0] === 'uid').map(r => r[9]) }; + }); +} + +test('documented owner public export has the exact complete RSA4096 identity and expiry', { + skip: missing.length ? `Missing tools: ${missing}` : false, +}, async () => { + assert.equal(OWNER_FINGERPRINT, '80FE0A7667A92A0AD3CEAE6D4C2FF8C3CC4E1599'); + const owner = await inspectExport(ownerExport, OWNER_FINGERPRINT); + assert.deepEqual(owner.uids, ['ProPR Desktop Release Signing']); + assert.equal(owner.created, '2026-10-19T14:09:59.000Z'); + assert.equal(owner.expires, '2028-10-18T14:09:59.000Z'); + // The previous export stays published unchanged as historical public material only. + const previous = await inspectExport(historicalExport, PREVIOUS_FINGERPRINT); + assert.deepEqual(previous.uids, ['ProPR Desktop RPM Signing']); + assert.equal(previous.created, '2026-10-12T13:07:27.000Z'); + assert.equal(previous.expires, '2028-10-11T13:11:25.000Z'); + // Neither export can stand in for the other under either fingerprint. + await assert.rejects(withKey({ fingerprint: OWNER_FINGERPRINT, publicKey: previous.publicKey }, async () => {}), /pinned, usable RSA/); + await assert.rejects(withKey({ fingerprint: PREVIOUS_FINGERPRINT, publicKey: owner.publicKey }, async () => {}), /pinned, usable RSA/); +}); + +test('production environment pin accepts only the replacement owner fingerprint with its public export', { + skip: missing.length ? `Missing tools: ${missing}` : false, +}, async t => { + const saved = { fingerprint: process.env.PROPR_DESKTOP_RPM_FINGERPRINT, publicKey: process.env.PROPR_DESKTOP_RPM_PUBLIC_KEY }; + t.after(() => { + for (const [name, value] of [['PROPR_DESKTOP_RPM_FINGERPRINT', saved.fingerprint], ['PROPR_DESKTOP_RPM_PUBLIC_KEY', saved.publicKey]]) { + if (value === undefined) delete process.env[name]; else process.env[name] = value; + } }); + const ownerKey = await readFile(join(repositoryRoot, ownerExport), 'utf8'); + const previousKey = await readFile(join(repositoryRoot, historicalExport), 'utf8'); + const root = await mkdtemp(join(tmpdir(), 'propr-rpm-pin-')); + t.after(() => rm(root, { recursive: true, force: true })); + const disposable = await key(root, 'wrong-signer'); + for (const [fingerprint, publicKey] of [[PREVIOUS_FINGERPRINT, previousKey], [PREVIOUS_FINGERPRINT, ownerKey], + [disposable.identity.fingerprint, disposable.identity.publicKey], [OWNER_FINGERPRINT.toLowerCase(), ownerKey], + [OWNER_FINGERPRINT.slice(-16), ownerKey], [undefined, ownerKey]]) { + if (fingerprint === undefined) delete process.env.PROPR_DESKTOP_RPM_FINGERPRINT; + else process.env.PROPR_DESKTOP_RPM_FINGERPRINT = fingerprint; + process.env.PROPR_DESKTOP_RPM_PUBLIC_KEY = publicKey; + assert.throws(() => rpmIdentityFromEnvironment(), /differs from owner pin/); + } + process.env.PROPR_DESKTOP_RPM_FINGERPRINT = OWNER_FINGERPRINT; + process.env.PROPR_DESKTOP_RPM_PUBLIC_KEY = ownerKey; + const identity = rpmIdentityFromEnvironment(); + assert.deepEqual(identity, { fingerprint: OWNER_FINGERPRINT, publicKey: ownerKey }); + assert.equal(await withKey(identity, async () => 'accepted'), 'accepted'); + // A matching pin with mismatched public settings (old export or another signer) fails before signing. + for (const publicKey of [previousKey, disposable.identity.publicKey]) { + process.env.PROPR_DESKTOP_RPM_PUBLIC_KEY = publicKey; + await assert.rejects(withKey(rpmIdentityFromEnvironment(), async () => {}), /pinned, usable RSA/); + } }); test('signature status parsing ignores filename tokens but requires both pinned signatures', () => { diff --git a/docs/docs/operations/linux-release-key.md b/docs/docs/operations/linux-release-key.md index e5d6221ad..1675dadf7 100644 --- a/docs/docs/operations/linux-release-key.md +++ b/docs/docs/operations/linux-release-key.md @@ -1,16 +1,20 @@ # Linux desktop release key -The owner-provisioned Linux desktop release identity is: +The current owner-provisioned Linux desktop release identity, effective for new +Linux previews signed on or after **2026-10-19**, is: -**DD4E7F65CE2345A1F4597D643CF856B53093D3A3** +**80FE0A7667A92A0AD3CEAE6D4C2FF8C3CC4E1599** [Download the ASCII-armored public key](/keys/propr-desktop-release.asc). This is public information; the export contains no private key material. -The RSA4096 primary signing key was issued on **2026-10-12** and expires on -**2028-10-11**. Its historical user ID is `ProPR Desktop RPM Signing`; the same -identity authenticates the new DEB/RPM preview checksums and APT repository metadata. -It does not authenticate older unsigned DEBs retroactively. +The RSA4096 primary signing key has user ID `ProPR Desktop Release Signing`. It was +issued on **2026-10-19** and expires on **2028-10-18**. It has no subkeys; the +primary key itself signs. For new previews it signs native RPM headers and +payloads, the release `SHA256SUMS` (as `SHA256SUMS.asc`), and the APT repository +metadata (`APT-InRelease` and `APT-Release.gpg`). DEB payloads are unchanged and +carry no embedded signature; APT authenticates them through the signed metadata +and package hashes. This key does not authenticate older releases retroactively. Inspect the downloaded export with GnuPG without installing host trust: @@ -18,18 +22,68 @@ Inspect the downloaded export with GnuPG without installing host trust: gpg --show-keys --with-colons --with-fingerprint propr-desktop-release.asc ``` -Require exactly one `pub` record, RSA4096, and the full fingerprint above in its -following `fpr` record. Compare this notice through independently reviewed project -documentation, not only a key delivered alongside an installer. Reject expired, -revoked, or different keys. See [Linux package authentication](linux-rpm-signing.md) -for checksum verification and scoped APT trust. APT verifies repository metadata -and hashes, not an embedded signature inside each DEB. +Require exactly one `pub` record, RSA4096, no `sub` records, and the full +fingerprint above in its following `fpr` record. Compare this notice through +independently reviewed project documentation, not only a key delivered alongside +an installer. Reject expired, revoked, or different keys. See +[Linux package authentication](linux-rpm-signing.md) for checksum verification and +scoped APT trust. APT verifies repository metadata and hashes, not an embedded +signature inside each DEB. -The owner must keep encrypted offline backups and a revocation certificate under -restricted custody; this notice specifies the required procedure, not an audit of -those backups. Never put private exports, passwords, backup locations, or recovery -material in issues, documentation, artifacts, or CI logs. Test restoration using a -controlled owner process; implementation tests use disposable keys only. +## 2026-10-19 rotation from the previous identity + +The previous identity was: + +- Fingerprint **DD4E7F65CE2345A1F4597D643CF856B53093D3A3** +- User ID `ProPR Desktop RPM Signing`, RSA4096 primary signing key +- Issued **2026-10-12**, expires **2028-10-11** +- [Historical public export](/keys/propr-desktop-release-historical-DD4E7F65CE2345A1F4597D643CF856B53093D3A3.asc) + (byte-for-byte the export previously published as `propr-desktop-release.asc`) + +The owner no longer has the passphrase for the previous private key and generated +a replacement key locally. **No compromise has been reported**, and the previous +key has **not** been revoked. Because the old key cannot sign, the replacement is **not +cross-signed** by it. The transition is instead authenticated only by this +reviewed project documentation and the code pin in the authenticated +`integry/propr` repository: compare the new fingerprint here with the pin in +`apps/desktop/scripts/rpm-signing.mjs` on the reviewed main branch. Do not expect +or accept a "transition statement" signed by the old key. + +The previous key signs nothing new after this rotation. Releases that were +signed with it keep their original signatures, assets and trust classification +unchanged; verify them only with the historical export and its own fingerprint. +Verification against the new code pin says nothing about those older releases, +and nothing here re-labels or re-signs them. + +### Consumer trust updates + +To verify a new preview, obtain the new public export from this notice and confirm +its full fingerprint as above. Then: + +- **RPM**: import the new public key into the RPM database you use for ProPR + previews (`sudo rpmkeys --import propr-desktop-release.asc`, or the equivalent + `rpm --import`). `rpmkeys --checksig --verbose` must report both the header and + the header+payload signature with key ID `cc4e1599` (the fingerprint suffix). + Keep the old key only if you still need to verify older RPMs signed with it; + otherwise remove it (for example `sudo rpm -e gpg-pubkey-3093d3a3` on RPM 4.x). + It is not revoked, so removal is housekeeping rather than an emergency. +- **Direct downloads**: verify `SHA256SUMS.asc` in a fresh isolated keyring that + contains only the new export, then check `SHA256SUMS`. +- **APT repository bundle**: replace the source-scoped keyring named in + `signed-by=` with a binary export of the new key (or create a new keyring file + and point the new preview's `deb` line at it). Do not add either key to + `/etc/apt/trusted.gpg` or `trusted.gpg.d`. A repository bundle signed by the new + key fails `apt update` with a keyring containing only the old key; that failure + is expected and must not be overridden. + +## Custody, compromise and future rotation + +The owner must keep encrypted offline backups, the passphrase, and a revocation +certificate under restricted custody; this notice specifies the required +procedure, not an audit of those backups. Never put private exports, passwords, +backup locations, or recovery material in issues, documentation, artifacts, or CI +logs. Test restoration using a controlled owner process; implementation tests use +disposable keys only. For a suspected compromise or a key question, contact the repository maintainers through [integry/propr on GitHub](https://github.com/integry/propr/issues). @@ -42,11 +96,15 @@ must stop trusting the affected key; local RPM databases and scoped APT keyrings do not discover revocations automatically. Consult the latest reviewed notice before installing. -Before expiry or rotation, publish both complete fingerprints, effective dates, -and the replacement public export, authenticating the transition with the old -key where safe. Review the code pin and public settings together. Preserve -historical notices and immutable assets with their original trust classification; -never relabel them or bypass verification to accommodate expiry. +Before expiry or a future rotation, publish both complete fingerprints, effective +dates, and the replacement public export, authenticating the transition with the +old key where the owner still controls it. When the old key is unavailable, as in +the 2026-10-19 rotation, say so explicitly and rely on reviewed documentation. +Review the code pin and public settings together: the protected +`PROPR_DESKTOP_RPM_PUBLIC_KEY` and `PROPR_DESKTOP_RPM_FINGERPRINT` settings must +match the reviewed pin before any signing run. Preserve historical notices and +immutable assets with their original trust classification; never relabel them or +bypass verification to accommodate expiry. This notice and download are delivered through the normal reviewed documentation pipeline. They do not establish a live production APT endpoint. diff --git a/docs/docs/operations/linux-rpm-signing.md b/docs/docs/operations/linux-rpm-signing.md index 5ba4a1a16..323a3c8c7 100644 --- a/docs/docs/operations/linux-rpm-signing.md +++ b/docs/docs/operations/linux-rpm-signing.md @@ -1,8 +1,13 @@ # Linux package authentication New public Linux previews authenticate **both DEB and RPM packages, on x64 and -arm64**. The owner identity is **DD4E7F65CE2345A1F4597D643CF856B53093D3A3**. -See the independent [release-key notice and public download](linux-release-key.md). +arm64**. The owner identity for previews signed on or after 2026-10-19 is +**80FE0A7667A92A0AD3CEAE6D4C2FF8C3CC4E1599** (`ProPR Desktop Release Signing`, +RSA4096, expires 2028-10-18). It replaces +DD4E7F65CE2345A1F4597D643CF856B53093D3A3, whose passphrase is no longer available; +no compromise has been reported, the old key is not revoked, and it has not +cross-signed the new one. See the independent [release-key notice, rotation details and public +downloads](linux-release-key.md). The main-only `desktop-linux-signed-preview.yml` consumes the exact finalized four-package artifact from a successful main-dispatched unsigned preview run. @@ -25,6 +30,16 @@ Its compatibility names remain unchanged: | `PROPR_DESKTOP_RPM_PUBLIC_KEY` | Repository variable containing the public export | | `PROPR_DESKTOP_RPM_FINGERPRINT` | Repository variable with the complete owner fingerprint | +The code pin `OWNER_FINGERPRINT` in `apps/desktop/scripts/rpm-signing.mjs` is the +reviewed source of truth. Signing refuses to start unless +`PROPR_DESKTOP_RPM_FINGERPRINT` equals it exactly, the public export imports as +exactly that one unexpired, unrevoked RSA signing primary key, and the private key +matches it. For the 2026-10-19 rotation a human administrator separately replaces +the protected private-key and passphrase secrets and sets both public settings to +`80FE0A7667A92A0AD3CEAE6D4C2FF8C3CC4E1599` and the export in +`docs/static/keys/propr-desktop-release.asc`. Until then signing fails closed; +there is no fallback to the previous identity. + Private credentials are confined to the protected read-only signing job. The entry point removes them from the environment before package parsers run. GnuPG uses temporary private files, scrubbed subprocess environments, exact-primary @@ -78,7 +93,10 @@ explicitly authenticates direct DEB downloads; `apt install ./package.deb` alone does not establish that provenance. RPM users additionally require both native signatures with `rpmkeys --checksig --verbose`. Use `dnf --setopt=localpkg_gpgcheck=1` or ordinary `zypper install` after bootstrapping -the confirmed RPM key. Never override a missing key or failed signature. +the confirmed RPM key. After the 2026-10-19 rotation, import the new public key +(both signature lines must report key ID `cc4e1599`); a database holding only the +previous key reports `NOKEY` for new RPMs. Never override a missing key or failed +signature. ## Exported APT repository @@ -93,6 +111,8 @@ recovered from InRelease. Use a source-scoped binary or armored public keyring: deb [signed-by=/absolute/path/propr-desktop-release.gpg] file:/absolute/path/apt-repository preview main ``` +After the 2026-10-19 rotation, point `signed-by=` at a keyring containing the new +key only; a keyring holding just the previous key correctly rejects new metadata. The keyring and repository must be readable by APT. A locally served copy can use a local HTTP URL with the same scoped keyring. There is no production URL to configure. Run `apt update` before downloading, and stop on authentication/hash @@ -115,6 +135,13 @@ Resume failed staging with the same `propr-desktop-linux-signed-` artifa Do not re-sign or overwrite an existing candidate: signatures can change bytes. Unavailable inputs require a new explicitly selected source/run, not a fallback. +Rotation does not change history. Any preview already signed by +DD4E7F65CE2345A1F4597D643CF856B53093D3A3 keeps its immutable assets, signatures and +original classification; verify it with the [historical public +export](/keys/propr-desktop-release-historical-DD4E7F65CE2345A1F4597D643CF856B53093D3A3.asc). +The new code pin and key verify only previews signed on or after 2026-10-19 and do +not authenticate older releases. + Unsigned schema 2 remains private validation evidence and cannot be newly published. Historical schema 3 (`rpm-signed-preview`, `-rpm-signed`) authenticated RPMs only; its DEBs and claimed checksums were unsigned. Historical immutable @@ -187,7 +214,7 @@ key notice. Run from the repository root, with a new output directory: gh run download "$SIGNING_RUN_ID" \ --name "propr-desktop-linux-signed-$SIGNING_RUN_ID" --dir signed-preview export PROPR_DESKTOP_RPM_PUBLIC_KEY="$(cat propr-desktop-release.asc)" -export PROPR_DESKTOP_RPM_FINGERPRINT=DD4E7F65CE2345A1F4597D643CF856B53093D3A3 +export PROPR_DESKTOP_RPM_FINGERPRINT=80FE0A7667A92A0AD3CEAE6D4C2FF8C3CC4E1599 PROPR_DESKTOP_REAL_LINUX_PACKAGE_ACCEPTANCE=1 \ node apps/desktop/scripts/run-signed-installed-rpm-acceptance.mjs \ --rpm "signed-preview/ProPR-Desktop-$VERSION-linux-x64.rpm" \ diff --git a/docs/static/keys/propr-desktop-release-historical-DD4E7F65CE2345A1F4597D643CF856B53093D3A3.asc b/docs/static/keys/propr-desktop-release-historical-DD4E7F65CE2345A1F4597D643CF856B53093D3A3.asc new file mode 100644 index 000000000..5b0bbb8bb --- /dev/null +++ b/docs/static/keys/propr-desktop-release-historical-DD4E7F65CE2345A1F4597D643CF856B53093D3A3.asc @@ -0,0 +1,29 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBGrM248BEAC54UTrJXUw/iDesahSJLZ8vN8Z8zFtWrBjkuHWYPzqeT/b+dSY +VUmgbhyzPta1LWp6tJpLK54s0aGM+7WpElBA1GiVLttSVshqLGTxy0TYl1jcxN02 +HfqRJS+Je+RHqxPT1yky6wgpXcUHx73Tby06SypHl33xd0g89Sv3sFivQbwYHcvF +mzzpUbuWbYBIa35Soc7OG6nKxcBIn8aN1obXTq8Da/CXmrXh/2RveoMrhVI98T8b +cAlCZ2EFU+uKY5IGQltnQojU68ZNm8RKtmTnhq2bZskhfltSzx0hy7gRKRdzozfx +fdSN2xJaqNzuA5qBHnj4/V45jJcgEOVsnXISP4ro1NP0h96dAFmI+hjmCmh4HN9m +zS3EH53XQ/Vn03IlOf2tFe4Ywxfl5hgjhqNyBuqYXX5xUeUFw6p+s8mrrfEBWL1V +9Yvq+C/a+sjxfEzOUcXDJisiqszY3AuZcPVs6noVIvIlFTxw31INoA0oduqOeNQM +9waYd5pbq90IIM1y2yHIAj9cH1O163arHET6X/6NlNWjImb2sVgY49yuhmVggF30 +Gd1FrJrHHBW+IDCeh2LvVDras/M03NuQBY3O2Luxz8IiRe3V6d6OMSpQaqBVVmzm +M17C3V+jr6sDG/Hi4FCT/M5HuHi5ebnv8hPp/R8FDJyCbR3dVM26qJm7xQARAQAB +tBlQcm9QUiBEZXNrdG9wIFJQTSBTaWduaW5niQJXBBMBCABBAhsDBQsJCAcCAiIC +BhUKCQgLAgQWAgMBAh4HAheAFiEE3U5/Zc4jRaH0WX1kPPhWtTCT06MFAmrM3H0F +CQPCZ+4ACgkQPPhWtTCT06Mi0hAAmzhXnwWXYODbf5+9/bSMJhE/ise7wL0yslSP +Sr+3WG0/7PJ824l9zF81Z4dAd8fp7nFTfGTK6E3RcvInRWgmAhWV2+4r0xGOkB0f +EQrEh3URsSo2be82FeY185CkmbP3j3g3+ieMxVHCCzm9AGObhRq/EQlwZJ3B/wpS +h6vbBZ3gHJL9TKxNHMS3HWd17gaDAbizfJL8k+7MgeTRyTPdhDddhYDtm2Y3VFyO +IBDPFQE0e3wUFXmCWY7LIMkdWhGd0Q878PtBAf+L6fyo0f2ztIQ4MQp64KpCI3PG +gzzm2RvSZlkpTvxZNnHgD0CzccVDhTub/YieSkn18K6znL4wfjFHM5RmUGDjwA/x +A2dU8jo9HBC/ucoJBw1XNM/enPzGBUZtXOakHGmzE5v6cw9ESIkAFh5reFCMZPFu +n5HFZoABmw7v/iFN3i05c1TazVqxehIY4u1pDJMcM6yNQfHDMHf1FH25EKVzL46n +UYfNyicu8N8fiA+BOJ+Wp+PMDZNtxMmOyTYCGbFJcxmTgTYxwK/Ns99QBIsXoexS +uL/dnGTZQitFc0aC96EH4Q4yWMXuquiPNBpx+jih5sjWrESADMLP1U0tNogU7xyK +dA8U1MikayEV0iVsz3IKbipMg86CyC/YNfsmXAVOJCKfUEvEJNlHNbv7eJbW9qKr +SmHB3TE= +=U47I +-----END PGP PUBLIC KEY BLOCK----- diff --git a/docs/static/keys/propr-desktop-release.asc b/docs/static/keys/propr-desktop-release.asc index 5b0bbb8bb..3900413e8 100644 --- a/docs/static/keys/propr-desktop-release.asc +++ b/docs/static/keys/propr-desktop-release.asc @@ -1,29 +1,29 @@ -----BEGIN PGP PUBLIC KEY BLOCK----- -mQINBGrM248BEAC54UTrJXUw/iDesahSJLZ8vN8Z8zFtWrBjkuHWYPzqeT/b+dSY -VUmgbhyzPta1LWp6tJpLK54s0aGM+7WpElBA1GiVLttSVshqLGTxy0TYl1jcxN02 -HfqRJS+Je+RHqxPT1yky6wgpXcUHx73Tby06SypHl33xd0g89Sv3sFivQbwYHcvF -mzzpUbuWbYBIa35Soc7OG6nKxcBIn8aN1obXTq8Da/CXmrXh/2RveoMrhVI98T8b -cAlCZ2EFU+uKY5IGQltnQojU68ZNm8RKtmTnhq2bZskhfltSzx0hy7gRKRdzozfx -fdSN2xJaqNzuA5qBHnj4/V45jJcgEOVsnXISP4ro1NP0h96dAFmI+hjmCmh4HN9m -zS3EH53XQ/Vn03IlOf2tFe4Ywxfl5hgjhqNyBuqYXX5xUeUFw6p+s8mrrfEBWL1V -9Yvq+C/a+sjxfEzOUcXDJisiqszY3AuZcPVs6noVIvIlFTxw31INoA0oduqOeNQM -9waYd5pbq90IIM1y2yHIAj9cH1O163arHET6X/6NlNWjImb2sVgY49yuhmVggF30 -Gd1FrJrHHBW+IDCeh2LvVDras/M03NuQBY3O2Luxz8IiRe3V6d6OMSpQaqBVVmzm -M17C3V+jr6sDG/Hi4FCT/M5HuHi5ebnv8hPp/R8FDJyCbR3dVM26qJm7xQARAQAB -tBlQcm9QUiBEZXNrdG9wIFJQTSBTaWduaW5niQJXBBMBCABBAhsDBQsJCAcCAiIC -BhUKCQgLAgQWAgMBAh4HAheAFiEE3U5/Zc4jRaH0WX1kPPhWtTCT06MFAmrM3H0F -CQPCZ+4ACgkQPPhWtTCT06Mi0hAAmzhXnwWXYODbf5+9/bSMJhE/ise7wL0yslSP -Sr+3WG0/7PJ824l9zF81Z4dAd8fp7nFTfGTK6E3RcvInRWgmAhWV2+4r0xGOkB0f -EQrEh3URsSo2be82FeY185CkmbP3j3g3+ieMxVHCCzm9AGObhRq/EQlwZJ3B/wpS -h6vbBZ3gHJL9TKxNHMS3HWd17gaDAbizfJL8k+7MgeTRyTPdhDddhYDtm2Y3VFyO -IBDPFQE0e3wUFXmCWY7LIMkdWhGd0Q878PtBAf+L6fyo0f2ztIQ4MQp64KpCI3PG -gzzm2RvSZlkpTvxZNnHgD0CzccVDhTub/YieSkn18K6znL4wfjFHM5RmUGDjwA/x -A2dU8jo9HBC/ucoJBw1XNM/enPzGBUZtXOakHGmzE5v6cw9ESIkAFh5reFCMZPFu -n5HFZoABmw7v/iFN3i05c1TazVqxehIY4u1pDJMcM6yNQfHDMHf1FH25EKVzL46n -UYfNyicu8N8fiA+BOJ+Wp+PMDZNtxMmOyTYCGbFJcxmTgTYxwK/Ns99QBIsXoexS -uL/dnGTZQitFc0aC96EH4Q4yWMXuquiPNBpx+jih5sjWrESADMLP1U0tNogU7xyK -dA8U1MikayEV0iVsz3IKbipMg86CyC/YNfsmXAVOJCKfUEvEJNlHNbv7eJbW9qKr -SmHB3TE= -=U47I +mQINBGrWJLcBEAC5xx+vmLZ7WTWDtbBsxFygpAZh4zHkDYlNCG/6rDgXDdIpAlHe +7ifmcx9e2ahRKazLucdAsrjODh6UvnSn82w4itqnyHo+NdqbfO13bUFodtuJDzhh +c4VO1dYes/eim1rgwiL6kFUon7so6kG8P3/aBHUt7fMFAC1l2KnsoIzn3771jZfl +joLdkUPMeU++ETggEw12iO////R/ozpNikHrYfLrHcCbBGR8LxJdnl97NV8cLzD3 +ho7DJW1ms4uBtorc5gs6HvtyCgTyKZ8928ZE/IBAxS8toiqjJr9w5C8zBZYo5Qps +yDo+vS63ew2s072tx8X1TEQGILW9t52cUg36W/+MTyhqBMZ/h/5uqpGCN1YaOS1h +ES7t5VH7kFGGfytGPEjCbhDJgPJdgHmm+/ZVhV0h5Qb5MuSi4rb34HHu93Xxhm9s +EWGbolU/tcTTgF0MlQjxXhEtWUrs/93J7hHyylnWvcb5LWucU/11Sh++GP6of16v +WFDwM/pCS3bp9YsrRuKVKIiRSP+Vv5u2op5Ni7FaagP3ACoad07EyfWcnQaVeXKx +LzTw0PtBkw5+nw8TkI80sS1K8MSb+FGBzbP3B3r9coL6bvqAUEwFmn6izJg2wC80 +w6FDLcVj6frDOL7Dj5OMzOlYT2nP1p0AqJF404vLMu1DLYkn4UtC76BFcwARAQAB +tB1Qcm9QUiBEZXNrdG9wIFJlbGVhc2UgU2lnbmluZ4kCVwQTAQgAQRYhBID+CnZn +qSoK086ubUwv+MPMThWZBQJq1iS3AhsDBQkDwmcABQsJCAcCAiICBhUKCQgLAgQW +AgMBAh4HAheAAAoJEEwv+MPMThWZnsEP/2yG3zpnMensASh7U5XCtKNOh9fTaCss +3Ch/F/GtcBoNDbKwOlG9uVT5S3uFk79Dr4NG7v8wj40kxZMS6Hy9XbTjo8PQtWE+ +NR3+rdIuskND/jZrBcG/WQaLz3NQ62RWuq+gf1lYbKdnpM/opOO11/CRCL090vWG +/C+nhfi+mWhhpCExVY+nUZ4lpnT0tPGml36jQ1R+8fwqhgH8i3KkqXxg57O2AZHa +O+W7cIkN5ARElxbrXf8IhJhfGA2dfZqcFiK3M1BX2J+MNC+eufPC/iMqfFXoq8R9 +/uAi5WmWD/alhNvRz/Whm5OvX4Ky+Lqh+sul3Lb73khHQ1b9cUYXMMZdU1ec9ISH +LVr5WNOazi/QZirU2cNQku0oLYZBBGdhPeMmRiv/aql8CUUMbo1Ude6I/CesPUUu +hiNQj0Z+5q+SXmKhcTvxs792bWbaCO2FBQlFvd1yzvbDAKHJRh7WtmRnTKURe5F2 +JySijpGmuwvuZ4bNBObv6q1jWaUpJm3yZGQ/J1t1l7lL2KAZw87X0o6DmRliPmh0 +hw6tf0/o1iF+kXY1eaX/2PTjfIw0Lz3l9j/u5cMaYpQsd4iDfMfef5Hh/34M4vmi +D1mQ4LbZ103KYi7t0eWsZtVstrNiWkjL1KJILz/dMeT+sWP1u9Jz8Kw/hmn0OAjK +rI+mn5ht6WkR +=QZi8 -----END PGP PUBLIC KEY BLOCK-----