ruby_clang_fpe 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+