-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathblowfish.c
122 lines (96 loc) · 2.63 KB
/
blowfish.c
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
#include <err.h>
#include "blowfish.h"
const char B64[] =
"./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
/* decode base64 string */
static uint32_t
base64dec (char c)
{
size_t i;
for (i = 0; i < 64; i++)
if (B64[i] == c)
return i;
return 0;
}
static uint32_t
load32_be (const void *p)
{
const unsigned char *in = p;
return (uint32_t) in[0] << 24 |
(uint32_t) in[1] << 16 | (uint32_t) in[2] << 8 | (uint32_t) in[3] << 0;
}
static void
store32_be (void *p, uint32_t v)
{
unsigned char *out = p;
out[0] = v >> 24;
out[1] = v >> 16;
out[2] = v >> 8;
out[3] = v >> 0;
}
/* Returned string must be freed when done with it! */
int
encrypt_string (const char *key, const char *str, char *dest, int len)
{
BF_KEY bf_key;
if (!key || !key[0])
return 0;
BF_set_key (&bf_key, strlen (key), (const unsigned char *) key);
while (len > 0)
{
const size_t blocksize = len < 8 ? len : BF_BLOCK;
unsigned char block[BF_BLOCK] = { 0 }; /* pad with zero */
uint32_t v;
size_t i;
memcpy (block, str, blocksize);
BF_ecb_encrypt (block, block, &bf_key, BF_ENCRYPT);
for (v = load32_be (block + 4), i = 0; i < 6; ++i)
{
*dest++ = B64[v & 0x3f];
v >>= 6;
}
for (v = load32_be (block + 0), i = 0; i < 6; ++i)
{
*dest++ = B64[v & 0x3f];
v >>= 6;
}
len -= blocksize;
str += blocksize;
}
*dest++ = 0;
return 1;
}
int
decrypt_string (const char *key, const char *str, char *dest, int len)
{
BF_KEY bf_key;
uint32_t v;
size_t i;
/* Pad encoded string with 0 bits in case it's bogus */
if (!key || !key[0]) {
errx(1, "!key || !key[0]");
return 0;
}
/* length must be a multiple of BF_BLOCK encoded in base64 */
if (len % (BF_BLOCK * 6 / 4) != 0) {
warnx("len %% (BF_BLOCK * 6 / 4) != 0: %d, %s", len, str);
len -= len % (BF_BLOCK * 6 / 4);
}
BF_set_key (&bf_key, strlen (key), (const unsigned char *) key);
while (len > 0)
{
unsigned char block[BF_BLOCK] = { 0 };
for (i = v = 0; i < 6; ++i)
v |= base64dec (*str++) << (i * 6);
store32_be (block + 4, v);
for (i = v = 0; i < 6; ++i)
v |= base64dec (*str++) << (i * 6);
store32_be (block + 0, v);
BF_ecb_encrypt (block, block, &bf_key, BF_DECRYPT);
memcpy (dest, block, BF_BLOCK);
dest += BF_BLOCK;
len -= BF_BLOCK * 6 / 4;
}
*dest++ = 0;
return 1;
}