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