The FF3-1 format-preserving encryption mode.
No longer NIST-approved
NIST removed the entire FF3 family (FF3 and FF3-1) in SP 800-38Gr1 2pd (Second Public Draft, February 2025): Beyne's linear cryptanalysis (CRYPTO 2021) found a weakness in the tweak schedule that affects both FF3 and FF3-1 but not FF1. FF1 is now the only approved FPE mode.
FF3-1 is retained here for interoperability with existing data, but new
applications should prefer ExFPE.FF1 (the :ff1 mode, which is the default).
Use it through the ExFPE facade: ExFPE.new(key, :ff3_1, radix_or_alphabet),
then ExFPE.encrypt!/3 / ExFPE.decrypt!/3. See ExFPE for the full how-to-use
guide (contexts, alphabets, tweaks). This module documents what is specific
to FF3-1: its fixed 7-byte tweak and its length constraints.
This implementation conforms, as best as possible, to Draft SP 800-38G Rev. 1 (the first draft, in which FF3-1 was still specified), as published by NIST in their Cryptographic Standards.
No official test vectors for FF3-1 exist as of the time of writing; many of the ones used in this library's test suite were copied almost verbatim from ubiq-fpe-go, an implementation of the FF1 and FF3-1 algorithms in Go.
Length constraints
Numerical strings under FF3-1 are subject to minimum and maximum lengths. These constraints depend on the radix.
iex> key = :crypto.strong_rand_bytes(32)
iex> {:ok, ctx} = ExFPE.new(key, :ff3_1,_radix = 10)
iex> %{min_length: 6, max_length: 56} = ExFPE.FF3_1.constraints(ctx.algorithm)
iex> key = :crypto.strong_rand_bytes(32)
iex> {:ok, ctx} = ExFPE.new(key, :ff3_1,_radix = 16)
iex> %{min_length: 5, max_length: 48} = ExFPE.FF3_1.constraints(ctx.algorithm)
iex> key = :crypto.strong_rand_bytes(32)
iex> {:ok, ctx} = ExFPE.new(key, :ff3_1,_radix = 2)
iex> %{min_length: 20, max_length: 192} = ExFPE.FF3_1.constraints(ctx.algorithm)min_length is required because, for any given radix, short enough numerical
strings encompass too few possible values, rendering encryption ineffective
under adversarial conditions. In other words: their domain is too small.
max_length may be there - pure layman speculation - as an incentive for people
to use regular crypto when working with large enough numbers. I didn't find
the exact reasoning for it.
Tweak
FF3-1 uses a fixed 7-byte (56-bit) tweak. See ExFPE for the general role
of tweaks in FPE, and Appendix C (page 20) of
the reference
document
for the specifics.
iex> byte_size(<<0::56>>)
7