GithubHelp home page GithubHelp logo

capitalone / fpe Goto Github PK

View Code? Open in Web Editor NEW
198.0 17.0 40.0 81 KB

A format-preserving encryption implementation in Go

License: Apache License 2.0

Go 100.00%
encryption golang fpe ff1 ff3 format-preserving-encryption

fpe's People

Contributors

anitgandhi avatar cstockton avatar ospo-capitalone avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fpe's Issues

One non-reversible FPE

Description of Issue

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.

Steps to Reproduce

If applicable, mention which version(s) of Go you are able to reproduce this on, along with go env output.

What did you expect to see?

ff3: fix maxLen calculation

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.

fpe/ff3/ff3.go

Line 87 in e6bfa0d

maxLen := uint32(math.Floor((192 / math.Log2(float64(radix)))))

Addition of FF2 algorithm

Description of Issue

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.

IV was not an issue

I dug deeper and apparently there is no way to get the IV back unless it is stored since the order is reversed.

The difference between output and input length of FPE

Description of Issue

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.

Steps to Reproduce

If applicable, mention which version(s) of Go you are able to reproduce this on, along with go env output.

What did you expect to see?

FF3: redundant maxLen check

Description of Issue

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”)
}

FF3 - Tweak Fix

Description of Issue

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.

Enhancement

Based on the above, the ff3 sub-package can be modified to enforce this extra requirement on the tweak.

Panic on strings with trailing zeros

Description of Issue

This is a tracking bug based on #9

Steps to Reproduce

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)
}

What did you expect to see?

Not a panic

Arbitrary alphabet and radix support

Description of Enhancement

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
}

Base62 support

Description of Enhancement

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.

Notes

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.

Codeowners file

Please add trusted reviewers to your code owners file and write team if necessary. Thanks!

Root repo directory is not a valid Go package

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?

Performance Tweaks

Description of Enhancement

  1. Use byte slices and utf8 instead of strings
  2. Reduce extraneous allocations, a la #3

FF3-1

Is there a plan to update the FF3 code to FF3-1? Thanks!

Plaintext is not equal to Original

Description of Issue:

Plaintext is not equal to Original

Steps to Reproduce:

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

What did you expect to see?

Expect:
Plaintext=Original=11111010

are there any restrictions on using this project

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.