Skip to main content

fiki (Python)

Python

The Python implementation of fiki. Requires Python 3.11 or newer, and depends on cryptography and http-sfv and on nothing else.

From a fresh clone to passing tests

cd py
uv sync
uv run pytest

The suite enforces 100% branch coverage; a gap needs an approved deviation: node in the repo's this.i.

Signing a request

from fiki import Key, sign_request

key = Key.generate()
print(key.aid)            # register this once with whoever you call
print(key.seed.hex())     # 32 bytes; persist them somewhere the cron job can read

url = "https://api.example.com/things?limit=1"
body = b'{"hello": "world"}'
headers = sign_request(key=key, method="POST", url=url, body=body)

By default the signature binds the method, the host, the path, the query string, and a digest of the body. Pass the body wherever you pass the URL: fiki covers a body it is given, or refuses to sign — but it cannot cover one it never sees.

Verifying a request

from fiki import verify_request

verdict = verify_request(
    method=request.method,
    url=request.url,      # a full URL, or a path plus a Host header
    headers=request.headers,
    body=request.body,
    max_age=300,          # seconds, or None to decline the check
)
verdict.aid               # who signed it

max_age has no default and must be given. Both defaults would be wrong: a number guesses at somebody else's clock skew and replay window, and skipping the check silently is the thing the argument exists to prevent. An expires the signer declared is enforced either way.

Responses, resolved keyids, and a minimum covered set

These exist for the KERI profile of RFC 9421 (this.i @7f28p7xk, @6g9zjsv9) and are, for now, in this port only.

from fiki import (REQUEST_MINIMUM, RESPONSE_MINIMUM, Request, sign_request, sign_response,
                  verify_request, verify_response)

# A keyid that is not the key itself, such as a KERI AID, needs a resolver on the verify side.
# The resolver returns the 32 raw bytes of the key, or None; fiki never decodes the keyid itself.
headers = sign_request(key=key, method="POST", url=url, body=body, keyid=aid)
verdict = verify_request(method="POST", url=url, headers=headers, body=body, max_age=300,
                         resolve=current_key_for, minimum=REQUEST_MINIMUM)

# A response binds the request it answers with RFC 9421's req parameter.
asked = Request(method="POST", url=url, headers=request_headers, body=body)
signed = sign_response(key=key, status=200, request=asked, body=reply)
verify_response(status=200, headers=signed, body=reply, request=asked, max_age=300,
                minimum=RESPONSE_MINIMUM)

minimum refuses a signature that covers less than the named components even when it is valid, and refuses a body — Content-Length above zero, any Transfer-Encoding, or one that simply arrived — whose content-digest is not covered. The method is signed exactly as given, with no case change, so pass it as it will go on the wire.

minimum=None, the default, enforces nothing: a body handed to verify_request with no covered content-digest is then accepted, and only the verdict's covered shows it. Pass a minimum whenever you hand over a body. Signers take the same minimum and refuse to cover less. A client checking a response should pass expected_keyid, the AID it is talking to; a server should pass authorities, the set it serves, which also makes @authority required: a signature that does not cover it is InsufficientCoverage. An unsigned 401 is Unauthenticated, and a resolver raises UnsupportedSigner for a key state with no single effective signer.

Conformance

tests/test_rfc9421_conformance.py signs RFC 9421's own Appendix B.2.6 request with the RFC's own published Ed25519 key and asserts the RFC's own signature, byte for byte. tests/test_vectors.py runs the shared vectors/ at the repository root, which every port runs. tests/test_keri_vectors.py runs vectors/keri/, the KERI profile's set, which only this port runs so far.

Metadata

Release files for fiki 0.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fiki 0.8.0
File Size Uploaded
fiki-0.8.0.tar.gz 96.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fiki 0.8.0
File Interpreter ABI Platform
fiki-0.8.0-py3-none-any.whl Python 3 none any Details

Total release size: 128.2 kB

Release files / fiki-0.8.0.tar.gz

Download URL fiki-0.8.0.tar.gz
Size 96.5 kB
Tags Source
SHA-256 checksum
How to use checksums
177246bb8dcc584ddbf5390f77b4c38a0d982b39371eebeee67cba2c4c91ecc3
BLAKE2b-256 checksum
How to use checksums
7cdbe09f39648248c0289a780e96d8e2bc06e4f07f11d4783e72c93d17123c92
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release files / fiki-0.8.0-py3-none-any.whl

Download URL fiki-0.8.0-py3-none-any.whl
Size 31.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c8596e6f8f8775c8c5cfea9979aa92134dff2780eaf373e1f35139fda3251c94
BLAKE2b-256 checksum
How to use checksums
5820efa9cba2d3d6f29c6387bbc7e5d0bdfb620bd2c8487b12f575d868f84949
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.8.0 This release

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page