Botan 2.1.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

hex.cpp
Go to the documentation of this file.
1 /*
2 * Hex Encoding and Decoding
3 * (C) 2010 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7
8 #include <botan/hex.h>
9 #include <botan/mem_ops.h>
10 #include <botan/exceptn.h>
11
12 namespace Botan {
13
14 void hex_encode(char output[],
15 const uint8_t input[],
16 size_t input_length,
17 bool uppercase)
18 {
19 static const uint8_t BIN_TO_HEX_UPPER[16] = {
20 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
21 'A', 'B', 'C', 'D', 'E', 'F' };
22
23 static const uint8_t BIN_TO_HEX_LOWER[16] = {
24 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
25 'a', 'b', 'c', 'd', 'e', 'f' };
26
27 const uint8_t* tbl = uppercase ? BIN_TO_HEX_UPPER : BIN_TO_HEX_LOWER;
28
29 for(size_t i = 0; i != input_length; ++i)
30 {
31 uint8_t x = input[i];
32 output[2*i ] = tbl[(x >> 4) & 0x0F];
33 output[2*i+1] = tbl[(x ) & 0x0F];
34 }
35 }
36
37 std::string hex_encode(const uint8_t input[],
38 size_t input_length,
39 bool uppercase)
40 {
41 std::string output(2 * input_length, 0);
42
43 if(input_length)
44 hex_encode(&output.front(), input, input_length, uppercase);
45
46 return output;
47 }
48
49 size_t hex_decode(uint8_t output[],
50 const char input[],
51 size_t input_length,
52 size_t& input_consumed,
53 bool ignore_ws)
54 {
55 /*
56 * Mapping of hex characters to either their binary equivalent
57 * or to an error code.
58 * If valid hex (0-9 A-F a-f), the value.
59 * If whitespace, then 0x80
60 * Otherwise 0xFF
61 * Warning: this table assumes ASCII character encodings
62 */
63
64 static const uint8_t HEX_TO_BIN[256] = {
65 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80,
66 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
67 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
68 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
69 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01,
70 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF,
71 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
72 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
73 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
74 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C,
75 0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
76 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
77 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
78 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
79 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
80 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
81 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
82 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
83 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
84 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
85 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
86 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
87 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
88 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
89 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
90 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
91
92 uint8_t* out_ptr = output;
93 bool top_nibble = true;
94
95 clear_mem(output, input_length / 2);
96
97 for(size_t i = 0; i != input_length; ++i)
98 {
99 const uint8_t bin = HEX_TO_BIN[static_cast<uint8_t>(input[i])];
100
101 if(bin >= 0x10)
102 {
103 if(bin == 0x80 && ignore_ws)
104 continue;
105
106 std::string bad_char(1, input[i]);
107 if(bad_char == "\t")
108 bad_char = "\\t";
109 else if(bad_char == "\n")
110 bad_char = "\\n";
111
112 throw Invalid_Argument(
113 std::string("hex_decode: invalid hex character '") +
114 bad_char + "'");
115 }
116
117 *out_ptr |= bin << (top_nibble*4);
118
119 top_nibble = !top_nibble;
120 if(top_nibble)
121 ++out_ptr;
122 }
123
124 input_consumed = input_length;
125 size_t written = (out_ptr - output);
126
127 /*
128 * We only got half of a uint8_t at the end; zap the half-written
129 * output and mark it as unread
130 */
131 if(!top_nibble)
132 {
133 *out_ptr = 0;
134 input_consumed -= 1;
135 }
136
137 return written;
138 }
139
140 size_t hex_decode(uint8_t output[],
141 const char input[],
142 size_t input_length,
143 bool ignore_ws)
144 {
145 size_t consumed = 0;
146 size_t written = hex_decode(output, input, input_length,
147 consumed, ignore_ws);
148
149 if(consumed != input_length)
150 throw Invalid_Argument("hex_decode: input did not have full bytes");
151
152 return written;
153 }
154
155 size_t hex_decode(uint8_t output[],
156 const std::string& input,
157 bool ignore_ws)
158 {
159 return hex_decode(output, input.data(), input.length(), ignore_ws);
160 }
161
162 secure_vector<uint8_t> hex_decode_locked(const char input[],
163 size_t input_length,
164 bool ignore_ws)
165 {
166 secure_vector<uint8_t> bin(1 + input_length / 2);
167
168 size_t written = hex_decode(bin.data(),
169 input,
170 input_length,
171 ignore_ws);
172
173 bin.resize(written);
174 return bin;
175 }
176
177 secure_vector<uint8_t> hex_decode_locked(const std::string& input,
178 bool ignore_ws)
179 {
180 return hex_decode_locked(input.data(), input.size(), ignore_ws);
181 }
182
183 std::vector<uint8_t> hex_decode(const char input[],
184 size_t input_length,
185 bool ignore_ws)
186 {
187 std::vector<uint8_t> bin(1 + input_length / 2);
188
189 size_t written = hex_decode(bin.data(),
190 input,
191 input_length,
192 ignore_ws);
193
194 bin.resize(written);
195 return bin;
196 }
197
198 std::vector<uint8_t> hex_decode(const std::string& input,
199 bool ignore_ws)
200 {
201 return hex_decode(input.data(), input.size(), ignore_ws);
202 }
203
204 }
Botan::Invalid_Argument
Definition: exceptn.h:34
Botan::clear_mem
void clear_mem(T *ptr, size_t n)
Definition: mem_ops.h:57
Botan::secure_vector
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:121
Botan::hex_decode_locked
secure_vector< uint8_t > hex_decode_locked(const char input[], size_t input_length, bool ignore_ws)
Definition: hex.cpp:162
Botan
Definition: alg_id.cpp:13
Botan::hex_encode
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition: hex.cpp:14
Botan::hex_decode
size_t hex_decode(uint8_t output[], const char input[], size_t input_length, size_t &input_consumed, bool ignore_ws)
Definition: hex.cpp:49