0NG / Format-Preserving-Encryption

FPE Implementation in C [Preparing for improvement]
MIT License
45 stars 30 forks source link
format-preserving-encryption fpe

FPE - Format Preserving Encryption Implementation in C

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.

Example Usage

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.

  1. 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
  1. 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
  1. 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
  1. 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.

Existing Implementations

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.

TODO

  1. Make the API simpler
  2. More effective implementation