-
Notifications
You must be signed in to change notification settings - Fork 0
/
ff1.go
145 lines (122 loc) · 3.33 KB
/
ff1.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package main
import (
"bufio"
"encoding/hex"
"flag"
"fmt"
"os"
"strings"
"github.com/capitalone/fpe/ff1"
)
func main() {
keyfile := flag.String("k", "", "Path to the key file (128, 192 or 256 bit, hex encoded)")
tweakfile := flag.String("t", "", "Path to the tweak file (64 bit, hex encoded)")
decryptFlag := flag.Bool("d", false, "Specify whether to decrypt the data")
padding := flag.Int("p", 0, "Specify the padding size in bytes")
width := flag.Int("w", 0, "Specify the line width")
flag.Parse()
if *keyfile == "" || *tweakfile == "" {
fmt.Println("Usage: ff1 -k <keyfile> -t <tweakfile> [-d] [-p <padding>] [-w <width>] < infile > outfile\n Infile = one long hex line, created with my base16 encoder or xxd.")
os.Exit(1)
}
keyHex, err := readLines(*keyfile)
if err != nil {
fmt.Printf("Error reading key file: %v\n", err)
os.Exit(1)
}
tweakHex, err := readLines(*tweakfile)
if err != nil {
fmt.Printf("Error reading tweak file: %v\n", err)
os.Exit(1)
}
key, err := hex.DecodeString(string(keyHex))
if err != nil {
fmt.Printf("Error decoding key hex: %v\n", err)
os.Exit(1)
}
tweak, err := hex.DecodeString(string(tweakHex))
if err != nil {
fmt.Printf("Error decoding tweak hex: %v\n", err)
os.Exit(1)
}
FF1, err := ff1.NewCipher(16, 8, key, tweak) // Changed radix to 16
if err != nil {
fmt.Printf("Error creating FF1 cipher: %v\n", err)
os.Exit(1)
}
inputData, err := readStdin()
if err != nil {
fmt.Printf("Error reading input data: %v\n", err)
os.Exit(1)
}
// Remove line breaks if decrypting
if *decryptFlag {
inputData = strings.ReplaceAll(inputData, "\n", "")
}
// Apply padding if necessary
if *padding > 0 && len(inputData) < *padding {
paddingSize := *padding - len(inputData)
paddingBytes := make([]byte, paddingSize)
for i := range paddingBytes {
paddingBytes[i] = '0'
}
inputData = inputData + string(paddingBytes)
}
var outputData string
if *decryptFlag {
// Decrypt if -decrypt flag is specified
plaintext, err := FF1.Decrypt(inputData)
if err != nil {
fmt.Printf("Error decrypting data: %v\n", err)
os.Exit(1)
}
outputData = plaintext
} else {
// Encrypt by default
ciphertext, err := FF1.Encrypt(inputData)
if err != nil {
fmt.Printf("Error encrypting data: %v\n", err)
os.Exit(1)
}
outputData = ciphertext
}
// Apply line width if necessary
if *width > 0 {
formattedOutputData := ""
for i := 0; i < len(outputData); i += *width {
end := i + *width
if end > len(outputData) {
end = len(outputData)
}
formattedOutputData += outputData[i:end] + "\n"
}
outputData = formattedOutputData
}
// Write the output data to the output file
_, err = os.Stdout.WriteString(outputData)
if err != nil {
fmt.Printf("Error writing output data: %v\n", err)
os.Exit(1)
}
}
func readLines(path string) (string, error) {
file, err := os.Open(path)
if err != nil {
return "", fmt.Errorf("failed to open file: %s", path)
}
defer file.Close()
scanner := bufio.NewScanner(file)
var lines []string
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return strings.Join(lines, "\n"), scanner.Err()
}
func readStdin() (string, error) {
scanner := bufio.NewScanner(os.Stdin)
var lines []string
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return strings.Join(lines, "\n"), scanner.Err()
}