A Falcon REST API implementation that handles KERI (Key Event Receipt Infrastructure) signed requests and responses for registering and retrieving user data.
This API provides two endpoints:
- POST /register: Register user data with KERI signatures
- GET /read: Retrieve user data by name, AID, or SAID with KERI signatures
All requests and responses are cryptographically signed using KERI signatures, ensuring authenticity and integrity without requiring trust in a third party.
- Clone the repository:
git clone <repository-url>
cd keripy- Install dependencies using uv (or your preferred package manager):
uv sync- Activate the virtual environment:
source .venv/bin/activateGunicorn is included in the dependencies and is the recommended way to run the API:
Basic usage:
gunicorn --bind 127.0.0.1:8000 main:appFor development with auto-reload:
gunicorn --reload --bind 127.0.0.1:8000 main:appCustomize the server:
# Use a different port
gunicorn --bind 127.0.0.1:8080 main:app
# Use a different host
gunicorn --bind 0.0.0.0:8000 main:app
# Combine options
gunicorn --reload --bind 0.0.0.0:8080 main:appThe provided main script can be used with Waitress for development, but Waitress is not installed by default:
- Install Waitress:
uv add waitress- Run the server:
python main.pyThis will start the server on http://127.0.0.1:8000 using Waitress.
Customize the server:
# Use a different port
python main.py --port 8080
# Use a different host
python main.py --host 0.0.0.0
# Use gunicorn instead (note: gunicorn should be run directly, see Option 1)
python main.py --server gunicorn- Install Waitress:
uv add waitress- Run the server:
waitress-serve --port=8000 main:appOnce the server is running, you can verify it's working by checking the endpoints:
# Health check (will return 404, but confirms server is running)
curl http://localhost:8000/readThe API will be available at:
POST http://localhost:8000/registerGET http://localhost:8000/read
Run the test suite using pytest:
pytestTo run with verbose output:
pytest -vRegister user data with a KERI signature.
Request:
- Body: JSON SAD (Self-Addressing Data) structure:
{ "d": "SAID_VALUE", "i": "AID_VALUE", "n": "User Name" } - Headers:
Signature: RFC8941-compliant signature header signing the SAID value (dfield)
Response:
- Status: 200 OK
- Body: JSON SAD with SAID
- Headers:
Signature: Signature header signed by host AID on response body SAID
Example Request:
curl -X POST http://localhost:8000/register \
-H "Content-Type: application/json" \
-H "Signature: indexed=\"?1\";0=\"C0EF9012...\"" \
-d '{"d":"Eabc123...","i":"EGqHykT1gVyuWxsVW6LUUsz_KtLJGYMi_SrohInwvjC-","n":"John Doe"}'Example Response:
{
"d": "Eabc123...",
"i": "EGqHykT1gVyuWxsVW6LUUsz_KtLJGYMi_SrohInwvjC-",
"n": "John Doe"
}Retrieve user data by name, AID, or SAID with a KERI signature.
Request:
- Query Parameters: One of:
name=User NameAID=AID_VALUESAID=SAID_VALUE
- Headers:
Signature: RFC8941-compliant signature header signing a digest of the query parameter string
Response:
- Status: 200 OK (if found) or 404 Not Found
- Body: JSON SAD with SAID (if found)
- Headers:
Signature: Signature header signed by host AID on response body SAID (only on success)
Example Request:
curl -X GET "http://localhost:8000/read?name=John%20Doe" \
-H "Signature: indexed=\"?1\";0=\"C0EF9012...\""Example Response:
{
"d": "Eabc123...",
"i": "EGqHykT1gVyuWxsVW6LUUsz_KtLJGYMi_SrohInwvjC-",
"n": "John Doe"
}The API uses RFC8941 Structured Field Values format for the Signature header. Signatures are indexed signatures using the Siger class from keripy.
Format:
Signature: indexed="?1";0="<signature_value>"
Where:
indexed="?1"indicates indexed signatures0="<signature_value>"is the signature value for key index 0
Error responses (4xx, 5xx) do not include Signature headers. Common error codes:
- 400 Bad Request: Invalid JSON, missing required fields, or missing query parameters
- 401 Unauthorized: Missing or invalid signature
- 404 Not Found: Requested data not found (GET only)
- POST requests: Signature is verified on the SAID value (
dfield) from the request body - GET requests: Signature is verified on a Blake3-256 digest of the query parameter string
Self-Addressing Identifiers (SAIDs) are generated using the Saider.saidify() method from keripy, which:
- Serializes the SAD to JSON
- Creates a Blake3-256 hash
- Encodes the hash in CESR format
- Injects the SAID into the
dfield
For testing purposes, data is stored in module-level memory. In production, this would be replaced with persistent storage.
The test suite includes:
- Successful registration and retrieval
- Invalid signature handling
- Missing signature handling
- Malformed request handling
- Response signature verification
Run tests with:
pytest- falcon: Web framework
- keri: KERI library (from GitHub)
- pytest: Testing framework
[Add your license here]