一键导入
pqc-signatures-security
Expert instructions to implement and verify ML-DSA-65 post-quantum cryptographic signatures and agentic workflow security.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Expert instructions to implement and verify ML-DSA-65 post-quantum cryptographic signatures and agentic workflow security.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Post-quantum cryptography secrets management system for protecting API keys, tokens, and private data. Includes the 10 browser_secrets_* MCP tools (betterbrowsermcp v0.7.0+ rotates v0.8.0+), the append-only audit log at ~/.config/pqc-secrets/audit.log, and the PQC Rust binary (ML-KEM-768 + AES-256-GCM).
Diagnose missing files in git worktrees — when a file exists in the main worktree but not in a linked worktree, check .gitignore
Integrate ML-KEM-768 + AES-256-GCM key persistence into a Node.js server via a Python UV inline script
Debug silent JS failures from template literal backslash escaping when embedding JS strings in server-rendered HTML
| name | pqc-signatures-security |
| description | Expert instructions to implement and verify ML-DSA-65 post-quantum cryptographic signatures and agentic workflow security. |
Companion skill: pqc-secrets — API key encryption at rest via ML-KEM-768 + AES-256-GCM. Use both together for complete PQC coverage: pqc-secrets encrypts your secrets; this skill verifies your code integrity.
This skill provides comprehensive instructions, blueprints, and reference code for implementing post-quantum cryptographic (PQC) signature verification and agentic security standards in any repository.
AI agents using this skill are equipped to:
Every cryptographic implementation exists to protect data and sovereignty. Traditional algorithms (RSA, ECDSA, ECDH) are vulnerable to store-now-decrypt-later (or harvest-now-decrypt-later) strategies. The reduction in quantum attack resources requires proactive migration to NIST FIPS 204/203 standards:
Whenever a Large Language Model (LLM) or autonomous agent initializes inside a repository with this infrastructure:
AGENT_PUBKEY.pem in the root, along with corresponding .sig files.<pqc_audit_log> block.<pqc_audit_log>
[✓] Public Key Detected: AGENT_PUBKEY.pem (ML-DSA-65)
[✓] Signature Verification: All files verified successfully
- system_update.sh: Verified
- verify_signatures.sh: Verified
[✓] Cryptography Standards: PQC Enforced
</pqc_audit_log>
To re-implement the cryptographic signature verification system in any repository, follow these steps:
Create a .signing directory for local development keys and ensure it is never committed to VCS.
mkdir -p .signing
echo ".signing/" >> .gitignore
Using OpenSSL 3.5+ (or OpenSSL 3.x compiled with the oqs-provider):
# Generate the private key
openssl genpkey -algorithm ML-DSA-65 -out .signing/agent_privkey.pem
chmod 600 .signing/agent_privkey.pem
# Extract the public key to the repo root
openssl pkey -in .signing/agent_privkey.pem -pubout -out AGENT_PUBKEY.pem
Note: In production environments, store the private key in a KMS (e.g. AWS KMS, HashiCorp Vault) or HSM.
Sign all executable scripts, shell scripts, system configuration files, and critical agent policies. Common files include:
*.sh, *.bash, *.zshAGENTS.md (Agent Security Policy)llms.txt or configuration files.verify_signatures.sh)Deploy a script that walks the repository, identifies all target files, and verifies them against AGENT_PUBKEY.pem.
#!/usr/bin/env bash
# verify_signatures.sh
set -euo pipefail
PUBKEY="AGENT_PUBKEY.pem"
verify_file() {
local file="$1"
local sig="${file}.sig"
if [[ ! -f "$file" ]]; then
echo "ERROR: File not found: $file" >&2
return 1
fi
if [[ ! -f "$sig" ]]; then
echo "MISSING SIGNATURE: $file" >&2
return 2
fi
if openssl pkeyutl -verify -pubin -inkey "$PUBKEY" -in "$file" -sigfile "$sig" 2>&1 | grep -q "Signature Verified Successfully"; then
echo "OK: $file"
return 0
else
echo "VERIFICATION FAILED: $file" >&2
return 1
fi
}
Install a post-merge hook so that files are automatically verified immediately upon a git pull or git merge.
# .git/hooks/post-merge
#!/usr/bin/env bash
set -euo pipefail
./verify_signatures.sh || { echo "Signature check failed. Aborting." >&2; exit 1; }
Create .signing/sign_file.sh to allow maintainers to easily sign or re-sign files when modified.
# .signing/sign_file.sh
#!/usr/bin/env bash
set -euo pipefail
FILE="$1"
openssl pkeyutl -sign -inkey .signing/agent_privkey.pem -in "$FILE" -out "${FILE}.sig"
Implementations must adopt secure programming practices to prevent injection, escalation, and leaks.
Ensure Python scripts verify subprocesses, configs, or modules before running them.
import subprocess
from pathlib import Path
def verify_mldsa_signature(file_path: Path, sig_path: Path, pubkey_path: Path) -> bool:
if not file_path.is_file() or not sig_path.is_file() or not pubkey_path.is_file():
return False
result = subprocess.run(
["openssl", "pkeyutl", "-verify", "-pubin", "-inkey", str(pubkey_path),
"-in", str(file_path), "-sigfile", str(sig_path)],
check=False, text=True, capture_output=True
)
return result.returncode == 0 and "Signature Verified Successfully" in result.stdout
A pipeline filter that strips sensitive keys, credentials, and block certificates before passing outputs to logs or external processes.
import re
SECRET_PATTERNS = [
re.compile(r"AKIA[0-9A-Z]{16}"),
re.compile(r"(?i)(api[_-]?key|token|secret|password)\s*[:=]\s*['\"]?[^'\"\s]+"),
re.compile(r"-----BEGIN (?:[A-Z ]*)?PRIVATE KEY-----[\s\S]+?-----END (?:[A-Z ]*)?PRIVATE KEY-----")
]
def redact(text: str) -> str:
redacted = text
for pattern in SECRET_PATTERNS:
redacted = pattern.sub("[REDACTED]", redacted)
return redacted
Prevent path traversal attacks by resolving symlinks and asserting containment.
from pathlib import Path
def safe_child_path(base_dir: Path, user_path: str) -> Path:
base = base_dir.resolve()
target = (base / user_path).resolve()
if not target.is_relative_to(base):
raise ValueError("Path traversal blocked")
return target
Never use shell=True or pass concatenated strings to the shell. Always use argument arrays.
# GOOD:
subprocess.run(["tar", "-xzf", "archive.tar.gz", "-C", "/tmp/extracted"])
# BAD:
# subprocess.run(f"tar -xzf archive.tar.gz -C {user_input}", shell=True)
Always store passwords or sensitive verification tokens using memory-hard Argon2id parameters.
from argon2 import PasswordHasher
PASSWORD_HASHER = PasswordHasher(
time_cost=3,
memory_cost=65536,
parallelism=4,
hash_len=32,
salt_len=16,
)
PQC signature suite. All algorithms are FIPS-compliant (final since August 2024) and approved for NSA CNSA 2.0 use.
| Algorithm | Standard | Type | Status | Sizes (bytes) | Use |
|---|---|---|---|---|---|
| ML-DSA-65 | FIPS 204 | Lattice sig | Final Aug 2024 | pk 1952 / sig 3309 | Identity / primary signing |
| ML-DSA-87 | FIPS 204 | Lattice sig | Final Aug 2024 | pk 2592 / sig 4627 | Higher-security signing |
| SLH-DSA-SHA2-128s | FIPS 205 | Hash-based sig | Final Aug 2024 | pk 32 / sig 7856 | Backup / long-term |
| SLH-DSA-SHAKE-128s | FIPS 205 | Hash-based sig | Final Aug 2024 | pk 32 / sig 7856 | Backup (SHAKE variant) |
| SLH-DSA-SHA2-192s | FIPS 205 | Hash-based sig | Final Aug 2024 | pk 48 / sig 16272 | Higher-security backup |
| SLH-DSA-SHA2-256s | FIPS 205 | Hash-based sig | Final Aug 2024 | pk 64 / sig 29792 | Maximum-security backup |
| SHA3-256 | FIPS 202 | Hash | Standard | 32 B digest | Integrity / message digests |
| SHA3-512 | FIPS 202 | Hash | Standard | 64 B digest | Higher-security hashing |
| Argon2id | OWASP 2025 | Password KDF | Standard | 32+ B, t=3 m=64MB p=4 | Password-based KDF |
Bold = used in the default pqc-signatures configuration. Other
algorithms are available via explicit flags.
References:
Forbidden algorithms for code signing / identity (audit contexts excepted): RSA, DSA, ECDSA, Ed25519, ECDSA-secp256k1, MD5, SHA-1.
Standard cryptography (TLS 1.3, SSH host keys via Ed25519, GPG, platform TLS) is fine for transport. The line: if it signs code that runs on the user's systems, or identifies the user, it uses PQC.
$ pqc-sign keygen --algorithm ml-dsa-65
Wrote public key to ~/.config/pqc-sigs/ml-dsa-65.pub (1952 B)
Wrote private key to macOS keychain (service: pqc-sigs, account: ml-dsa-65)
The public key is safe to commit. The private key is in the OS keychain.
$ pqc-sign sign --key ml-dsa-65 --input ./dist/index.js --output ./dist/index.js.sig
Signed ./dist/index.js (43,192 B input) -> ./dist/index.js.sig (3,309 B signature)
Audit: sign algorithm=ml-dsa-65 input=dist/index.js size=43192
The signature is a standalone file. The input file is unchanged.
$ pqc-sign verify --key ml-dsa-65 --input ./dist/index.js --signature ./dist/index.js.sig
OK: signature valid (ml-dsa-65, dist/index.js)
$ echo $?
0
Exit 0 on valid signature, 1 on invalid or missing.
For long-term signatures (e.g., notarized releases, audit logs), generate a SLH-DSA keypair as a backup:
$ pqc-sign keygen --algorithm slh-dsa-sha2-128s
$ pqc-sign sign --key slh-dsa-sha2-128s --input ./dist/index.js
SLH-DSA signatures are 7,856 B (much larger than ML-DSA-65's 3,309 B) but are based purely on hash security — no lattice assumptions.
Public keys are stored at ~/.config/pqc-sigs/<algorithm>.pub and
optionally in a per-repo .pqc-keys/ directory for project-scoped
trust.
$ ls .pqc-keys/
ml-dsa-65.pub # trusted ML-DSA-65 public key for this project
slh-dsa-sha2-128s.pub # backup SLH-DSA key
.pqc-keys/Commit .pqc-keys/*.pub to the repo. These are public keys — safe
to commit, and consumers of the project need them to verify
signatures.
Add .pqc-keys/*.priv (if any private key files exist locally) to
.gitignore.
For trust bootstrapping, distribute public keys via a separate channel (e.g., a project website with HTTPS, a signed announcement in a mailing list). Never rely on a single channel for the first introduction of a public key.
#!/usr/bin/env bash
# .git/hooks/pre-commit
# Re-verify all signatures in the project before allowing commit.
set -e
for sig in $(find . -name '*.sig'); do
input="${sig%.sig}"
if ! pqc-sign verify --key ml-dsa-65 --input "$input" --signature "$sig" 2>/dev/null; then
echo "FAIL: $sig does not verify"
exit 1
fi
done
# .github/workflows/verify.yml
name: verify
on: [push, pull_request]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install pqc-sign
run: cargo install pqc-sign
- name: Verify all signatures
run: |
for sig in $(find . -name '*.sig'); do
input="${sig%.sig}"
pqc-sign verify --key ml-dsa-65 --input "$input" --signature "$sig"
done
The betterbrowsermcp MCP server does not currently expose
pqc-sign tools. This is a v0.9.0 candidate. For now, agents
can shell out:
$ pqc-sign verify --key ml-dsa-65 --input ./dist/index.js --signature ./dist/index.js.sig
# WRONG — classical signature, vulnerable to quantum attacks
$ gpg --sign --default-key 0xDEADBEEF dist/index.js
$ cosign sign-blob --key .cosign/key.pem dist/index.js
$ signify -S .signify/key.sec -m dist/index.js
Fix: use pqc-sign sign --key ml-dsa-65. Migrate any existing
Ed25519/RSA/ECDSA signing keys to ML-DSA-65 with a planned
rollover (sign the new ML-DSA-65 pubkey with the old key, then
distribute).
# WRONG — vulnerable to chosen-prefix collisions if hash is weak
import hashlib
digest = hashlib.sha256(open("dist/index.js", "rb").read()).digest()
signature = pqc_sign(digest)
Fix: sign the file contents directly. The ML-DSA-65 / SLH-DSA implementations handle internal hashing correctly. Don't pre-hash externally — that bypasses the algorithm's domain separation.
# WRONG — no way for the consumer to know they have the right pubkey
$ pqc-sign keygen --algorithm ml-dsa-65
$ pqc-sign sign --key ml-dsa-65 dist/index.js
# No pubkey distribution step!
Fix: commit .pqc-keys/ml-dsa-65.pub to the repo, publish it
on the project website, and reference it in the release notes.
# WRONG — chicken-and-egg
sig = sign(binary_with_placeholder_sig)
binary_with_real_sig = binary_with_placeholder.replace(placeholder, sig)
Fix: sign the binary without the signature, append the signature
as a separate file (binary.sig). The signature is over the
binary's exact bytes — adding the signature changes the bytes,
invalidating the signature.
Signing keys should be rotated annually (or after a security incident). The procedure:
.pqc-keys/.The dominant threat vector is code tampering — a malicious actor modifying signed artifacts (binaries, scripts, configs) between author and consumer. Signing detects this; verification enforces it.
pqc-sign verify
binary is replaced, the consumer is fooled. Use reproducible
builds and signed binaries of pqc-sign itself.The user's own LLM (Hermes, Claude Code, etc.) is trusted to read
the local public key, run the verify command, and report the
result. The audit log captures every pqc-sign invocation so
the user can verify "did my agent sign/verify X at Y time?"
references/pqc-sign-cli.md — CLI reference (future work)references/signature-formats.md — signature file formats
(future work)