mirror of
https://github.com/saymrwulf/proof-aware-crypto-tooling-agent.git
synced 2026-09-04 20:03:40 +00:00
Fifth quorum member, first post-quantum one: verifies an SLH-DSA-SHA2-128s signature by calling slh_verify_128s, the extraction root the eleven fips205 certificates cover (apex fips205.slh_verify_128s_accepts_iff). Verify-only like the other four: quorum members judge, they never sign. Build discipline, because "built from the proven source" is a claim that has to survive a hostile reader: build-verify-slhdsa.sh REFUSES to build if the pinned checkout is dirty or at any commit other than a3ce8e8, exports the pinned commit via git archive (never a working copy), applies expose-mono.patch to that scratch copy, and then DIFFS the patched verify_mono.rs against the pinned one, aborting if any existing line changed rather than being appended. The patch is a visibility keyword plus its doc comment (the crate denies missing_docs, so pub mod alone does not compile) and one appended argument-assembly function whose body is the crate's own test helper. The extraction root is provably untouched. A provenance sidecar lands beside the binary: source commit, patch hash, main.rs hash, rustc, and a not_covered field naming what no certificate reaches — M-prime assembly (including the pure/prehash domain-separator byte), hex/file IO, the compiler; signing and keygen out of scope entirely. Demonstrated against OpenSSL 3.5.5 on a throwaway key: valid signature OK both ways, wrong message INVALID, corrupted signature INVALID. The agreement is itself a finding — this binary assembles M' = 0x00 || 0x00 || payload (pure variant, empty context) and OpenSSL evidently does the same. Convention matches the other members: template + main.rs + patch + build script tracked; rendered Cargo.toml, lock, target/ and the .build-slhdsa scratch tree ignored. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
102 lines
4.9 KiB
Bash
Executable file
102 lines
4.9 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Build pacta-verify-slhdsa from the PINNED proven source.
|
|
#
|
|
# The pinned checkout is never modified. This script exports the pinned commit
|
|
# into a scratch tree, applies expose-mono.patch there, builds against that, and
|
|
# records exactly what went in. If the pinned checkout is dirty, or is not at
|
|
# the commit the attestation names, it refuses: a quorum member built from a
|
|
# tree nobody can identify is a quorum member that proves nothing.
|
|
set -euo pipefail
|
|
|
|
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
SRC="${FIPS205_SOURCE:-$HOME/GitClone/FormalVerification/sources/fips205-source}"
|
|
PIN="${FIPS205_PIN:-a3ce8e8}"
|
|
BUILD="${BUILD_DIR:-$HERE/.build-slhdsa}"
|
|
OUT="$HERE/verify-slhdsa/target/release/pacta-verify-slhdsa"
|
|
|
|
echo "=== pacta-verify-slhdsa: build from the proven source ==="
|
|
|
|
[ -d "$SRC/.git" ] || { echo "FATAL: '$SRC' is not a git checkout of fips205-source."; exit 2; }
|
|
HEAD_SHA="$(git -C "$SRC" rev-parse HEAD)"
|
|
case "$HEAD_SHA" in
|
|
"$PIN"*) ;;
|
|
*) echo "FATAL: pinned source is at ${HEAD_SHA:0:8}, expected $PIN."
|
|
echo " The certificates cover $PIN. Building a 'proven' verifier from any"
|
|
echo " other tree would be a claim nobody can check."; exit 1;;
|
|
esac
|
|
if [ -n "$(git -C "$SRC" status --porcelain)" ]; then
|
|
echo "FATAL: the pinned source has uncommitted changes:"
|
|
git -C "$SRC" status --porcelain | sed 's/^/ /'
|
|
echo " Refusing: the binary must correspond to a nameable tree."; exit 1
|
|
fi
|
|
echo " pinned source $SRC @ ${HEAD_SHA:0:8} (clean)"
|
|
|
|
# Export the pinned commit, never a working copy.
|
|
rm -rf "$BUILD"; mkdir -p "$BUILD"
|
|
git -C "$SRC" archive --format=tar "$HEAD_SHA" | tar -x -C "$BUILD"
|
|
echo " exported $(find "$BUILD" -type f | wc -l) files from $PIN"
|
|
|
|
# --- the two changes, applied verbatim and then VERIFIED to be present -------
|
|
LIB="$BUILD/src/lib.rs"; VM="$BUILD/src/verify_mono.rs"
|
|
grep -q '^mod verify_mono;' "$LIB" || { echo "FATAL: 'mod verify_mono;' not found in lib.rs — the source moved."; exit 1; }
|
|
# The crate is `#![deny(missing_docs)]`, so a module cannot become public
|
|
# without a doc comment. The comment is part of the visibility change, not an
|
|
# extra edit: `pub mod` alone does not compile here.
|
|
sed -i 's|^mod verify_mono;|/// Aeneas-compat monomorphic verify path: the extraction root the eleven\n/// certificates cover (apex `fips205.slh_verify_128s_accepts_iff`). Public only\n/// so a quorum binary can call the proven function; see expose-mono.patch.\npub mod verify_mono;|' "$LIB"
|
|
|
|
cat >> "$VM" <<'RUST'
|
|
|
|
/// Byte-level entry to the PROVEN root, for out-of-crate callers.
|
|
///
|
|
/// Assembles arguments only; the body is the crate's own test helper
|
|
/// `internal_inputs` followed by the call. `mprime` is FIPS 205's M' and is
|
|
/// built by the CALLER — its construction is outside every certificate
|
|
/// (TRUSTED-BASE item 10), which is why it is a parameter and not computed
|
|
/// here.
|
|
pub fn verify_mono_bytes(mprime: &[u8], sig_bytes: &[u8; 7856], pk_bytes: &[u8; 32]) -> bool {
|
|
let mut pk_seed = [0u8; 16];
|
|
let mut pk_root = [0u8; 16];
|
|
pk_seed.copy_from_slice(&pk_bytes[0..16]);
|
|
pk_root.copy_from_slice(&pk_bytes[16..32]);
|
|
let pk = SlhPublicKey { pk_seed, pk_root };
|
|
let sig = SlhDsaSig::<12, 7, 9, 14, 35, 16>::deserialize(sig_bytes);
|
|
slh_verify_128s(mprime, &sig, &pk)
|
|
}
|
|
RUST
|
|
|
|
# The extraction root must be untouched. Compare it against the pinned tree.
|
|
if ! diff <(git -C "$SRC" show "$HEAD_SHA:src/verify_mono.rs") \
|
|
<(head -n "$(git -C "$SRC" show "$HEAD_SHA:src/verify_mono.rs" | wc -l)" "$VM") > /dev/null; then
|
|
echo "FATAL: the patch altered existing lines of verify_mono.rs, not just appended."
|
|
exit 1
|
|
fi
|
|
echo " patched lib.rs visibility + verify_mono_bytes appended (existing lines unchanged)"
|
|
|
|
# --- render Cargo.toml from the template ------------------------------------
|
|
sed "s|{{SOURCE}}|$BUILD|g" "$HERE/verify-slhdsa/Cargo.toml.template" > "$HERE/verify-slhdsa/Cargo.toml"
|
|
|
|
echo " building..."
|
|
( cd "$HERE/verify-slhdsa" && cargo build --release 2>&1 | tail -5 | sed 's/^/ /' )
|
|
|
|
[ -x "$OUT" ] || { echo "FATAL: build produced no binary at $OUT"; exit 1; }
|
|
|
|
cat > "$HERE/verify-slhdsa/target/release/pacta-verify-slhdsa.provenance.json" <<JSON
|
|
{
|
|
"binary_sha256": "$(sha256sum "$OUT" | cut -d' ' -f1)",
|
|
"source_repo": "fips205-source",
|
|
"source_commit": "$HEAD_SHA",
|
|
"patch": "expose-mono.patch",
|
|
"patch_sha256": "$(sha256sum "$HERE/verify-slhdsa/expose-mono.patch" | cut -d' ' -f1)",
|
|
"main_sha256": "$(sha256sum "$HERE/verify-slhdsa/src/main.rs" | cut -d' ' -f1)",
|
|
"proven_root": "slh_verify_128s",
|
|
"parameter_set": "SLH-DSA-SHA2-128s",
|
|
"certificates": 11,
|
|
"apex": "fips205.slh_verify_128s_accepts_iff",
|
|
"not_covered": "M-prime assembly (domain separator, context length), hex/file IO, and the compiler. Signing and keygen are out of scope entirely.",
|
|
"rustc": "$(rustc --version)"
|
|
}
|
|
JSON
|
|
|
|
echo " binary $OUT"
|
|
echo " sha256 $(sha256sum "$OUT" | cut -c1-16)…"
|
|
echo " provenance written beside the binary"
|