Compare commits

...
Author SHA1 Message Date
Emil 25fa6a488a Switch release signing to RSA-2048/SHA-256 for openssl compatibility
coordinator / test (push) Waiting to run
python / test (push) Waiting to run
release / binaries (amd64, darwin) (push) Waiting to run
release / binaries (amd64, linux) (push) Waiting to run
release / binaries (amd64, windows) (push) Waiting to run
release / binaries (arm64, darwin) (push) Waiting to run
release / binaries (arm64, linux) (push) Waiting to run
release / binaries (arm64, windows) (push) Waiting to run
release / wheel (push) Waiting to run
release / release (push) Blocked by required conditions
release / image (push) Waiting to run
users / test (push) Waiting to run
2026-08-04 07:40:47 +03:00
Emil 78dacb7e17 Use openssl dgst for Ed25519 (pkeyutl does not support the key type) 2026-08-04 07:35:26 +03:00
Emil c2c8336438 Sign release checksums with Ed25519 and verify them in the installers 2026-08-04 07:31:45 +03:00
3 changed files with 79 additions and 4 deletions
+14
View File
@@ -104,6 +104,20 @@ jobs:
working-directory: artifacts
run: sha256sum * > SHA256SUMS.txt
- name: sign the checksums (RSA-2048/SHA-256)
env:
KEY: ${{ secrets.SCIMESH_SIGNING_KEY }}
working-directory: artifacts
run: |
if [ -n "$KEY" ]; then
printf '%s\n' "$KEY" > /tmp/scimesh-sign-key.pem
openssl dgst -sha256 -sign /tmp/scimesh-sign-key.pem \
-out SHA256SUMS.txt.sig SHA256SUMS.txt
echo "signed SHA256SUMS.txt"
else
echo "SCIMESH_SIGNING_KEY is not set; releasing without a signature"
fi
- uses: softprops/action-gh-release@v2
with:
files: |
+40 -3
View File
@@ -8,6 +8,11 @@
# coordinator serve --open
$ErrorActionPreference = "Stop"
# Public half of the Ed25519 key that signs SHA256SUMS.txt in releases (see
# install.sh). Verification needs the openssl binary; without it the installer
# falls back to checksum verification with a warning.
$ScimeshSigningPubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA01rjmCme4W4zAgBwbO00LvwgnB1srlg0LbooRG8ej7iNxzOtJ8vjRFR2Cu7z7OKjoDo9/0GW3pvcwB+ndBB6yUwht33IRwdsnbioBI4M7LL+yC1ubi4fJ5bigOgZ9VsVqKdU3T9GYxmrfJF1UexiOg6HjoRLO3V4Id+3e/CiI5Sr8UMfJMXUfO3uiEs9RpstxpP1V/UU4YDicTF0QjkOESimEwwXBG4z3VcVmQtqkb7Q3413iekTdQ13093GKAKp0Q2ia1TpB2su6ELUhHAqhmK88cJ73Opy1uEVye0twov4BFTu5GkxgazNTuU//aYVWVpd/NAlD+VVSmpDsbfBBQIDAQAB"
$Repo = "emil28092005/SciMesh"
$Component = if ($env:SCIMESH_COMPONENT) { $env:SCIMESH_COMPONENT } else { "coordinator" }
$Version = if ($env:SCIMESH_VERSION) { $env:SCIMESH_VERSION } else { "latest" }
@@ -63,19 +68,51 @@ Invoke-WebRequest -Uri $Url -OutFile "$Target.tmp"
if ($env:SCIMESH_SKIP_VERIFY -ne "1") {
try {
$SumUrl = "https://github.com/$Repo/releases/download/$Version/SHA256SUMS.txt"
$Sums = (Invoke-WebRequest -Uri $SumUrl).Content
# Ed25519 signature over the checksum file, when openssl is present.
# Both files are fetched with -OutFile so their bytes match the
# release exactly (string pipelines would rewrite line endings).
$openssl = Get-Command openssl -ErrorAction SilentlyContinue
if ($env:SCIMESH_SKIP_SIGNATURE -ne "1" -and $openssl) {
$PubFile = Join-Path $env:TEMP "scimesh-signing-pub.pem"
$SumFile = Join-Path $env:TEMP ("scimesh-sums-" + [guid]::NewGuid().ToString("N") + ".txt")
$SigFile = "$SumFile.sig"
Set-Content -Path $PubFile -Value @("-----BEGIN PUBLIC KEY-----", $ScimeshSigningPubKey, "-----END PUBLIC KEY-----")
try {
Invoke-WebRequest -Uri $SumUrl -OutFile $SumFile
Invoke-WebRequest -Uri "$SumUrl.sig" -OutFile $SigFile
& $openssl.Source dgst -sha256 -verify $PubFile -signature $SigFile $SumFile 2>&1 | Out-Null
if ($LASTEXITCODE -eq 0) {
Write-Host "Signature verified (RSA-2048/SHA-256)"
} else {
Remove-Item -Force "$Target.tmp"
throw "the release signature does not verify; the download channel may be tampered with"
}
} catch {
Remove-Item -Force "$Target.tmp"
throw "signature verification failed: $($_.Exception.Message)"
} finally {
Remove-Item -Force $PubFile, $SumFile, $SigFile -ErrorAction SilentlyContinue
}
} elseif ($env:SCIMESH_SKIP_SIGNATURE -ne "1") {
Write-Host "WARNING: openssl not found; falling back to checksum verification only"
}
$BinaryName = Split-Path $Url -Leaf
$Line = ($Sums -split "`n") | Where-Object { $_.Trim().EndsWith(" " + $BinaryName) } | Select-Object -First 1
$SumFileCheck = Join-Path $env:TEMP ("scimesh-sums-check-" + [guid]::NewGuid().ToString("N") + ".txt")
Invoke-WebRequest -Uri $SumUrl -OutFile $SumFileCheck
$Line = (Get-Content $SumFileCheck -Raw -ErrorAction SilentlyContinue -split "`n") | Where-Object { $_.Trim().EndsWith(" " + $BinaryName) } | Select-Object -First 1
if ($Line) {
$Expected = ($Line -split "\s+")[0]
$Actual = (Get-FileHash -Algorithm SHA256 -Path "$Target.tmp").Hash.ToLower()
if ($Actual -ne $Expected.ToLower()) {
Remove-Item -Force "$Target.tmp"
Remove-Item -Force "$Target.tmp", $SumFileCheck
throw "checksum mismatch for $Binary (got $Actual, want $Expected)"
}
Write-Host "Checksum verified ($($Expected.Substring(0,12))...)"
} else {
Write-Host "WARNING: no checksum entry for $Binary; skipping verification"
Remove-Item -Force $SumFileCheck -ErrorAction SilentlyContinue
}
} catch {
Write-Host "WARNING: could not verify checksum ($($_.Exception.Message)); continuing"
+25 -1
View File
@@ -14,6 +14,13 @@
set -eu
REPO="emil28092005/SciMesh"
# Public half of the Ed25519 key that signs SHA256SUMS.txt in releases. The
# private half lives in the repository secret SCIMESH_SIGNING_KEY. Verification
# uses openssl when available; without openssl the installer falls back to the
# checksum-only check with a warning.
SCIMESH_SIGNING_PUBKEY='MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA01rjmCme4W4zAgBwbO00LvwgnB1srlg0LbooRG8ej7iNxzOtJ8vjRFR2Cu7z7OKjoDo9/0GW3pvcwB+ndBB6yUwht33IRwdsnbioBI4M7LL+yC1ubi4fJ5bigOgZ9VsVqKdU3T9GYxmrfJF1UexiOg6HjoRLO3V4Id+3e/CiI5Sr8UMfJMXUfO3uiEs9RpstxpP1V/UU4YDicTF0QjkOESimEwwXBG4z3VcVmQtqkb7Q3413iekTdQ13093GKAKp0Q2ia1TpB2su6ELUhHAqhmK88cJ73Opy1uEVye0twov4BFTu5GkxgazNTuU//aYVWVpd/NAlD+VVSmpDsbfBBQIDAQAB'
COMPONENT="${1:-coordinator}"
VERSION="${SCIMESH_VERSION:-latest}"
INSTALL_DIR="${SCIMESH_INSTALL_DIR:-$HOME/.local/bin}"
@@ -68,7 +75,24 @@ curl -fsSL -o "$TARGET.tmp" "$URL"
if [ "${SCIMESH_SKIP_VERIFY:-0}" != "1" ]; then
if SUMFILE=$(mktemp) && curl -fsSL -o "$SUMFILE" "https://github.com/${REPO}/releases/download/${VERSION}/SHA256SUMS.txt"; then
EXPECTED=$(awk '$2 == "'"$(basename "$URL")"'" {print $1}' "$SUMFILE" 2>/dev/null | head -1)
rm -f "$SUMFILE"
SIGFILE="$SUMFILE.sig"
if [ "${SCIMESH_SKIP_SIGNATURE:-0}" != "1" ] && command -v openssl >/dev/null 2>&1 \
&& curl -fsSL -o "$SIGFILE" "https://github.com/${REPO}/releases/download/${VERSION}/SHA256SUMS.txt.sig" 2>/dev/null; then
PUBKEY_FILE=$(mktemp)
printf '%s\n' '-----BEGIN PUBLIC KEY-----' "$SCIMESH_SIGNING_PUBKEY" '-----END PUBLIC KEY-----' > "$PUBKEY_FILE"
if openssl dgst -sha256 -verify "$PUBKEY_FILE" -signature "$SIGFILE" "$SUMFILE" >/dev/null 2>&1; then
echo "Signature verified (RSA-2048/SHA-256)"
else
rm -f "$PUBKEY_FILE" "$SIGFILE" "$SUMFILE" "$TARGET.tmp"
echo "ERROR: the release signature does not verify; the download channel may be tampered with." >&2
echo "Retry later, or bypass with SCIMESH_SKIP_SIGNATURE=1." >&2
exit 1
fi
rm -f "$PUBKEY_FILE"
elif [ "${SCIMESH_SKIP_SIGNATURE:-0}" != "1" ] && ! command -v openssl >/dev/null 2>&1; then
echo "WARNING: openssl not found; falling back to checksum verification only"
fi
rm -f "$SUMFILE" "$SIGFILE"
if [ -n "$EXPECTED" ]; then
ACTUAL=$(sha256sum "$TARGET.tmp" | awk '{print $1}')
if [ "$ACTUAL" != "$EXPECTED" ]; then