1
|
|
/*
|
2
|
|
*******************************************************************************
|
3
|
|
\file hex.c
|
4
|
|
\brief Hexadecimal strings
|
5
|
|
\project bee2 [cryptographic library]
|
6
|
|
\author (C) Sergey Agievich [agievich@{bsu.by|gmail.com}]
|
7
|
|
\created 2015.10.29
|
8
|
|
\version 2016.06.19
|
9
|
|
\license This program is released under the GNU General Public License
|
10
|
|
version 3. See Copyright Notices in bee2/info.h.
|
11
|
|
*******************************************************************************
|
12
|
|
*/
|
13
|
|
|
14
|
|
#include "bee2/core/hex.h"
|
15
|
|
#include "bee2/core/mem.h"
|
16
|
|
#include "bee2/core/str.h"
|
17
|
|
#include "bee2/core/util.h"
|
18
|
|
#include "bee2/core/word.h"
|
19
|
|
|
20
|
|
/*
|
21
|
|
*******************************************************************************
|
22
|
|
Таблицы
|
23
|
|
*******************************************************************************
|
24
|
|
*/
|
25
|
|
|
26
|
|
static const char hex_upper[] = "0123456789ABCDEF";
|
27
|
|
static const char hex_lower[] = "0123456789abcdef";
|
28
|
|
|
29
|
|
static const octet hex_dec_table[256] = {
|
30
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
31
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
32
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
33
|
|
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
34
|
|
0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
35
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
36
|
|
0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
37
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
38
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
39
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
40
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
41
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
42
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
43
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
44
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
45
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
46
|
|
};
|
47
|
|
|
48
|
|
/*
|
49
|
|
*******************************************************************************
|
50
|
|
Октеты
|
51
|
|
*******************************************************************************
|
52
|
|
*/
|
53
|
|
|
54
|
1
|
static octet hexToO(const char* hex)
|
55
|
|
{
|
56
|
|
register octet hi;
|
57
|
|
register octet lo;
|
58
|
1
|
ASSERT(memIsValid(hex, 2));
|
59
|
1
|
hi = hex_dec_table[(octet)hex[0]];
|
60
|
1
|
lo = hex_dec_table[(octet)hex[1]];
|
61
|
1
|
ASSERT(hi != 0xFF && lo != 0xFF);
|
62
|
1
|
return hi << 4 | lo;
|
63
|
|
}
|
64
|
|
|
65
|
1
|
static void hexFromOUpper(char* hex, register octet o)
|
66
|
|
{
|
67
|
1
|
ASSERT(memIsValid(hex, 2));
|
68
|
1
|
hex[0] = hex_upper[o >> 4];
|
69
|
1
|
hex[1] = hex_upper[o & 15];
|
70
|
1
|
o = 0;
|
71
|
|
}
|
72
|
|
|
73
|
1
|
static void hexFromOLower(char* hex, register octet o)
|
74
|
|
{
|
75
|
1
|
ASSERT(memIsValid(hex, 2));
|
76
|
1
|
hex[0] = hex_lower[o >> 4];
|
77
|
1
|
hex[1] = hex_lower[o & 15];
|
78
|
1
|
o = 0;
|
79
|
|
}
|
80
|
|
|
81
|
|
/*
|
82
|
|
*******************************************************************************
|
83
|
|
Проверка
|
84
|
|
*******************************************************************************
|
85
|
|
*/
|
86
|
|
|
87
|
1
|
bool_t hexIsValid(const char* hex)
|
88
|
|
{
|
89
|
1
|
if (!strIsValid(hex) || strLen(hex) % 2)
|
90
|
1
|
return FALSE;
|
91
|
1
|
for (; *hex; ++hex)
|
92
|
1
|
if (hex_dec_table[(octet)*hex] == 0xFF)
|
93
|
1
|
return FALSE;
|
94
|
1
|
return TRUE;
|
95
|
|
}
|
96
|
|
|
97
|
|
/*
|
98
|
|
*******************************************************************************
|
99
|
|
Регистр
|
100
|
|
*******************************************************************************
|
101
|
|
*/
|
102
|
|
|
103
|
1
|
void hexUpper(char* hex)
|
104
|
|
{
|
105
|
1
|
ASSERT(hexIsValid(hex));
|
106
|
1
|
for (; *hex; hex += 2)
|
107
|
1
|
hexFromOUpper(hex, hexToO(hex));
|
108
|
|
}
|
109
|
|
|
110
|
1
|
void hexLower(char* hex)
|
111
|
|
{
|
112
|
1
|
ASSERT(hexIsValid(hex));
|
113
|
1
|
for (; *hex; hex += 2)
|
114
|
1
|
hexFromOLower(hex, hexToO(hex));
|
115
|
|
}
|
116
|
|
|
117
|
|
/*
|
118
|
|
*******************************************************************************
|
119
|
|
Сравнения
|
120
|
|
*******************************************************************************
|
121
|
|
*/
|
122
|
|
|
123
|
1
|
bool_t SAFE(hexEq)(const void* buf, const char* hex)
|
124
|
|
{
|
125
|
1
|
register word diff = 0;
|
126
|
|
size_t count;
|
127
|
1
|
ASSERT(hexIsValid(hex));
|
128
|
1
|
ASSERT(memIsValid(buf, strLen(hex) / 2));
|
129
|
1
|
count = strLen(hex);
|
130
|
1
|
for (; count; count -= 2, hex += 2, buf = (const octet*)buf + 1)
|
131
|
1
|
diff |= *(const octet*)buf ^ hexToO(hex);
|
132
|
1
|
return wordEq(diff, 0);
|
133
|
|
}
|
134
|
|
|
135
|
0
|
bool_t FAST(hexEq)(const void* buf, const char* hex)
|
136
|
|
{
|
137
|
|
size_t count;
|
138
|
0
|
ASSERT(hexIsValid(hex));
|
139
|
0
|
ASSERT(memIsValid(buf, strLen(hex) / 2));
|
140
|
0
|
count = strLen(hex);
|
141
|
0
|
for (; count; count -= 2, hex += 2, buf = (const octet*)buf + 1)
|
142
|
0
|
if (*(const octet*)buf != hexToO(hex))
|
143
|
0
|
return FALSE;
|
144
|
0
|
return TRUE;
|
145
|
|
}
|
146
|
|
|
147
|
1
|
bool_t SAFE(hexEqRev)(const void* buf, const char* hex)
|
148
|
|
{
|
149
|
1
|
register word diff = 0;
|
150
|
|
size_t count;
|
151
|
1
|
ASSERT(hexIsValid(hex));
|
152
|
1
|
ASSERT(memIsValid(buf, strLen(hex) / 2));
|
153
|
1
|
count = strLen(hex);
|
154
|
1
|
hex = hex + count;
|
155
|
1
|
for (; count; count -= 2, buf = (const octet*)buf + 1)
|
156
|
1
|
diff |= *(const octet*)buf ^ hexToO(hex -= 2);
|
157
|
1
|
return wordEq(diff, 0);
|
158
|
|
}
|
159
|
|
|
160
|
0
|
bool_t FAST(hexEqRev)(const void* buf, const char* hex)
|
161
|
|
{
|
162
|
|
size_t count;
|
163
|
0
|
ASSERT(hexIsValid(hex));
|
164
|
0
|
ASSERT(memIsValid(buf, strLen(hex) / 2));
|
165
|
0
|
count = strLen(hex);
|
166
|
0
|
hex = hex + count;
|
167
|
0
|
for (; count; count -= 2, buf = (const octet*)buf + 1)
|
168
|
0
|
if (*(const octet*)buf != hexToO(hex -= 2))
|
169
|
0
|
return FALSE;
|
170
|
0
|
return TRUE;
|
171
|
|
}
|
172
|
|
|
173
|
|
/*
|
174
|
|
*******************************************************************************
|
175
|
|
Кодирование
|
176
|
|
*******************************************************************************
|
177
|
|
*/
|
178
|
|
|
179
|
1
|
void hexFrom(char* dest, const void* src, size_t count)
|
180
|
|
{
|
181
|
1
|
ASSERT(memIsDisjoint2(src, count, dest, 2 * count + 1));
|
182
|
1
|
for (; count--; dest += 2, src = (const octet*)src + 1)
|
183
|
1
|
hexFromOUpper(dest, *(const octet*)src);
|
184
|
1
|
*dest = '\0';
|
185
|
|
}
|
186
|
|
|
187
|
1
|
void hexFromRev(char* dest, const void* src, size_t count)
|
188
|
|
{
|
189
|
1
|
ASSERT(memIsDisjoint2(src, count, dest, 2 * count + 1));
|
190
|
1
|
dest = dest + 2 * count;
|
191
|
1
|
*dest = '\0';
|
192
|
1
|
for (; count--; src = (const octet*)src + 1)
|
193
|
1
|
hexFromOUpper(dest -= 2, *(const octet*)src);
|
194
|
|
}
|
195
|
|
|
196
|
1
|
void hexTo(void* dest, const char* src)
|
197
|
|
{
|
198
|
|
size_t count;
|
199
|
1
|
ASSERT(hexIsValid(src));
|
200
|
1
|
ASSERT(memIsDisjoint2(src, strLen(src) + 1, dest, strLen(src) / 2));
|
201
|
1
|
count = strLen(src);
|
202
|
1
|
for (; count; count -= 2, src += 2, dest = (octet*)dest + 1)
|
203
|
1
|
*(octet*)dest = hexToO(src);
|
204
|
|
}
|
205
|
|
|
206
|
1
|
void hexToRev(void* dest, const char* src)
|
207
|
|
{
|
208
|
|
size_t count;
|
209
|
1
|
ASSERT(hexIsValid(src));
|
210
|
1
|
ASSERT(memIsDisjoint2(src, strLen(src) + 1, dest, strLen(src) / 2));
|
211
|
1
|
count = strLen(src);
|
212
|
1
|
src = src + count;
|
213
|
1
|
for (; count; count -= 2, dest = (octet*)dest + 1)
|
214
|
1
|
*(octet*)dest = hexToO(src -= 2);
|
215
|
|
}
|