Botan  2.1.0
Crypto and TLS for C++11
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 
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 }
void clear_mem(T *ptr, size_t n)
Definition: mem_ops.h:57
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:121
secure_vector< uint8_t > hex_decode_locked(const char input[], size_t input_length, bool ignore_ws)
Definition: hex.cpp:162
Definition: alg_id.cpp:13
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition: hex.cpp:14
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