ruby_clang_fpe 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,124 @@
1
+ [![Build Status](https://github.com/mysto/clang-fpe/actions/workflows/c-cpp.yml/badge.svg)](https://github.com/mysto/clang-fpe/actions)
2
+ [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
3
+
4
+ <p align="center">
5
+ <a href="https://privacylogistics.com/">
6
+ <img
7
+ alt="Mysto"
8
+ src="https://privacylogistics.com/Mysto-logo.jpg"
9
+ />
10
+ </a>
11
+ </p>
12
+
13
+ # FPE - Format Preserving Encryption Implementation in C
14
+
15
+ An implementation of the NIST approved FF1, FF3 and FF3-1 Format Preserving Encryption (FPE) algorithms in Python.
16
+
17
+ This package implements the FPE algorithm for Format Preserving Encryption as described in the March 2016 NIST publication 800-38G _Methods for Format-Preserving Encryption_,
18
+ and revised on February 28th, 2019 with a draft update for FF3-1.
19
+
20
+ * [NIST Recommendation SP 800-38G (FF3)](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38G.pdf)
21
+ * [NIST Recommendation SP 800-38G Revision 1 (FF3-1)](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38Gr1-draft.pdf)
22
+
23
+ ## Build and Run
24
+
25
+ To compile the example.c with the fpe library, just run
26
+
27
+ `make`
28
+
29
+ To build on macOS:
30
+ ```shell
31
+ brew install openssl
32
+ export CFLAGS="-I$(brew --prefix openssl)/include"
33
+ export LDFLAGS="-L$(brew --prefix openssl)/lib"
34
+ ```
35
+ Run the example in
36
+ [example.c](https://github.com/0NG/Format-Preserving-Encryption/blob/master/example.c).
37
+
38
+ ```shell
39
+ ./example EF4359D8D580AA4F7F036D6F04FC6A94 D8E7920AFA330A73 10 890121234567890000
40
+
41
+ plaintext: 890121234567890000
42
+
43
+ FF1 ciphertext: 318181603547192051
44
+ FF1 decrypted: 890121234567890000
45
+
46
+ FF3 ciphertext: 750918814058654607
47
+ FF3 decrypted: 890121234567890000
48
+ ```
49
+ Run the tests
50
+
51
+ There are official [test vectors](http://csrc.nist.gov/groups/ST/toolkit/examples.html) for both FF1 and FF3 provided by NIST. You can run [test.py](https://github.com/0NG/Format-Preserving-Encryption/blob/master/test.py) with python 3.x.
52
+ with a known test vector:
53
+
54
+ ```shell
55
+ make test
56
+ ```
57
+ ## Example Usage
58
+
59
+ This implementation is based on OpenSSL's BIGNUM and AES, so you need to install OpenSSL first.
60
+
61
+ There are several functions for FF1 and FF3 algorithm, respectively.
62
+
63
+ 1. Create and delete FF1 key and tweak
64
+
65
+ ```c
66
+ FPE_KEY* FPE_ff1_create_key(const char *key, const char *tweak, const unsigned int radix);
67
+
68
+ void FPE_ff1_delete_key(FPE_KEY *keystruct);
69
+ ```
70
+
71
+ | name | description |
72
+ | -------- | ---------------------------------------- |
73
+ | key | encryption key (128 bit, 192 bits or 256 bits), represented as a c string |
74
+ | tweak | tweak, represented as a c string |
75
+ | radix | number of characters in the given alphabet, it must be in [2, 2^16] |
76
+ | returns | FPE_KEY structure |
77
+
78
+ 2. encrypt or decrypt text using FF1 algorithm
79
+
80
+ ```c
81
+ void FPE_ff1_encrypt(char *plaintext, char *ciphertext, FPE_KEY *keystruct)
82
+ void FPE_ff1_decrypt(char *ciphertext, char *plaintext, FPE_KEY *keystruct)
83
+ ```
84
+
85
+ | name | description |
86
+ | ----- | ---------------------------------------- |
87
+ | plaintext | numeral string to be encrypted, represented as an array of integers |
88
+ | ciphertext | encrypted numeral string, represented as an array of integers |
89
+ | keystruct | FPE_KEY structure that has been set with key and tweak |
90
+
91
+ 3. Create and delete FF3 key and tweak
92
+
93
+ ```c
94
+ FPE_KEY* FPE_ff3_create_key(const char *key, const char *tweak, const unsigned char radix);
95
+ FPE_KEY* FPE_ff3_1_create_key(const char *key, const char *tweak, const unsigned char radix);
96
+
97
+ void FPE_ff3_delete_key(FPE_KEY *keystruct);
98
+ ```
99
+
100
+ | name | description |
101
+ | ------- | ---------------------------------------- |
102
+ | key | encryption key (128 bit, 192 bits or 256 bits), represented as a c string |
103
+ | tweak | tweak, represented as a c string (it must be 64 bytes) |
104
+ | radix | number of characters in the given alphabet, it must be in [2, 2^16] |
105
+ | returns | FPE_KEY structure |
106
+
107
+ 4. encrypt or decrypt text using FF3 algorithm
108
+
109
+ ```c
110
+ void FPE_ff3_encrypt(char *plaintext, char *ciphertext, FPE_KEY *keystruct);
111
+ void FPE_ff3_decrypt(char *ciphertext, char *plaintext, FPE_KEY *keystruct);
112
+ ```
113
+
114
+ | name | description |
115
+ | ----- | ---------------------------------------- |
116
+ | plaintext | numeral string to be encrypted, represented as an array of integers |
117
+ | ciphertext | encrypted numeral string, represented as an array of integers |
118
+ | radix | number of characters in the given alphabet, it must be in [2, 2^16] |
119
+ | keystruct | FPE_KEY structure that has been set with key and tweak |
120
+
121
+ ## TODO
122
+
123
+ 1. Performance testing
124
+ 3. Custom alphabet support
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+ #
3
+ # empty configue script
4
+ #
@@ -0,0 +1,59 @@
1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include <assert.h>
4
+ #include <string.h>
5
+ #include <fpe.h>
6
+ #include <fpe_locl.h>
7
+
8
+ /*
9
+ usage:
10
+
11
+ ./example 2DE79D232DF5585D68CE47882AE256D6 CBD09280979564 10 3992520240
12
+
13
+ */
14
+
15
+ int main(int argc, char *argv[])
16
+ {
17
+ if (argc != 5) {
18
+ printf("Usage: %s <key> <tweak> <radix> <plaintext>\n", argv[0]);
19
+ return 0;
20
+ }
21
+
22
+ char ciphertext[100];
23
+ char resulttext[100];
24
+
25
+ char* key = argv[1];
26
+ char* tweak = argv[2];
27
+ char* plaintext = argv[4];
28
+ int radix = atoi(argv[3]);
29
+
30
+ int txtlen = strlen(plaintext),
31
+ tlen = strlen(tweak) / 2;
32
+
33
+ FPE_KEY *ff1 = FPE_ff1_create_key(key, tweak, radix);
34
+ FPE_KEY *ff3 = (tlen == 7) ?
35
+ FPE_ff3_1_create_key(key, tweak, radix) :
36
+ FPE_ff3_create_key(key, tweak, radix);
37
+
38
+ //for (int i = 0; i < xlen; ++i)
39
+ // assert(x[i] < radix);
40
+
41
+ FPE_ff1_encrypt(plaintext, ciphertext, ff1);
42
+ printf("FF1 ciphertext: %s\n", ciphertext);
43
+
44
+ memset(resulttext, 0, txtlen);
45
+ FPE_ff1_decrypt(ciphertext, resulttext, ff1);
46
+ printf("FF1 decrypted: %s\n\n", resulttext);
47
+
48
+ FPE_ff3_encrypt(plaintext, ciphertext, ff3);
49
+ printf("FF3 ciphertext: %s\n", ciphertext);
50
+
51
+ memset(resulttext, 0, txtlen);
52
+ FPE_ff3_decrypt(ciphertext, resulttext, ff3);
53
+ printf("FF3 decrypted: %s\n\n", resulttext);
54
+
55
+ FPE_ff1_delete_key(ff1);
56
+ FPE_ff3_delete_key(ff3);
57
+
58
+ return 0;
59
+ }
@@ -0,0 +1,411 @@
1
+ #include <stdint.h>
2
+ #include <string.h>
3
+ #include <math.h>
4
+ #include <assert.h>
5
+ #include <openssl/aes.h>
6
+ #include <openssl/crypto.h>
7
+ #include <openssl/bn.h>
8
+ #include "fpe.h"
9
+ #include "fpe_locl.h"
10
+
11
+ // convert numeral string to number
12
+ void str2num(BIGNUM *Y, const unsigned int *X, unsigned long long radix, unsigned int len, BN_CTX *ctx)
13
+ {
14
+ BN_CTX_start(ctx);
15
+ BIGNUM *r = BN_CTX_get(ctx),
16
+ *x = BN_CTX_get(ctx);
17
+
18
+ BN_set_word(Y, 0);
19
+ BN_set_word(r, radix);
20
+ for (int i = 0; i < len; ++i) {
21
+ // Y = Y * radix + X[i]
22
+ BN_set_word(x, X[i]);
23
+ BN_mul(Y, Y, r, ctx);
24
+ BN_add(Y, Y, x);
25
+ }
26
+
27
+ BN_CTX_end(ctx);
28
+ return;
29
+ }
30
+
31
+ // convert number to numeral string
32
+ void num2str(const BIGNUM *X, unsigned int *Y, unsigned int radix, int len, BN_CTX *ctx)
33
+ {
34
+ BN_CTX_start(ctx);
35
+ BIGNUM *dv = BN_CTX_get(ctx),
36
+ *rem = BN_CTX_get(ctx),
37
+ *r = BN_CTX_get(ctx),
38
+ *XX = BN_CTX_get(ctx);
39
+
40
+ BN_copy(XX, X);
41
+ BN_set_word(r, radix);
42
+ memset(Y, 0, len << 2);
43
+
44
+ for (int i = len - 1; i >= 0; --i) {
45
+ // XX / r = dv ... rem
46
+ BN_div(dv, rem, XX, r, ctx);
47
+ // Y[i] = XX % r
48
+ Y[i] = BN_get_word(rem);
49
+ // XX = XX / r
50
+ BN_copy(XX, dv);
51
+ }
52
+
53
+ BN_CTX_end(ctx);
54
+ return;
55
+ }
56
+
57
+ void FF1_encrypt(const unsigned int *plaintext, unsigned int *ciphertext, FPE_KEY *key, const unsigned char *tweak, size_t txtlen, size_t tweaklen)
58
+ {
59
+ BIGNUM *bnum = BN_new(),
60
+ *y = BN_new(),
61
+ *c = BN_new(),
62
+ *anum = BN_new(),
63
+ *qpow_u = BN_new(),
64
+ *qpow_v = BN_new();
65
+ BN_CTX *ctx = BN_CTX_new();
66
+
67
+ union {
68
+ long one;
69
+ char little;
70
+ } is_endian = { 1 };
71
+
72
+ // Calculate split point
73
+ int u = floor2(txtlen, 1);
74
+ int v = txtlen - u;
75
+
76
+ // Split the message
77
+ memcpy(ciphertext, plaintext, txtlen << 2);
78
+ unsigned int *A = ciphertext;
79
+ unsigned int *B = ciphertext + u;
80
+
81
+ pow_uv(qpow_u, qpow_v, key->radix, u, v, ctx);
82
+
83
+ unsigned int temp = (unsigned int)ceil(v * log2(key->radix));
84
+ const int b = ceil2(temp, 3);
85
+ const int d = 4 * ceil2(b, 2) + 4;
86
+
87
+ int pad = ( (-tweaklen - b - 1) % 16 + 16 ) % 16;
88
+ int Qlen = tweaklen + pad + 1 + b;
89
+ unsigned char P[16];
90
+ unsigned char *Q = (unsigned char *)OPENSSL_malloc(Qlen), *Bytes = (unsigned char *)OPENSSL_malloc(b);
91
+
92
+ // initialize P
93
+ P[0] = 0x1;
94
+ P[1] = 0x2;
95
+ P[2] = 0x1;
96
+ P[7] = u % 256;
97
+ if (is_endian.little) {
98
+ temp = (key->radix << 8) | 10;
99
+ P[3] = (temp >> 24) & 0xff;
100
+ P[4] = (temp >> 16) & 0xff;
101
+ P[5] = (temp >> 8) & 0xff;
102
+ P[6] = temp & 0xff;
103
+ P[8] = (txtlen >> 24) & 0xff;
104
+ P[9] = (txtlen >> 16) & 0xff;
105
+ P[10] = (txtlen >> 8) & 0xff;
106
+ P[11] = txtlen & 0xff;
107
+ P[12] = (tweaklen >> 24) & 0xff;
108
+ P[13] = (tweaklen >> 16) & 0xff;
109
+ P[14] = (tweaklen >> 8) & 0xff;
110
+ P[15] = tweaklen & 0xff;
111
+ } else {
112
+ *( (unsigned int *)(P + 3) ) = (key->radix << 8) | 10;
113
+ *( (unsigned int *)(P + 8) ) = txtlen;
114
+ *( (unsigned int *)(P + 12) ) = tweaklen;
115
+ }
116
+
117
+ // initialize Q
118
+ memcpy(Q, tweak, tweaklen);
119
+ memset(Q + tweaklen, 0x00, pad);
120
+ assert(tweaklen + pad - 1 <= Qlen);
121
+
122
+ unsigned char R[16];
123
+ int cnt = ceil2(d, 4) - 1;
124
+ int Slen = 16 + cnt * 16;
125
+ unsigned char *S = (unsigned char *)OPENSSL_malloc(Slen);
126
+ for (int i = 0; i < FF1_ROUNDS; ++i) {
127
+ // v
128
+ int m = (i & 1)? v: u;
129
+
130
+ // i
131
+ Q[tweaklen + pad] = i & 0xff;
132
+ str2num(bnum, B, key->radix, txtlen - m, ctx);
133
+ int BytesLen = BN_bn2bin(bnum, Bytes);
134
+ memset(Q + Qlen - b, 0x00, b);
135
+
136
+ int qtmp = Qlen - BytesLen;
137
+ memcpy(Q + qtmp, Bytes, BytesLen);
138
+
139
+ // ii PRF(P || Q), P is always 16 bytes long
140
+ AES_encrypt(P, R, &key->aes_enc_ctx);
141
+ int count = Qlen / 16;
142
+ unsigned char Ri[16];
143
+ unsigned char *Qi = Q;
144
+ for (int cc = 0; cc < count; ++cc) {
145
+ for (int j = 0; j < 16; ++j) Ri[j] = Qi[j] ^ R[j];
146
+ AES_encrypt(Ri, R, &key->aes_enc_ctx);
147
+ Qi += 16;
148
+ }
149
+
150
+ // iii
151
+ unsigned char tmp[16], SS[16];
152
+ memset(S, 0x00, Slen);
153
+ assert(Slen >= 16);
154
+ memcpy(S, R, 16);
155
+ for (int j = 1; j <= cnt; ++j) {
156
+ memset(tmp, 0x00, 16);
157
+
158
+ if (is_endian.little) {
159
+ // convert to big endian
160
+ // full unroll
161
+ tmp[15] = j & 0xff;
162
+ tmp[14] = (j >> 8) & 0xff;
163
+ tmp[13] = (j >> 16) & 0xff;
164
+ tmp[12] = (j >> 24) & 0xff;
165
+ } else *( (unsigned int *)tmp + 3 ) = j;
166
+
167
+ for (int k = 0; k < 16; ++k) tmp[k] ^= R[k];
168
+ AES_encrypt(tmp, SS, &key->aes_enc_ctx);
169
+ assert((S + 16 * j)[0] == 0x00);
170
+ assert(16 + 16 * j <= Slen);
171
+ memcpy(S + 16 * j, SS, 16);
172
+ }
173
+
174
+ // iv
175
+ BN_bin2bn(S, d, y);
176
+ // vi
177
+ // (num(A, key->radix, m) + y) % qpow(key->radix, m);
178
+ str2num(anum, A, key->radix, m, ctx);
179
+ // anum = (anum + y) mod qpow_uv
180
+ if (m == u) BN_mod_add(c, anum, y, qpow_u, ctx);
181
+ else BN_mod_add(c, anum, y, qpow_v, ctx);
182
+
183
+ // swap A and B
184
+ assert(A != B);
185
+ A = (unsigned int *)( (uintptr_t)A ^ (uintptr_t)B );
186
+ B = (unsigned int *)( (uintptr_t)B ^ (uintptr_t)A );
187
+ A = (unsigned int *)( (uintptr_t)A ^ (uintptr_t)B );
188
+ num2str(c, B, key->radix, m, ctx);
189
+ }
190
+
191
+ // free the space
192
+ BN_clear_free(anum);
193
+ BN_clear_free(bnum);
194
+ BN_clear_free(c);
195
+ BN_clear_free(y);
196
+ BN_clear_free(qpow_u);
197
+ BN_clear_free(qpow_v);
198
+ BN_CTX_free(ctx);
199
+ OPENSSL_free(Bytes);
200
+ OPENSSL_free(Q);
201
+ OPENSSL_free(S);
202
+ return;
203
+ }
204
+
205
+ void FF1_decrypt(const unsigned int *ciphertext, unsigned int *plaintext, FPE_KEY *key, const unsigned char *tweak, size_t txtlen, size_t tweaklen)
206
+ {
207
+ BIGNUM *bnum = BN_new(),
208
+ *y = BN_new(),
209
+ *c = BN_new(),
210
+ *anum = BN_new(),
211
+ *qpow_u = BN_new(),
212
+ *qpow_v = BN_new();
213
+ BN_CTX *ctx = BN_CTX_new();
214
+
215
+ union {
216
+ long one;
217
+ char little;
218
+ } is_endian = { 1 };
219
+
220
+ // Calculate split point
221
+ int u = floor2(txtlen, 1);
222
+ int v = txtlen - u;
223
+
224
+ // Split the message
225
+ memcpy(plaintext, ciphertext, txtlen << 2);
226
+ unsigned int *A = plaintext, *B = plaintext + u;
227
+ pow_uv(qpow_u, qpow_v, key->radix, u, v, ctx);
228
+
229
+ unsigned int temp = (unsigned int)ceil(v * log2(key->radix));
230
+ const int b = ceil2(temp, 3);
231
+ const int d = 4 * ceil2(b, 2) + 4;
232
+
233
+ int pad = ( (-tweaklen - b - 1) % 16 + 16 ) % 16;
234
+ int Qlen = tweaklen + pad + 1 + b;
235
+ unsigned char P[16];
236
+ unsigned char *Q = (unsigned char *)OPENSSL_malloc(Qlen), *Bytes = (unsigned char *)OPENSSL_malloc(b);
237
+ // initialize P
238
+ P[0] = 0x1;
239
+ P[1] = 0x2;
240
+ P[2] = 0x1;
241
+ P[7] = u % 256;
242
+ if (is_endian.little) {
243
+ temp = (key->radix << 8) | 10;
244
+ P[3] = (temp >> 24) & 0xff;
245
+ P[4] = (temp >> 16) & 0xff;
246
+ P[5] = (temp >> 8) & 0xff;
247
+ P[6] = temp & 0xff;
248
+ P[8] = (txtlen >> 24) & 0xff;
249
+ P[9] = (txtlen >> 16) & 0xff;
250
+ P[10] = (txtlen >> 8) & 0xff;
251
+ P[11] = txtlen & 0xff;
252
+ P[12] = (tweaklen >> 24) & 0xff;
253
+ P[13] = (tweaklen >> 16) & 0xff;
254
+ P[14] = (tweaklen >> 8) & 0xff;
255
+ P[15] = tweaklen & 0xff;
256
+ } else {
257
+ *( (unsigned int *)(P + 3) ) = (key->radix << 8) | 10;
258
+ *( (unsigned int *)(P + 8) ) = txtlen;
259
+ *( (unsigned int *)(P + 12) ) = tweaklen;
260
+ }
261
+
262
+ // initialize Q
263
+ memcpy(Q, tweak, tweaklen);
264
+ memset(Q + tweaklen, 0x00, pad);
265
+ assert(tweaklen + pad - 1 <= Qlen);
266
+
267
+ unsigned char R[16];
268
+ int cnt = ceil2(d, 4) - 1;
269
+ int Slen = 16 + cnt * 16;
270
+ unsigned char *S = (unsigned char *)OPENSSL_malloc(Slen);
271
+ for (int i = FF1_ROUNDS - 1; i >= 0; --i) {
272
+ // v
273
+ int m = (i & 1)? v: u;
274
+
275
+ // i
276
+ Q[tweaklen + pad] = i & 0xff;
277
+ str2num(anum, A, key->radix, txtlen - m, ctx);
278
+ memset(Q + Qlen - b, 0x00, b);
279
+ int BytesLen = BN_bn2bin(anum, Bytes);
280
+ int qtmp = Qlen - BytesLen;
281
+ memcpy(Q + qtmp, Bytes, BytesLen);
282
+
283
+ // ii PRF(P || Q)
284
+ memset(R, 0x00, sizeof(R));
285
+ AES_encrypt(P, R, &key->aes_enc_ctx);
286
+ int count = Qlen / 16;
287
+ unsigned char Ri[16];
288
+ unsigned char *Qi = Q;
289
+ for (int cc = 0; cc < count; ++cc) {
290
+ for (int j = 0; j < 16; ++j) Ri[j] = Qi[j] ^ R[j];
291
+ AES_encrypt(Ri, R, &key->aes_enc_ctx);
292
+ Qi += 16;
293
+ }
294
+
295
+ // iii
296
+ unsigned char tmp[16], SS[16];
297
+ memset(S, 0x00, Slen);
298
+ memcpy(S, R, 16);
299
+ for (int j = 1; j <= cnt; ++j) {
300
+ memset(tmp, 0x00, 16);
301
+
302
+ if (is_endian.little) {
303
+ // convert to big endian
304
+ // full unroll
305
+ tmp[15] = j & 0xff;
306
+ tmp[14] = (j >> 8) & 0xff;
307
+ tmp[13] = (j >> 16) & 0xff;
308
+ tmp[12] = (j >> 24) & 0xff;
309
+ } else *( (unsigned int *)tmp + 3 ) = j;
310
+
311
+ for (int k = 0; k < 16; ++k) tmp[k] ^= R[k];
312
+ AES_encrypt(tmp, SS, &key->aes_enc_ctx);
313
+ assert((S + 16 * j)[0] == 0x00);
314
+ memcpy(S + 16 * j, SS, 16);
315
+ }
316
+
317
+ // iv
318
+ BN_bin2bn(S, d, y);
319
+ // vi
320
+ // (num(B, key->radix, m) - y) % qpow(key->radix, m);
321
+ str2num(bnum, B, key->radix, m, ctx);
322
+ if (m == u) BN_mod_sub(c, bnum, y, qpow_u, ctx);
323
+ else BN_mod_sub(c, bnum, y, qpow_v, ctx);
324
+
325
+ // swap A and B
326
+ assert(A != B);
327
+ A = (unsigned int *)( (uintptr_t)A ^ (uintptr_t)B );
328
+ B = (unsigned int *)( (uintptr_t)B ^ (uintptr_t)A );
329
+ A = (unsigned int *)( (uintptr_t)A ^ (uintptr_t)B );
330
+ num2str(c, A, key->radix, m, ctx);
331
+
332
+ }
333
+
334
+ // free the space
335
+ BN_clear_free(anum);
336
+ BN_clear_free(bnum);
337
+ BN_clear_free(y);
338
+ BN_clear_free(c);
339
+ BN_clear_free(qpow_u);
340
+ BN_clear_free(qpow_v);
341
+ BN_CTX_free(ctx);
342
+ OPENSSL_free(Bytes);
343
+ OPENSSL_free(Q);
344
+ OPENSSL_free(S);
345
+ return;
346
+ }
347
+
348
+ int create_ff1_key(const unsigned char *userKey, const int bits, const unsigned char *tweak, const unsigned int tweaklen, const unsigned int radix, FPE_KEY *key)
349
+ {
350
+ int ret;
351
+ if (bits != 128 && bits != 192 && bits != 256) {
352
+ ret = -1;
353
+ return ret;
354
+ }
355
+ key->tweaklen = tweaklen;
356
+ key->tweak = (unsigned char *)OPENSSL_malloc(tweaklen);
357
+ memcpy(key->tweak, tweak, tweaklen);
358
+ ret = AES_set_encrypt_key(userKey, bits, &key->aes_enc_ctx);
359
+ key->radix = radix;
360
+ return ret;
361
+ }
362
+
363
+ FPE_KEY* FPE_ff1_create_key(const char *key, const char *tweak, unsigned int radix)
364
+ {
365
+ unsigned char k[100],
366
+ t[100];
367
+ int klen = strlen(key) / 2;
368
+ int tlen = strlen(tweak) / 2;
369
+
370
+ hex2chars(key, k);
371
+ hex2chars(tweak, t);
372
+
373
+ FPE_KEY *keystruct = (FPE_KEY *)OPENSSL_malloc(sizeof(FPE_KEY));
374
+ create_ff1_key(k,klen*8,t,tlen,radix,keystruct);
375
+ return keystruct;
376
+ }
377
+
378
+ void FPE_ff1_delete_key(FPE_KEY *key)
379
+ {
380
+ OPENSSL_clear_free(key->tweak,key->tweaklen/8);
381
+ OPENSSL_clear_free(key,sizeof(key));
382
+ }
383
+
384
+ void FPE_ff1_encrypt(char *plaintext, char *ciphertext, FPE_KEY *key)
385
+ {
386
+ int txtlen = strlen(plaintext);
387
+ unsigned int x[100],
388
+ y[txtlen];
389
+ map_chars(plaintext, x);
390
+
391
+ printf("plaintext: ");
392
+ for (int i = 0; i < txtlen; ++i) printf("%d", x[i]);
393
+ printf("\n\n");
394
+
395
+ FF1_encrypt(x, y, key, key->tweak, txtlen, key->tweaklen);
396
+
397
+ inverse_map_chars(y, ciphertext, txtlen);
398
+ }
399
+
400
+ void FPE_ff1_decrypt(char *ciphertext, char* plaintext, FPE_KEY *key)
401
+ {
402
+ int txtlen = strlen(ciphertext);
403
+ unsigned int x[100],
404
+ y[txtlen];
405
+ map_chars(ciphertext, x);
406
+
407
+ FF1_decrypt(x, y, key, key->tweak, txtlen, key->tweaklen);
408
+
409
+ inverse_map_chars(y, plaintext, txtlen);
410
+ }
411
+