fibcrypt
fibcrypt is an open-source, edge-oriented encryption toolkit that combines a Fibonacci-based key derivation design with AES-256-CBC and HMAC-SHA256 authentication.
It is designed for applications that need many low-latency encryption/decryption operations and want to evaluate an alternative, transparent cryptographic construction. It is not presented as a replacement for Argon2, scrypt, or other independently reviewed password KDFs.
What It Provides
- Fibonacci-based key derivation using modular fast-doubling arithmetic
- A 256-bit default modulus and full SHA-256-derived seed
- AES-256-CBC encryption with PKCS#7 padding
- Encrypt-then-MAC using HMAC-SHA256
- A fresh random salt and IV for every encryption
- A required deployment secret (
pepper) kept outside the ciphertext - Versioned
FC2ciphertext payloads
Security Model
Each encryption requires four inputs:
plaintext: the data to encryptpassword: the user/application passwordsalt: caller-provided context; it may be public, but must be supplied again for decryptionpepper: a secret deployment value that must not be stored in the ciphertext or source code
The ciphertext contains the version marker, random salt, IV, encrypted data, and authentication tag:
FC2 + random_salt + iv + ciphertext + HMAC-SHA256 tag
Decryption authenticates the tag before attempting CBC decryption. Modified or truncated ciphertexts, wrong passwords, wrong salts, and wrong peppers are rejected.
For a ciphertext-only attacker who has no password, caller salt, or pepper, the payload and public source code are not sufficient to derive the keys. This assumes the deployment pepper is a high-entropy secret and is not embedded in application source, test configuration, logs, or the payload.
Important limitations:
- The Fibonacci KDF is custom and has not received an independent cryptographic audit.
iterations=128is selected for latency, not as a claim of equivalence to a memory-hard password KDF.- Weak or reused passwords remain vulnerable to dictionary attacks if the attacker also knows or can guess the salt and obtains the pepper.
- The pepper must be managed as a deployment secret. If an attacker compromises the application host and reads its secrets, this model no longer applies.
- Do not use this package for high-assurance or regulated cryptographic requirements without an independent review.
Installation
pip install fibcrypt
Usage
Set the pepper through a secret manager or environment variable. Do not commit it to source control.
export FIBCRYPT_PEPPER="your-long-random-deployment-secret"
import os
from fibcrypt.crypto_utils import decrypt, encrypt
message = "This is a secret message"
password = "my-strong-password"
salt = "application-context"
pepper = os.environ["FIBCRYPT_PEPPER"]
ciphertext = encrypt(message, password, salt, pepper)
print("Encrypted:", ciphertext.hex())
plaintext = decrypt(ciphertext, password, salt, pepper)
print("Decrypted:", plaintext)
encrypt returns bytes. Store or transmit those bytes directly, or encode them as hexadecimal/base64. Keep the salt and pepper available to the decrypting service; only the pepper must remain secret.
Wrong credentials and tampered ciphertext raise ValueError during authentication.
Parameters
The default public API uses:
iterations=128prime=2**256 - 2**32 - 977
Both can be overridden explicitly for experiments and benchmarks. Changing these values changes the derived keys, so the parameters must remain consistent between encryption and decryption.
Performance
On the development benchmark machine (Python 3.14, Apple Silicon, 7 samples after one warmup), v8 measured approximately:
| Payload | Encrypt | Decrypt |
|---|---|---|
| 16 B | 67.8 ms | 68.4 ms |
| 1 KiB | 68.5 ms | 69.0 ms |
| 1 MiB | 73.4 ms | 72.8 ms |
These are reference measurements, not performance guarantees. Benchmark the target edge hardware before deployment.
PyPI 0.1.5 vs v1.0
The following comparison was run on the same machine against the published PyPI 0.1.5 wheel and the current v1.0 implementation. The legacy release used its original iterations=20 default and unauthenticated AES-CBC format; v1.0 uses iterations=128, full-seed derivation, a secret pepper, random salt, and HMAC authentication. This is therefore a release comparison, not an equal-security-configuration comparison.
| Payload | 0.1.5 Encrypt | v1.0 Encrypt | Speedup | 0.1.5 Decrypt | v1.0 Decrypt | Speedup |
|---|---|---|---|---|---|---|
| 16 B | 3443 ms | 67.8 ms | 50.8x | 3446 ms | 68.4 ms | 50.4x |
| 1 KiB | 3471 ms | 68.5 ms | 50.7x | 3497 ms | 69.0 ms | 50.7x |
| 1 MiB | 3524 ms | 73.4 ms | 48.0x | 3507 ms | 72.8 ms | 48.2x |
The legacy values used three timed samples after one warmup; v1.0 values used seven timed samples after one warmup. Values are rounded and will vary by hardware.
Security Improvements
Compared with the original PyPI fibcrypt 0.1.5 release, fibcrypt 1.0 includes:
- Modular fast-doubling Fibonacci arithmetic instead of unbounded intermediate matrix growth
- A 256-bit default modulus instead of
65537 - The full SHA-256-derived seed instead of a directly enumerable
seed % 10**6space - A required deployment pepper kept outside the ciphertext and source code
- A fresh random salt for every encryption
- Separate encryption and authentication key derivation domains
- HMAC-SHA256 authentication verified before CBC decryption
- Versioned
FC2payloads with explicit format boundaries - Approximately 48-51x lower measured latency than the published
0.1.5artifact on the benchmark machine
Upgrading From 0.1.5
Version 1.0 changes both the API and ciphertext format. Existing systems must not be upgraded blindly:
- Provision one high-entropy pepper through a secret manager or environment variable and make it available to every service that encrypts or decrypts the shared data.
- Update calls from
encrypt(plaintext, password, salt)anddecrypt(ciphertext, password, salt)to include the same pepper value. - Keep the original
0.1.5runtime available while migrating existing data. - Decrypt each
0.1.5ciphertext with the original package and credentials, then re-encrypt it with v1.0 and the managed pepper. - Verify the migrated plaintext or application record before replacing the old ciphertext.
- Test the migration on a backup or staging copy before rolling it out to production.
The v0.1.5 format was iv + ciphertext and used different key derivation defaults. It has no authentication tag and is not readable by the v1.0 FC2 decoder. Conversely, v1.0 ciphertexts require the v1.0 parameters and the correct pepper. Losing the pepper makes v1.0 ciphertexts unrecoverable.
Development
python3 -m pip install -r requirements-dev.txt
python3 -m pytest
ruff check .
mypy
PYTHONPATH=. python3 test/main.py
License
This project is licensed under the MIT License.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fibcrypt-1.0.0.tar.gz.
File metadata
- Download URL: fibcrypt-1.0.0.tar.gz
- Upload date:
- Size: 7.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8bbc44f1e94613fa347787ae7971960a7d2feef2374c549ed860f8b7cef3bd60
|
|
| MD5 |
0383a705d4d12cc1584e1604fb71ad5e
|
|
| BLAKE2b-256 |
3cd838281738328cf1b94bbe334befe2711e7a29248c4e69b370023df55cb8be
|
File details
Details for the file fibcrypt-1.0.0-py3-none-any.whl.
File metadata
- Download URL: fibcrypt-1.0.0-py3-none-any.whl
- Upload date:
- Size: 7.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
249aae17ddea2ba351636e592a8f68232629b3d0777f0de55b498e6d5c7a6951
|
|
| MD5 |
849b0a5a4964b294b13e6ede8c1badb2
|
|
| BLAKE2b-256 |
f19cc0983ad6ec0ae72f712d759cfa02aa888419ec8b4c8e6325d25a3a954d0a
|