capitalone / fpe Goto Github PK
View Code? Open in Web Editor NEWA format-preserving encryption implementation in Go
License: Apache License 2.0
A format-preserving encryption implementation in Go
License: Apache License 2.0
Right now, the tweak
parameter to NewCipher
prevents re-use of the same cipher for different data inputs.
So, would it be better to instead pass in tweak
to Encrypt
and Decrypt
?
This would likely cause a breaking change to the current API.
If applicable, mention which version(s) of Go you are able to reproduce this on, along with go env
output.
I want to use the FPE for one-way format preserving tokens only. How do I use the FF3 to achieve that. Any help appreciated.
If applicable, mention which version(s) of Go you are able to reproduce this on, along with go env
output.
maxLen is incorrectly being calculated by moving the multiplication by 2 into the floor, whereas the spec calls for the multiplication to happen outside (after) the flooring.
This causes the bug referenced later in Encrypt, where the length of the input, n, is not allowed to be equal to maxLen, whereas it is allowed in the spec.
Line 87 in e6bfa0d
While FF2 was not approved by NIST and is currently under re-review as DFF, it may not hurt to add another package ff2
that implements the algorithm, and keep it up to date as the recommendations change.
I dug deeper and apparently there is no way to get the IV back unless it is stored since the order is reversed.
Hi Anit,
I have a variable with 16 to 19 Byte length (PAN) within a message with maximum 37 Byte length (Track2). I want to know if it is possible to use FPE to encrypt this variable (PAN) without any change in message (Track2) format. From the contents of "NIST SP 800-38g" document, it appears that FPE uses AES 128-bit block ciphers. As a result, for encrypting a 19 Byte variable, it will change the message format and will use 32 Byte instead of 19 Byte in Track2 message. (Each 128bit is equal to 16 Byte and for encrypting 19 Byte, we need two 128-bit blocks).
I want to make sure if my explanation is correct. With this assumption, the format of the message will not be preserved.
I am looking forward to hearing from you.
Best Regards.
If applicable, mention which version(s) of Go you are able to reproduce this on, along with go env
output.
In the FF3 constructor. The 3rd check in the ‘if’ statement looks redundant. It seems to test if maxLen > maxLen, which must always be false?
maxLen := uint32(math.Floor((192 / math.Log2(float64(radix)))))
// Make sure 2 <= minLength <= maxLength < 2*floor(log base radix of 2^96) is satisfied
if (minLen < 2) || (maxLen < minLen) || (float64(maxLen) > (192 / math.Log2(float64(radix)))) {
return newCipher, errors.New("minLen or maxLen invalid, adjust your radix”)
}
Based on the recent cryptanalysis of FF3, the FF3 algorithm is no longer considered a suitable algorithm for FPE by NIST. However, a simple fix was given:
The researchers proposed a straightforward modification to FF3: require two particular bytes of the tweak to be set to zero, which in effect would reduce the size of the tweak from eight bytes to six bytes. Implementations that properly enforce this requirement should not be vulnerable to the attack. Alternative structures/conditions on the tweak might also preclude the attack.
Based on the above, the ff3
sub-package can be modified to enforce this extra requirement on the tweak.
This is a tracking bug based on #9
package main
import (
"fmt"
"github.com/capitalone/fpe/ff1"
)
// Note: panic(err) is just used for example purposes.
func main() {
key := []byte{0x4, 0x8, 0x15, 0x16, 0x23, 0x42, 0x4, 0x8, 0x15, 0x16, 0x23, 0x42, 0x4, 0x8, 0x15, 0x16, 0x23, 0x42, 0x4, 0x8, 0x15, 0x16, 0x23, 0x42}
tweak := []byte{0x42}
// Create a new FF1 cipher "object"
// 10 is the radix/base, and 8 is the tweak length.
ciph, err := ff1.NewCipher(10, 8, key, tweak)
if err != nil {
panic(err)
}
original := "750000000"
// Call the encryption function on an example test vector
ciphertext, err := ciph.Encrypt(original)
if err != nil {
fmt.Println(err)
}
fmt.Println(ciphertext)
}
Not a panic
Expanding on #1 , in theory, this package should support arbitrary alphabets as well. It will require either major changes to math/big
or a new sub-package.
This may or may not have to include non-ASCII characters.
Further, there is a chance it will require a breaking change in the interface, if this alphabet input is added to NewCipher
. Alternatively, a new function on Cipher
called SetAlphabet
could be added.
func NewCipher(radix int, maxTLen int, key []byte, tweak []byte) (Cipher, error) {
...
// defaults
f.alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
f.radix = 62
}
func (f Cipher) SetAlphabet(alphabet string, radix int) {
// error checking on alphabet and radix
// ex: alphabet can't be "12345" and radix be 9
...
f.alphabet = alphabet
f.radix = radix
}
Currently, this package only has support for inputs of base/radix 36, due to math/big
MaxBase
const being 36, as of June 29, 2017.
So, this package should have base62 support. This may involve the math/big
package itself being updated, or a modified version of it must be used. See below.
In fact, because the math/big
actually treats upper case and lower case alpha characters as the same, this actually causes a bug in this package. For example:
Encrypt Input: abc123def
Encrypt Output: flknlk32n
Encrypt Input: ABC123DEF
Encrypt Output: flknlk32n
(same as before)
Decrypt input: flknlk32n
Decrypt output: abc123def
This is a collision of sorts.
Supporting base 62 properly in math/big
directly is very easy. Here's a diff on math/big/natconv.go
that shows it. Ideally, this change will be accepted by Golang maintainers.
< // This file was has minor configurations compared to
< // the standard library's math/big package in order
< // to support base 62 conversions rather than base 36
<
21c17
< const digits = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
---
> const digits = "0123456789abcdefghijklmnopqrstuvwxyz"
27c23
< const MaxBase = len(digits)
---
> const MaxBase = 'z' - 'a' + 10 + 1
179c175
< d1 = Word(ch - 'A' + 10 + 26)
---
> d1 = Word(ch - 'A' + 10)
181c177
< d1 = Word(MaxBase + 1)
---
> d1 = MaxBase + 1
While maintaining a customized version of math/big
as a subpackage of fpe
is not difficult, it's arguably not the best path forward.
Please add trusted reviewers to your code owners file and write team if necessary. Thanks!
The root repo directory is not a valid Go package because it does not contain any Go files. This means that the link to godoc.org in the Readme (the badge) is broken and go get
cannot be used to fetch it directly (which may or may not be a problem). Maybe the badge should point to the ff1
or ff3
packages instead, or a doc.go
should be added to the root repo directory purely to give some context and link to the subdirectories?
Lines 374 to 377 in e6bfa0d
Is there a plan to update the FF3 code to FF3-1? Thanks!
Looking here:
Line 484 in e6bfa0d
The comment suggests R
should be used but it is entirely unused. (As reported by staticcheck here). Is this dead/delete-able or does it indicate a decryption error?
Plaintext is not equal to Original
Follow Example Usage in main.go. Just replace original := "11111010", radix = 2, maxTlen=128
###Output
Original: 11111010
Ciphertext: 1110011
Plaintext: 1011011
If applicable, mention which version(s) of Go you are able to reproduce this on, along with go env
output.
go version go1.9.2 windows/amd64
Expect:
Plaintext=Original=11111010
The documentations states there is a patent on the algorithm by Voltage. Hence am curious to know how is this open source project available? Can an organization (not profit making) make use of this? are there any restrictions?
thanks
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.