mirror of
https://github.com/JGoyd/JGoyd.git
synced 2026-06-25 10:39:57 +02:00
JGoyd Public Evidence System: 187 Verifiable Events | 5 CVE Rescores | 27 Global
Cases
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env bash
|
||||
# anchor.sh — Hash, PGP-sign, and OpenTimestamps-anchor a single artifact.
|
||||
#
|
||||
# Usage: ./anchor.sh path/to/artifact.eml
|
||||
# Effect: Produces <artifact>.sha256, <artifact>.asc, <artifact>.ots in the same directory.
|
||||
#
|
||||
# Requirements:
|
||||
# gpg (with the canonical signing key already imported and the fingerprint
|
||||
# configured below or in env var GOYD_PGP_FPR)
|
||||
# sha256sum (coreutils)
|
||||
# ots (pip install opentimestamps-client)
|
||||
#
|
||||
# Resilience notes:
|
||||
# - We sign the hash FILE, not the artifact directly. This is so a verifier
|
||||
# can cheaply check "this artifact is the one I anchored" without re-reading
|
||||
# a multi-MB file.
|
||||
# - We OTS-anchor the hash FILE for the same reason: small file, fast Bitcoin
|
||||
# attestation, no need to push the artifact body anywhere.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# -ne 1 ]]; then
|
||||
echo "usage: $0 <artifact-path>" >&2
|
||||
exit 64
|
||||
fi
|
||||
|
||||
ART="$1"
|
||||
if [[ ! -f "$ART" ]]; then
|
||||
echo "not a file: $ART" >&2
|
||||
exit 66
|
||||
fi
|
||||
|
||||
# CHOOSE ONE canonical signing key. The user currently has two fingerprints in
|
||||
# circulation; reconcile before using this script in production.
|
||||
FPR="${GOYD_PGP_FPR:-4A041F506D894F5EE391743864878B56A2EB2D11}"
|
||||
|
||||
DIR="$(dirname "$ART")"
|
||||
BASE="$(basename "$ART")"
|
||||
HASH_FILE="${ART}.sha256"
|
||||
SIG_FILE="${ART}.asc"
|
||||
OTS_FILE="${HASH_FILE}.ots"
|
||||
|
||||
# 1. Hash
|
||||
( cd "$DIR" && sha256sum "$BASE" ) > "$HASH_FILE"
|
||||
echo "wrote $HASH_FILE"
|
||||
|
||||
# 2. PGP-sign the artifact (detached, armored)
|
||||
gpg --local-user "$FPR" --armor --detach-sign --output "$SIG_FILE" "$ART"
|
||||
echo "wrote $SIG_FILE"
|
||||
|
||||
# 3. PGP-sign the hash file too (so a verifier can cheaply confirm the binding)
|
||||
gpg --local-user "$FPR" --armor --detach-sign --output "${HASH_FILE}.asc" "$HASH_FILE"
|
||||
echo "wrote ${HASH_FILE}.asc"
|
||||
|
||||
# 4. OpenTimestamps-anchor the hash file
|
||||
ots stamp "$HASH_FILE"
|
||||
echo "wrote $OTS_FILE (pending Bitcoin confirmation, run 'ots upgrade' later)"
|
||||
|
||||
echo
|
||||
echo "Verification commands a third party will run:"
|
||||
echo " sha256sum -c $HASH_FILE"
|
||||
echo " gpg --verify $SIG_FILE $ART"
|
||||
echo " gpg --verify ${HASH_FILE}.asc $HASH_FILE"
|
||||
echo " ots verify $OTS_FILE"
|
||||
@@ -0,0 +1,90 @@
|
||||
# Publishing your canonical PGP key
|
||||
|
||||
Before anchoring any evidence, the public must be able to fetch your signing key
|
||||
without trusting you. Do this once.
|
||||
|
||||
## Step 0 — Reconcile keys
|
||||
|
||||
You have two fingerprints in public circulation today. Pick one as canonical
|
||||
and either:
|
||||
- Revoke the other and publish the revocation certificate, or
|
||||
- Sign a public cross-attestation from each key to the other so a verifier can
|
||||
walk between them. Save it as `canonical/key-cross-attestation.txt.asc`.
|
||||
|
||||
Until this is done, ANY verifier hitting your evidence will reasonably ask
|
||||
which fingerprint is correct.
|
||||
|
||||
Pick CANONICAL_FPR before continuing:
|
||||
```bash
|
||||
CANONICAL_FPR=4A041F506D894F5EE391743864878B56A2EB2D11 # or the 6DCB… fingerprint
|
||||
```
|
||||
|
||||
## Step 1 — Export the public key (ASCII-armored)
|
||||
|
||||
```bash
|
||||
gpg --armor --export "$CANONICAL_FPR" > canonical/jgoyd-pgp-public.asc
|
||||
```
|
||||
|
||||
Commit this file to `/canonical/` in the public repo.
|
||||
|
||||
## Step 2 — Upload to multiple independent keyservers
|
||||
|
||||
```bash
|
||||
# keys.openpgp.org — verified-email keyserver, the default modern hub
|
||||
gpg --keyserver hkps://keys.openpgp.org --send-keys "$CANONICAL_FPR"
|
||||
# You will receive an email at the UID address; click the link to publish the UIDs.
|
||||
|
||||
# Ubuntu (SKS-style)
|
||||
gpg --keyserver hkps://keyserver.ubuntu.com --send-keys "$CANONICAL_FPR"
|
||||
|
||||
# MIT (SKS-style, legacy but still queried by many clients)
|
||||
gpg --keyserver hkps://pgp.mit.edu --send-keys "$CANONICAL_FPR"
|
||||
```
|
||||
|
||||
## Step 3 — Cross-publish the fingerprint everywhere it can be checked
|
||||
|
||||
Place the same fingerprint string in:
|
||||
|
||||
- `github.com/JGoyd` profile README — `/canonical/index.md` mirror committed there.
|
||||
- `keybase.io/<handle>` profile (if used).
|
||||
- LinkedIn "About" section.
|
||||
- Substack bio.
|
||||
- Mastodon / Bluesky profile bio.
|
||||
- DNS TXT record on a domain you own — e.g.:
|
||||
```
|
||||
_pgp.your-domain.example. IN TXT "openpgp-fingerprint=4A041F506D894F5EE391743864878B56A2EB2D11"
|
||||
```
|
||||
This anchors the key to a domain a registrar controls, not you alone.
|
||||
- If you control a TLS-served site, publish a `/.well-known/openpgpkey/...` Web Key Directory entry per RFC 7929.
|
||||
|
||||
The more independent fingerprint witnesses, the harder it becomes to fake your key.
|
||||
|
||||
## Step 4 — Sign an attestation file linking the key to your identity
|
||||
|
||||
```bash
|
||||
cat > canonical/identity-attestation.txt <<'TXT'
|
||||
I, Joseph R. Goydish II, attest that the OpenPGP key with fingerprint
|
||||
4A04 1F50 6D89 4F5E E391 7438 6487 8B56 A2EB 2D11
|
||||
is my canonical signing key for all evidence published under github.com/JGoyd.
|
||||
|
||||
Cross-references:
|
||||
- github.com/JGoyd (profile)
|
||||
- github.com/JGoyd/Running-Ledger
|
||||
- keys.openpgp.org
|
||||
- keyserver.ubuntu.com
|
||||
- pgp.mit.edu
|
||||
TXT
|
||||
gpg --local-user "$CANONICAL_FPR" --clearsign canonical/identity-attestation.txt
|
||||
```
|
||||
|
||||
Commit `canonical/identity-attestation.txt.asc` to the public repo.
|
||||
OpenTimestamps-anchor it: `ots stamp canonical/identity-attestation.txt.asc`.
|
||||
|
||||
## Step 5 — Verify, as a third party would
|
||||
|
||||
From a clean machine:
|
||||
```bash
|
||||
gpg --keyserver hkps://keys.openpgp.org --recv-keys 4A041F506D894F5EE391743864878B56A2EB2D11
|
||||
gpg --verify canonical/identity-attestation.txt.asc
|
||||
```
|
||||
Expect: `Good signature` and a UID matching the email address on the key.
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
# upgrade_ots.sh — Walk every .ots in /evidence and run `ots upgrade` to pull
|
||||
# the latest Bitcoin attestation into the file. Safe to run on a cron.
|
||||
#
|
||||
# Usage: ./upgrade_ots.sh /path/to/evidence/root
|
||||
#
|
||||
# A fresh `ots stamp` produces an incomplete proof referencing a calendar
|
||||
# server. After the next Bitcoin block confirms (~10 min) and a few more
|
||||
# confirmations land, `ots upgrade` rewrites the .ots file in-place to include
|
||||
# the full Bitcoin-attested proof. Once upgraded, the .ots file is permanently
|
||||
# verifiable even if every calendar server disappears.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="${1:-./evidence}"
|
||||
if [[ ! -d "$ROOT" ]]; then
|
||||
echo "not a directory: $ROOT" >&2
|
||||
exit 66
|
||||
fi
|
||||
|
||||
find "$ROOT" -name '*.ots' -print0 | while IFS= read -r -d '' f; do
|
||||
echo "upgrading: $f"
|
||||
ots upgrade "$f" || echo " (still pending — try again later)"
|
||||
done
|
||||
Reference in New Issue
Block a user