Botan  2.7.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  if(top_nibble)
118  *out_ptr |= bin << 4;
119  else
120  *out_ptr |= bin;
121 
122  top_nibble = !top_nibble;
123  if(top_nibble)
124  ++out_ptr;
125  }
126 
127  input_consumed = input_length;
128  size_t written = (out_ptr - output);
129 
130  /*
131  * We only got half of a uint8_t at the end; zap the half-written
132  * output and mark it as unread
133  */
134  if(!top_nibble)
135  {
136  *out_ptr = 0;
137  input_consumed -= 1;
138  }
139 
140  return written;
141  }
142 
143 size_t hex_decode(uint8_t output[],
144  const char input[],
145  size_t input_length,
146  bool ignore_ws)
147  {
148  size_t consumed = 0;
149  size_t written = hex_decode(output, input, input_length,
150  consumed, ignore_ws);
151 
152  if(consumed != input_length)
153  throw Invalid_Argument("hex_decode: input did not have full bytes");
154 
155  return written;
156  }
157 
158 size_t hex_decode(uint8_t output[],
159  const std::string& input,
160  bool ignore_ws)
161  {
162  return hex_decode(output, input.data(), input.length(), ignore_ws);
163  }
164 
166  size_t input_length,
167  bool ignore_ws)
168  {
169  secure_vector<uint8_t> bin(1 + input_length / 2);
170 
171  size_t written = hex_decode(bin.data(),
172  input,
173  input_length,
174  ignore_ws);
175 
176  bin.resize(written);
177  return bin;
178  }
179 
180 secure_vector<uint8_t> hex_decode_locked(const std::string& input,
181  bool ignore_ws)
182  {
183  return hex_decode_locked(input.data(), input.size(), ignore_ws);
184  }
185 
186 std::vector<uint8_t> hex_decode(const char input[],
187  size_t input_length,
188  bool ignore_ws)
189  {
190  std::vector<uint8_t> bin(1 + input_length / 2);
191 
192  size_t written = hex_decode(bin.data(),
193  input,
194  input_length,
195  ignore_ws);
196 
197  bin.resize(written);
198  return bin;
199  }
200 
201 std::vector<uint8_t> hex_decode(const std::string& input,
202  bool ignore_ws)
203  {
204  return hex_decode(input.data(), input.size(), ignore_ws);
205  }
206 
207 }
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition: hex.cpp:14
secure_vector< uint8_t > hex_decode_locked(const char input[], size_t input_length, bool ignore_ws)
Definition: hex.cpp:165
void clear_mem(T *ptr, size_t n)
Definition: mem_ops.h:97
Definition: alg_id.cpp:13
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
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88