Skip to content
This repository has been archived by the owner on Feb 2, 2022. It is now read-only.

Commit

Permalink
Merge pull request #15 from capitalone/issue-14
Browse files Browse the repository at this point in the history
Padding fix for issue 14
  • Loading branch information
anitgandhi authored Jan 22, 2018
2 parents b430d2b + 420eba6 commit 80b2f95
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 16 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ language: go
go:
- 1.7.x
- 1.8.x
- 1.9.x
- tip
23 changes: 7 additions & 16 deletions ff1/ff1.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"errors"
"math"
"math/big"
"strings"
)

// Note that this is strictly following the official NIST spec guidelines. In the linked PDF Appendix A (README.md), NIST recommends that radix^minLength >= 1,000,000. If you would like to follow that, change this parameter.
Expand Down Expand Up @@ -167,7 +168,6 @@ func (c Cipher) EncryptWithTweak(X string, tweak []byte) (string, error) {
B := X[u:]

// Byte lengths
// TODO: can these calculations be done more efficiently?
b := int(math.Ceil(math.Ceil(float64(v)*math.Log2(float64(radix))) / 8))
d := int(4*math.Ceil(float64(b)/4) + 4)

Expand Down Expand Up @@ -217,8 +217,6 @@ func (c Cipher) EncryptWithTweak(X string, tweak []byte) (string, error) {
totalBufLen := lenQ + lenPQ + (maxJ-1)*blockSize
buf := make([]byte, totalBufLen)

// TODO: small inputs will likely cause Q length to be 16,
// could start with that with larger cap and expand as necessary?
// Q will use the first lenQ bytes of buf
// Only the last b+1 bytes of Q change for each loop iteration
Q := buf[:lenQ]
Expand Down Expand Up @@ -348,11 +346,9 @@ func (c Cipher) EncryptWithTweak(X string, tweak []byte) (string, error) {
A = numA.Text(radix)
B = numB.Text(radix)

// Pad B properly
// TODO: improve this, but don't import "strings" just for it
for len(B) < int(v) {
B = "0" + B
}
// Pad both A and B properly
A = strings.Repeat("0", int(u)-len(A)) + A
B = strings.Repeat("0", int(v)-len(B)) + B

ret = A + B

Expand Down Expand Up @@ -406,7 +402,6 @@ func (c Cipher) DecryptWithTweak(X string, tweak []byte) (string, error) {
B := X[u:]

// Byte lengths
// TODO: can these calculations be done more efficiently?
b := int(math.Ceil(math.Ceil(float64(v)*math.Log2(float64(radix))) / 8))
d := int(4*math.Ceil(float64(b)/4) + 4)

Expand Down Expand Up @@ -456,8 +451,6 @@ func (c Cipher) DecryptWithTweak(X string, tweak []byte) (string, error) {
totalBufLen := lenQ + lenPQ + (maxJ-1)*blockSize
buf := make([]byte, totalBufLen)

// TODO: small inputs will likely cause Q length to be 16,
// could start with that with larger cap and expand as necessary?
// Q will use the first lenQ bytes of buf
// Only the last b+1 bytes of Q change for each loop iteration
Q := buf[:lenQ]
Expand Down Expand Up @@ -587,11 +580,9 @@ func (c Cipher) DecryptWithTweak(X string, tweak []byte) (string, error) {
A = numA.Text(radix)
B = numB.Text(radix)

// Pad A properly
// TODO: improve this, but don't import "strings" just for it
for len(A) < int(u) {
A = "0" + A
}
// Pad both A and B properly
A = strings.Repeat("0", int(u)-len(A)) + A
B = strings.Repeat("0", int(v)-len(B)) + B

ret = A + B

Expand Down
28 changes: 28 additions & 0 deletions ff1/ff1_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,34 @@ func TestLong(t *testing.T) {
}
}

// Regression test for issue 14: https://github.com/capitalone/fpe/issues/14
func TestIssue14(t *testing.T) {
key, err := hex.DecodeString("EF4359D8D580AA4F7F036D6F04FC6A94")

tweak, err := hex.DecodeString("D8E7920AFA330A73")

ff1, err := NewCipher(2, 8, key, tweak)
if err != nil {
t.Fatalf("Unable to create cipher: %v", err)
}

plaintext := "11111010"

ciphertext, err := ff1.Encrypt(plaintext)
if err != nil {
t.Fatalf("%v", err)
}

decrypted, err := ff1.Decrypt(ciphertext)
if err != nil {
t.Fatalf("%v", err)
}

if plaintext != decrypted {
t.Fatalf("Issue 14 Decrypt Failed. \n Expected: %v \n Got: %v \n", plaintext, decrypted)
}
}

// Note: panic(err) is just used for example purposes.
func ExampleCipher_Encrypt() {
// Key and tweak should be byte arrays. Put your key and tweak here.
Expand Down

0 comments on commit 80b2f95

Please sign in to comment.