QuipNetwork/hashsigs-py
Slowing — last commit 8mo ago
weakest axiscopyleft license (AGPL-3.0) — review compatibility; single-maintainer (no co-maintainers visible)
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 8mo ago
- ✓AGPL-3.0 licensed
- ✓CI configured
Show all 7 evidence items →Show less
- ✓Tests present
- ⚠Slowing — last commit 8mo ago
- ⚠Solo or near-solo (1 contributor active in recent commits)
- ⚠AGPL-3.0 is copyleft — check downstream compatibility
What would change the summary?
- →Use as dependency Concerns → Mixed if: relicense under MIT/Apache-2.0 (rare for established libs)
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/quipnetwork/hashsigs-py)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/quipnetwork/hashsigs-py on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: QuipNetwork/hashsigs-py
Generated by RepoPilot · 2026-05-07 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/QuipNetwork/hashsigs-py shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Slowing — last commit 8mo ago
- Last commit 8mo ago
- AGPL-3.0 licensed
- CI configured
- Tests present
- ⚠ Slowing — last commit 8mo ago
- ⚠ Solo or near-solo (1 contributor active in recent commits)
- ⚠ AGPL-3.0 is copyleft — check downstream compatibility
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live QuipNetwork/hashsigs-py
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/QuipNetwork/hashsigs-py.
What it runs against: a local clone of QuipNetwork/hashsigs-py — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in QuipNetwork/hashsigs-py | Confirms the artifact applies here, not a fork |
| 2 | License is still AGPL-3.0 | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 283 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of QuipNetwork/hashsigs-py. If you don't
# have one yet, run these first:
#
# git clone https://github.com/QuipNetwork/hashsigs-py.git
# cd hashsigs-py
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of QuipNetwork/hashsigs-py and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "QuipNetwork/hashsigs-py(\\.git)?\\b" \\
&& ok "origin remote is QuipNetwork/hashsigs-py" \\
|| miss "origin remote is not QuipNetwork/hashsigs-py (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(AGPL-3\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"AGPL-3\\.0\"" package.json 2>/dev/null) \\
&& ok "license is AGPL-3.0" \\
|| miss "license drift — was AGPL-3.0 at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "hashsigs/__init__.py" \\
&& ok "hashsigs/__init__.py" \\
|| miss "missing critical file: hashsigs/__init__.py"
test -f "hashsigs/core.py" \\
&& ok "hashsigs/core.py" \\
|| miss "missing critical file: hashsigs/core.py"
test -f "python-bindings/src/lib.rs" \\
&& ok "python-bindings/src/lib.rs" \\
|| miss "missing critical file: python-bindings/src/lib.rs"
test -f "pyproject.toml" \\
&& ok "pyproject.toml" \\
|| miss "missing critical file: pyproject.toml"
test -f "tests/test_pure_python_basic.py" \\
&& ok "tests/test_pure_python_basic.py" \\
|| miss "missing critical file: tests/test_pure_python_basic.py"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 283 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~253d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/QuipNetwork/hashsigs-py"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
hashsigs-py is a Python package implementing WOTS+ (Winternitz One-Time Signature Plus), a post-quantum cryptographic signature scheme. It provides both a pure Python implementation and optional Rust acceleration via PyO3 bindings to hashsigs-rs, enabling high-performance one-time digital signatures with Keccak-256 hashing. Hybrid package structure: hashsigs/ contains pure Python core (core.py, init.py) with optional Rust extension imported from python-bindings/src/lib.rs (compiled to hashsigs._rust). Tests split across test_pure_python_basic.py (Python-only) and test_vectors_test.py (vector-based validation). Type stubs in _rust.pyi bridge the compiled module.
👥Who it's for
Cryptographers, security researchers, and developers building post-quantum cryptographic systems who need production-grade WOTS+ implementations with optional performance acceleration. Contributors familiar with Python/Rust hybrid projects and test-vector validation.
🌱Maturity & risk
Actively developed but pre-release (v0.0.2). Has CI/CD setup (.github/workflows/ci.yml, .gitlab-ci.yml), comprehensive test vectors (test_vectors/wotsplus_keccak256.json), and type checking (mypy.ini, py.typed marker). However, the 0.0.x version number and lack of stable release tags indicate it's still in stabilization phase—suitable for research but evaluate carefully for production use.
Low immediate risk: minimal external dependencies (pyo3, hashsigs-rs, tiny-keccak). Main risks are: (1) optional Rust compilation failure silently falls back to pure Python, masking performance expectations; (2) keccak provider required for vector tests but not enforced in core dependencies; (3) single-maintainer pattern (Richard T. Carback III) with unclear backup; (4) post-quantum crypto is still evolving—algorithm may shift with NIST standardization.
Active areas of work
Unknown from file structure alone—no recent commit data visible. The codebase shows infrastructure for both CI and publishing (workflows/publish.yml) and supports multiple Python versions (setup.py, tox.ini), suggesting active maintenance but no specific active issues or PRs evident from repo snapshot.
🚀Get running
git clone https://github.com/QuipNetwork/hashsigs-py.git && cd hashsigs-py && python3 -m venv .hashsigs && source .hashsigs/bin/activate && pip install -U pip pytest pytest-cov && pip install -v -e '.[rust,dev]' && pip install pycryptodome && pytest -q
Daily commands: Development: pytest -q --cov=hashsigs --cov-report=term-missing (full suite with Rust); pytest -q -m 'not requires_rust' (Python-only). Quick import: python -c 'import hashsigs; wots = hashsigs.WOTSPlus(); pk, sk = wots.generate_key_pair()'. Check Rust: python -c 'import hashsigs._rust as m; print("rust ext ok:", m)' (fails silently if not built).
🗺️Map of the codebase
hashsigs/__init__.py— Entry point that exports the public API and handles fallback between Rust and pure Python implementations.hashsigs/core.py— Contains the pure Python implementation of WOTS+ cryptographic primitives; fallback when Rust unavailable.python-bindings/src/lib.rs— Rust FFI layer that binds hashsigs-rs library to Python via PyO3; performance-critical path.pyproject.toml— Package configuration including version, dependencies, and build system specification for both pure Python and Rust builds.tests/test_pure_python_basic.py— Core test suite validating WOTS+ correctness; must pass before any release.tests/test_vectors_test.py— Cryptographic test vector validation ensuring implementation matches specification.
🧩Components & responsibilities
- hashsigs.init (Python 3.5+) — Public API entry point; exports WOTSPlus class with transparent fallback from Rust to Python implementation.
- Failure mode: ImportError on missing core.py or broken _rust module; failure cascades to user code.
- hashsigs.core (Pure Python) (Python stdlib (hashlib, hmac)) — Complete reference WOTS+ implementation: key generation, signing, verification, hash chain logic.
- Failure mode: Arithmetic/logic errors in hash chain iterations; slow on large message counts.
- python-bindings Rust FFI (Rust, PyO3 0.25, hashsigs-rs 0.0.2) — Thin PyO3 wrapper exposing hashsigs-rs functions (generate_key_pair, sign, verify) to Python.
- Failure mode: Segmentation fault if Rust code panics; binary incompatibility across Python versions.
- hashsigs-rs external crate (Rust) — Upstream Rust library implementing WOTS+ algorithm and hash operations; assumed correct.
- Failure mode: Incorrect algorithm implementation; timing side-channels; upstream bugs.
- undefined — undefined
🛠️How to make changes
Add a new hash function to WOTS+
- Add hash implementation to hashsigs/core.py in the WOTSPlus class or as utility function (
hashsigs/core.py) - Add corresponding Rust binding in python-bindings/src/lib.rs using PyO3 macros (
python-bindings/src/lib.rs) - Export new function in hashsigs/init.py with fallback logic to pure Python (
hashsigs/__init__.py) - Add test vectors to tests/test_vectors/ and validate in tests/test_vectors_test.py (
tests/test_vectors_test.py)
Add a new cryptographic primitive test
- Create test function in tests/test_pure_python_basic.py following existing test patterns (
tests/test_pure_python_basic.py) - If using test vectors, add JSON file to tests/test_vectors/ with known good outputs (
tests/test_vectors/wotsplus_keccak256.json) - Validate against both Python and Rust implementations by importing from hashsigs module (
tests/test_pure_python_basic.py)
Update package version and publish
- Increment version in pyproject.toml (
pyproject.toml) - Ensure all tests pass locally and on CI via .github/workflows/ci.yml (
.github/workflows/ci.yml) - Create a Git tag matching version; .github/workflows/publish.yml triggers automatically to build wheels and publish to PyPI (
.github/workflows/publish.yml)
🔧Why these technologies
- PyO3 (Rust bindings) — Enables optional high-performance Rust acceleration for WOTS+ operations while maintaining pure Python fallback; zero-cost abstraction when compiled.
- hashsigs-rs external crate — Offloads cryptographic algorithm correctness to a dedicated, audited Rust library; reduces maintenance burden and leverages Rust safety guarantees.
- tiny-keccak with Keccak feature — Provides constant-time Keccak-256 hashing required by WOTS+ specification; optional feature-flag reduces binary size.
- Python 3.x with type hints — Enables type checking via mypy (mypy.ini configured) for early error detection; py.typed marker signals type-aware consumers.
⚖️Trade-offs already made
-
Optional Rust acceleration with Python fallback
- Why: Maximizes compatibility (works on any Python install) while providing performance boost when Rust toolchain available.
- Consequence: Build process is conditional; test matrix must cover both paths; adds complexity to init.py fallback logic.
-
Separate python-bindings/ Cargo.toml from hashsigs/ pure Python code
- Why: Decouples cryptographic reference implementation from optimization layer; Rust build is optional.
- Consequence: Two build systems must be maintained; CI must test both pure Python and Rust paths independently.
-
Test vectors in JSON format (wotsplus_keccak256.json)
- Why: Language-agnostic specification for validation; can cross-validate against other WOTS+ implementations.
- Consequence: Requires JSON parsing overhead in tests; tight coupling to specific hash function (Keccak-256).
🚫Non-goals (don't propose these)
- Does not handle key derivation beyond WOTS+ key pair generation
- Not a full Merkle signature tree implementation (WOTS+ is leaf-level only)
- Does not provide key persistence, serialization, or secure storage
- Not a cryptographic library for general-purpose hashing or asymmetric crypto
- Does not include post-quantum security proofs or formal verification
🪤Traps & gotchas
(1) HASHSIGS_BUILD_RUST=0 environment variable must be set to skip Rust compilation and test pure Python only—not documented in main README. (2) Keccak provider (pycryptodome or pysha3) required for test_vectors_test.py but not in base dependencies—silent skip if missing. (3) Rust extension failure is silent (ImportError caught in init.py)—verify with 'python -c import hashsigs._rust' to confirm acceleration is active. (4) pysha3 build fails on Python 3.13 macOS; must use pycryptodome instead. (5) tox.ini and .flake8 config exists but invoke discipline differs across CI workflows.
🏗️Architecture
💡Concepts to learn
- WOTS+ (Winternitz One-Time Signature Plus) — Core algorithm this repo implements; understanding Winternitz chains, chaining functions, and parameter selection (w parameter) is essential to modify or extend the signature scheme
- Post-quantum cryptography — WOTS+ is designed to resist quantum computer attacks; context for understanding why this signature scheme exists and its security properties
- Keccak-256 / SHA-3 — WOTS+ relies on collision-resistant hash functions; this repo uses Keccak-256 specifically, available via pycryptodome or pysha3 in Python side and tiny-keccak in Rust
- PyO3 (Python ↔ Rust FFI) — Mechanism for optional Rust acceleration; understanding PyO3 extensions is needed to modify bindings or debug import errors in python-bindings/src/lib.rs
- One-time signatures (OTS) — WOTS+ is stateless one-time signature—each private key can only sign one message securely; reuse invalidates security, a key constraint for protocol design
- Merkle tree / hash-based signatures — WOTS+ is a building block for Merkle-signature-tree (MST) schemes; understanding how OTS chains combine into larger signature systems informs use cases
- Setuptools build extensions with optional Rust — pyproject.toml + setup.py orchestrate conditional Rust compilation; understanding [rust] extras and HASHSIGS_BUILD_RUST env var is needed to fix build issues or add new optional features
🔗Related repos
liboqs/liboqs-python— Official Python bindings for liboqs post-quantum crypto library; WOTS+ is one option but this is more comprehensive ecosystemQuipNetwork/hashsigs-rs— Parent Rust crate (hashsigs-rs 0.0.2) that this package wraps—source of truth for algorithm and core implementationtQxyz/wots— Alternative pure Python WOTS+ implementation; useful for cross-validation and understanding algorithm variantsPQClean/PQClean— Comprehensive post-quantum crypto clean-room implementations with multiple language bindings; shows broader ecosystem contextpyca/cryptography— Industry-standard Python cryptography bindings with Rust acceleration (via PyO3); architectural inspiration for hybrid Python/Rust design
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive test vectors and cross-validation tests between Python and Rust implementations
The repo has test_vectors/wotsplus_keccak256.json but tests/test_vectors_test.py appears incomplete (file name suggests it tests vectors but no actual validation is shown). This is critical for a cryptographic library to ensure Python and Rust implementations produce identical outputs. Currently only test_pure_python_basic.py exists, but no tests validate that the optional Rust acceleration (hashsigs._rust) produces identical results to pure Python on the same inputs.
- [ ] Extend tests/test_vectors_test.py to load and validate all test vectors from tests/test_vectors/wotsplus_keccak256.json
- [ ] Add tests that compare pure Python output (hashsigs.core) against Rust output (hashsigs._rust) for key generation, signing, and verification
- [ ] Add edge case tests in tests/ for boundary conditions (empty messages, max-length messages, invalid signatures)
- [ ] Ensure CI runs these tests with and without Rust bindings available
Add Rust build failure fallback with clear user warnings
The current setup.py and pyproject.toml build Rust bindings but there's no explicit handling or user communication if the Rust build fails (e.g., no Rust toolchain). The README mentions 'automatically build the Rust extension if available' but the actual fallback behavior isn't documented or tested. New contributors should add graceful degradation with informative warnings.
- [ ] Modify setup.py to catch Rust compilation failures and emit a clear warning message (e.g., via logging or print) explaining that pure Python fallback is being used
- [ ] Add a test in tests/ (e.g., test_fallback.py) that validates the package still functions correctly when hashsigs._rust import fails
- [ ] Update README.md to explicitly document the fallback behavior and what users can expect in terms of performance
- [ ] Add a helper function in hashsigs/init.py that checks and reports which implementation is active (see _rust.pyi for type hints)
Add parameter validation and security-focused unit tests for hashsigs/core.py
The core.py file implements pure Python WOTS+ but there are no visible tests specifically validating input constraints (key sizes, message formats, parameter bounds). For a cryptographic library, this is essential to prevent misuse. Test files reference WOTSPlus class but specific parameter validation tests are missing.
- [ ] Create tests/test_core_validation.py to test hashsigs/core.py parameter validation (invalid key sizes, null/empty messages, malformed private/public keys)
- [ ] Add tests for the WOTS+ parameter set consistency (Winternitz parameter w, hash function selection, output lengths)
- [ ] Verify that both hashsigs.core and hashsigs._rust (Rust bindings) reject invalid inputs identically
- [ ] Add docstring examples in hashsigs/core.py showing correct usage and referencing the validation tests
🌿Good first issues
- Add integration tests in tests/ that explicitly verify Rust extension is loaded and benchmarks pure Python vs. Rust performance—currently no perf tests in test suite
- Document the three test modes (All Tests, Basic with keccak, Basic without keccak) with exact pip install + pytest commands in CONTRIBUTING.md—currently hidden in README 'Test options' section
- Expand type coverage: hashsigs/core.py lacks type hints on function signatures (e.g., sign(), verify() return types); add stubs and regenerate _rust.pyi to match
📝Recent commits
Click to expand
Recent commits
645ae03— Try using a file instead. License fix #3 (rcarback)7d4a9e2— license build fix #2 (rcarback)4e8764c— Update license to fix build (rcarback)bad5347— Bump to v0.0.2 (rcarback)3b9d7bd— Update readme for pypi (rcarback)d591241— Attempt to fix the license warning (rcarback)8a35072— Try to fix windows (rcarback)ba69fe1— Add pytest-cov (rcarback)6b679a0— Try to build with rust whenever the opportunity arises, remove cibuildwheel (rcarback)1ccf487— Docker test env (rcarback)
🔒Security observations
The hashsigs-py project shows moderate security posture for a cryptographic library. Primary concerns include: (1) strong AGPL copyleft license which may limit adoption, (2) reliance on early-stage external Rust crates without clear security audit trails, (3) dual code paths (Rust/Python) for cryptographic operations increasing complexity, and (4) loose dependency version constraints. Strengths include use of established libraries (pyo3, tiny-keccak) and organized test structure. Recommendations: implement strict dependency management, complete security documentation, consider security audits of core dependencies, and ensure both implementation paths are equally audited.
- High · AGPL-3.0-or-later License Compatibility Risk —
python-bindings/Cargo.toml, COPYING. The project uses AGPL-3.0-or-later license which has strong copyleft requirements. Any proprietary software linking against this library must also be open-sourced. This could create legal/compliance issues for commercial users and may limit adoption. Fix: Review license compatibility with your use case. Consider dual-licensing or alternative licenses (MIT, Apache-2.0) if broader adoption is needed. Ensure all users understand the copyleft obligations. - Medium · Unvalidated External Rust Dependency —
python-bindings/Cargo.toml. The Cargo.toml depends on external crate 'hashsigs-rs' (version 0.0.2) from what appears to be an early-stage project. No version pinning strategy is visible, and early version numbers suggest potential API instability and security audit gaps. Fix: Pin exact versions of critical dependencies. Conduct security audit of hashsigs-rs crate. Monitor for security advisories using 'cargo audit'. Consider using hash verification for dependencies. - Medium · Build Process Security - Optional Rust Extension —
README.md, hashsigs/__init__.py. The README indicates the Rust extension is optional and falls back to pure Python. This creates two different code paths for cryptographic operations, increasing attack surface and complicating security maintenance. Users may unknowingly use the slower, less-audited Python implementation. Fix: Clearly document which implementation users are running. Consider making Rust extension mandatory for security-critical operations. Log warnings when pure Python fallback is used. Ensure both implementations are regularly audited and kept in sync. - Medium · Missing Dependency Version Constraints —
python-bindings/Cargo.toml. The pyo3 dependency uses flexible versioning (0.25) without upper bound constraints, and tiny-keccak uses version 2 without pinning. This could introduce breaking changes or security issues when dependencies update. Fix: Use semantic versioning constraints: 'pyo3 = ">=0.25,<0.26"' and 'tiny-keccak = ">=2.0,<3.0"'. Regularly audit dependencies and update deliberately rather than automatically. - Low · Incomplete README Documentation —
README.md. The README snippet appears truncated with incomplete sentences, suggesting incomplete documentation. This could lead to users misunderstanding security implications or usage requirements. Fix: Complete and review all documentation. Add security considerations section explicitly stating: cryptographic guarantees, known limitations, and security practices for key management. - Low · Missing Security Policy —
Repository root. No SECURITY.md file is visible in the repository structure. This makes it difficult for security researchers to responsibly disclose vulnerabilities. Fix: Create SECURITY.md file with vulnerability disclosure process, supported versions, and contact information for security issues. - Low · Test Vector Coverage Unclear —
tests/test_vectors/. Only wotsplus_keccak256.json test vector is visible. Insufficient test vector coverage could miss security issues in edge cases or alternative implementations. Fix: Expand test vector coverage. Include vectors from official WOTS+ specifications. Test boundary conditions and malformed input handling.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.