Skip to content

Format Preserving Encryption (FPE) NIST FF3-1 Implementation in C

License

Notifications You must be signed in to change notification settings

SINHASantos/Format-Preserving-Encryption-via-FF3-1

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

39 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FPE - Format Preserving Encryption Implementation in C via FF3-1

An implementation of the NIST approved Format Preserving Encryption (FPE) FF1, FF3 and FF3-1 algorithms in C.

NIST decided to update FF3 (called FF3-1) to address the vulnerability in a new version of SP 800-38Grev1. This announcement also noted that FF3 is no longer suitable as a general-purpose FPE method.

Vendors shall not claim any compliance to FF3 in an approved mode of operation.

SP 800-38G requires that the underlying encryption function used in the format-preserving algorithms is an approved block cipher operating on the 128-bit blocks of data. As of August 2020, and for the foreseeable future, the only such function is the AES algorithm. The length of an AES key may be 128, 192, or 256 bits.

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 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
  1. Set and unset ff31 key and tweak
int FPE_set_ff31_key(const unsigned char *userKey, const int bits, const unsigned char *tweak, const unsigned int radix, FPE_KEY *key);

void FPE_unset_ff31_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 56 bytes)
radix number of characters in the given alphabet, if the key is used within an IETF protocol; it must be in [2, 2^16] // maxRadix = 65536 // 2^16
key FPE_KEY structure
  1. encrypt or decrypt text using ff31 algorithm
void FPE_ff31_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.

Rust FPE Implementation https://github.com/str4d/fpe

TODO

  1. Create RUST Wrapper

About

Format Preserving Encryption (FPE) NIST FF3-1 Implementation in C

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C 75.4%
  • Python 21.9%
  • Makefile 1.8%
  • C++ 0.9%