Format Preserving Encryption (FPE) with FF3
Project description
ff3 - Format Preserving Encryption in Python
An implementation of the NIST approved Format Preserving Encryption (FPE) FF3 algorithm in Python.
This package follows the FF3 algorithum for Format Preserving Encryption as described in the March 2016 NIST publication Methods for Format-Preserving Encryption, and revised on Feburary 28th, 2020 with a draft update for FF3-1.
Changes to minimum domain size and revised tweak length have been partially implemented in this package with updates to domain size. It is expected that the final standard will provide new test vectors necessary to change the tweak lengths to 56 bits. Currently, tweaks remain set to 64 bits.
Requires
This project was built and tested with Python 3.6 and later versions. It requires the pycryptodome library:
pip3 install pycryptodome
Installation
Install this project with pip:
pip3 install ff3
Usage
FF3 is a Feistel ciphers, and Feistel ciphers are initialized with a radix representing an alphabet.
Practial radix limits of 36 in python means the following radix values are typical:
- radix 10: digits 0..9
- radix 26: alphabetic a-z
- radix 36: alphanumeric 0..9, a-z
Special characters and international character sets, such as those found in UTF-8, would require a larger radix, and are not supported. Also, all elements in a plaintext string share the same radix. Thus, an identification number that consists of a letter followed by 6 digits (e.g. A123456) cannot be correctly encrypted by FPE while preserving this convention.
Input plaintext has maximum length restrictions based upon the chosen radix (2 * floor(96/log2(radix))):
- radix 10: 56
- radix 26: 40
- radix 36: 36
To work around string length, its possible to encode longer text in chunks.
As with any cryptographic package, managing and protecting the key(s) is crucial. The tweak is generally not kept secret. This package does not protect the key in memory.
Code Example
The example code below can help you get started.
from ff3 import FF3Cipher
key = "EF4359D8D580AA4F7F036D6F04FC6A94"
tweak = "D8E7920AFA330A73"
c = FF3Cipher(key, tweak)
plaintext = "4000001234567899"
ciphertext = c.encrypt(plaintext)
decrypted = c.decrypt(ciphertext)
print("Original: " + plaintext)
print("Ciphertext: " + ciphertext)
print("Decrypted: " + decrypted)
Testing
There are official test vectors for FF3 provided by NIST, which are used for testing in this package.
To run unit tests on this implementation, including all test vectors from the NIST specification, run the command:
python3 ff3_test.py
Implementation Notes
This implementation was originally based upon the Capital One Go implemntation. It follows the algorithm as outlined in the NIST specification as closely as possible, including naming.
FPE can be used for sensitive data tokenization, especially with PCI and cryptographically reversible tokens. This implementation does not provide any guarantees regarding PCI DSS or other validation.
While all test vectors pass, this package has not otherwise been extensively tested.
As of Python 3.7, the standard library's int package supports radices/bases up to 36. Therefore, this release supports a max base of 36, which can contain numeric digits 0-9 and lowercase alphabetic characters a-z.
The django.utils.baseconv module supports base 62 and could be used to increase the radix range.
The cryptographic library used is PyCryptodome for AES encryption. FF3 uses a single-block with an IV of 0, which is effectively ECB mode. AES ECB is the only block cipher function which matches the requirement of the FF3 spec.
The domain size was revised in FF3-1 to radixminLen >= 1,000,000 and is represented by the constant DOMAIN_MIN
in ff3.py
. FF3-1 is in draft status and updated 56-bit test vectors are not yet available.
The tweak is required in the initial FF3Cipher
constructor, but can optionally be overriden in each encrypt
and decrypt
call. This is similar to passing an IV or nonce when creating an encryptor object.
Author
Brad Schoening
License
This project is licensed under the terms of the Apache 2.0 license.
Project details
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
File details
Details for the file ff3-0.9.0.tar.gz
.
File metadata
- Download URL: ff3-0.9.0.tar.gz
- Upload date:
- Size: 11.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/53.0.0 requests-toolbelt/0.9.1 tqdm/4.56.2 CPython/3.9.2
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 4466f22a4a984d400de7a9736cc4af1c12954ddfb28a8dda82ffcce2cbbedad5 |
|
MD5 | 45b8dd3d561de92e9d800336003378e5 |
|
BLAKE2b-256 | fa8ceb73742da48b3df819d056a1092569a0c565d2761faae5904ec1c83c3901 |
File details
Details for the file ff3-0.9.0-py3-none-any.whl
.
File metadata
- Download URL: ff3-0.9.0-py3-none-any.whl
- Upload date:
- Size: 13.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/53.0.0 requests-toolbelt/0.9.1 tqdm/4.56.2 CPython/3.9.2
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 75f1f0ff4fdba5f67a933ef333612e0c3ff88eddb7ce2c04df967c2c3584d6d4 |
|
MD5 | 91aeb6de76747621d63d80c8ea7e15b4 |
|
BLAKE2b-256 | b6f5ae0f36e784f5c67ea9ab4b477e8c60ed51461709dd4b26cf271e458a99ae |