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.7.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.7.0
File Size Uploaded
fiki-0.7.0.tar.gz 85.8 kB Details

Built distribution (wheel)

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

Total release size: 113.3 kB

Release files / fiki-0.7.0.tar.gz

Download URL fiki-0.7.0.tar.gz
Size 85.8 kB
Tags Source
SHA-256 checksum
How to use checksums
347af1504e159a487fcf9e23aec274fcbb220f5d3b85dd46f5d8b36c7b5fa09b
BLAKE2b-256 checksum
How to use checksums
5e04d8172ac8dd8de5555099ad584e65b575f849dba991d27f3dbd6d8a8313d3
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.7.0-py3-none-any.whl

Download URL fiki-0.7.0-py3-none-any.whl
Size 27.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
94af4fddabb34988d35fc99a875fabd2d3f7517a7340fe0bbef6dd8abf353d3f
BLAKE2b-256 checksum
How to use checksums
95686782c9a3571eee2185a9bc76fe18e8be5e3f0a09bfe64ab2553a43a58609
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

0.8.0

2 release files

This release

0.7.0 This release

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