An implementation of the NIST approved Format Preserving Encryption (FPE) FF1 and FF3 algorithms in C.
NIST Recommendation SP 800-38G
This follows the FF1 and FF3 schemes for Format Preserving Encryption outlined in the NIST Recommendation, released in March 2016. For FF1, it builds on and formalizes (differing from but remaining mathematically equivalent to) the FFX-A10 scheme by Bellare, Rogaway and Spies as defined here and here. For FF3, it formalizes the BPS scheme.
A note about FF3: There was some recent cryptanalysis about the FF3 algorithm that is important to review. NIST has concluded that FF3 is no longer suitable as a general-purpose FPE method.
A note about FF2: FF2 was originally NOT recommended by NIST, but it is under review again as DFF. You can read about it here.
This implementation is based on openssl's BIGNUM and AES, so you need to install openssl first.
There are several functions for FF1 and FF3 algorithm, respectively.
- Set and unset ff1 key and tweak
int FPE_set_ff1_key(const unsigned char *userKey, const int bits, const unsigned char *tweak, const unsigned int tweaklen, const int radix, FPE_KEY *key);
void FPE_unset_ff1_key(FPE_KEY *key);
name | description |
---|---|
userKey | encryption key (128 bit, 192 bits or 256 bits), represented as a c string |
bits | length of userKey (128, 192 or 256) |
tweak | tweak, represented as a c string |
tweaklen | the byte length of the tweak |
radix | number of characters in the given alphabet, it must be in [2, 2^16] |
key | FPE_KEY structure |
- encrypt or decrypt text using ff1 algorithm
void FPE_ff1_encrypt(unsigned int *in, unsigned int *out, unsigned int inlen, FPE_KEY *key, const int enc)
name | description |
---|---|
in | numeral string to be encrypted, represented as an array of integers |
out | encrypted numeral string, represented as an array of integers |
inlen | the length of input numeral string (in) |
key | FPE_KEY structure that have been set with key and tweak |
enc | can be two value: FPE_ENCRYPT for encrypt and FPE_DECRYPT for decrypt |
- Set and unset ff3 key and tweak
int FPE_set_ff3_key(const unsigned char *userKey, const int bits, const unsigned char *tweak, const unsigned int radix, FPE_KEY *key);
void FPE_unset_ff3_key(FPE_KEY *key);
name | description |
---|---|
userKey | encryption key (128 bit, 192 bits or 256 bits), represented as a c string |
bits | length of userKey (128, 192 or 256) |
tweak | tweak, represented as a c string (it must be 64 bytes) |
radix | number of characters in the given alphabet, it must be in [2, 2^16] |
key | FPE_KEY structure |
- encrypt or decrypt text using ff3 algorithm
void FPE_ff3_encrypt(unsigned int *in, unsigned int *out, unsigned int inlen, FPE_KEY *key, const int enc);
name | description |
---|---|
in | numeral string to be encrypted, represented as an array of integers |
out | encrypted numeral string, represented as an array of integers |
inlen | the length of input numeral string (in) |
key | FPE_KEY structure that have been set with key and tweak |
enc | can be two value: FPE_ENCRYPT for encrypt and FPE_DECRYPT for decrypt |
The example code is example.c. Also, there are some official test vectors for both FF1 and FF3 provided by NIST. You can run test.py with python 3.x.
To compile the example.c with the fpe library, just run make example or make.
Run test.py for testing with official test vectors.
Based on searching GitHub and the Internet, there are no known reference implementations for either algorithm.
An existing C++ implementation based on the FFX mode, but the implementation differs from the NIST recommendation.
Also, another implementation in Go is great. I have learned a lot from it.
- Make the API simpler
- More effective implementation