Botan
1.11.15
|
00001 /* 00002 * Hex Encoding and Decoding 00003 * (C) 2010 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/hex.h> 00009 #include <botan/mem_ops.h> 00010 #include <stdexcept> 00011 00012 namespace Botan { 00013 00014 void hex_encode(char output[], 00015 const byte input[], 00016 size_t input_length, 00017 bool uppercase) 00018 { 00019 static const byte BIN_TO_HEX_UPPER[16] = { 00020 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 00021 'A', 'B', 'C', 'D', 'E', 'F' }; 00022 00023 static const byte BIN_TO_HEX_LOWER[16] = { 00024 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 00025 'a', 'b', 'c', 'd', 'e', 'f' }; 00026 00027 const byte* tbl = uppercase ? BIN_TO_HEX_UPPER : BIN_TO_HEX_LOWER; 00028 00029 for(size_t i = 0; i != input_length; ++i) 00030 { 00031 byte x = input[i]; 00032 output[2*i ] = tbl[(x >> 4) & 0x0F]; 00033 output[2*i+1] = tbl[(x ) & 0x0F]; 00034 } 00035 } 00036 00037 std::string hex_encode(const byte input[], 00038 size_t input_length, 00039 bool uppercase) 00040 { 00041 std::string output(2 * input_length, 0); 00042 00043 if(input_length) 00044 hex_encode(&output[0], input, input_length, uppercase); 00045 00046 return output; 00047 } 00048 00049 size_t hex_decode(byte output[], 00050 const char input[], 00051 size_t input_length, 00052 size_t& input_consumed, 00053 bool ignore_ws) 00054 { 00055 /* 00056 * Mapping of hex characters to either their binary equivalent 00057 * or to an error code. 00058 * If valid hex (0-9 A-F a-f), the value. 00059 * If whitespace, then 0x80 00060 * Otherwise 0xFF 00061 * Warning: this table assumes ASCII character encodings 00062 */ 00063 00064 static const byte HEX_TO_BIN[256] = { 00065 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 00066 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00067 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00068 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00069 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 00070 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF, 00071 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 00072 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00073 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00074 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, 00075 0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00076 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00077 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00078 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00079 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00080 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00081 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00082 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00083 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00084 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00085 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00086 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00087 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00088 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00089 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00090 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 00091 00092 byte* out_ptr = output; 00093 bool top_nibble = true; 00094 00095 clear_mem(output, input_length / 2); 00096 00097 for(size_t i = 0; i != input_length; ++i) 00098 { 00099 const byte bin = HEX_TO_BIN[static_cast<byte>(input[i])]; 00100 00101 if(bin >= 0x10) 00102 { 00103 if(bin == 0x80 && ignore_ws) 00104 continue; 00105 00106 std::string bad_char(1, input[i]); 00107 if(bad_char == "\t") 00108 bad_char = "\\t"; 00109 else if(bad_char == "\n") 00110 bad_char = "\\n"; 00111 00112 throw std::invalid_argument( 00113 std::string("hex_decode: invalid hex character '") + 00114 bad_char + "'"); 00115 } 00116 00117 *out_ptr |= bin << (top_nibble*4); 00118 00119 top_nibble = !top_nibble; 00120 if(top_nibble) 00121 ++out_ptr; 00122 } 00123 00124 input_consumed = input_length; 00125 size_t written = (out_ptr - output); 00126 00127 /* 00128 * We only got half of a byte at the end; zap the half-written 00129 * output and mark it as unread 00130 */ 00131 if(!top_nibble) 00132 { 00133 *out_ptr = 0; 00134 input_consumed -= 1; 00135 } 00136 00137 return written; 00138 } 00139 00140 size_t hex_decode(byte output[], 00141 const char input[], 00142 size_t input_length, 00143 bool ignore_ws) 00144 { 00145 size_t consumed = 0; 00146 size_t written = hex_decode(output, input, input_length, 00147 consumed, ignore_ws); 00148 00149 if(consumed != input_length) 00150 throw std::invalid_argument("hex_decode: input did not have full bytes"); 00151 00152 return written; 00153 } 00154 00155 size_t hex_decode(byte output[], 00156 const std::string& input, 00157 bool ignore_ws) 00158 { 00159 return hex_decode(output, &input[0], input.length(), ignore_ws); 00160 } 00161 00162 secure_vector<byte> hex_decode_locked(const char input[], 00163 size_t input_length, 00164 bool ignore_ws) 00165 { 00166 secure_vector<byte> bin(1 + input_length / 2); 00167 00168 size_t written = hex_decode(&bin[0], 00169 input, 00170 input_length, 00171 ignore_ws); 00172 00173 bin.resize(written); 00174 return bin; 00175 } 00176 00177 secure_vector<byte> hex_decode_locked(const std::string& input, 00178 bool ignore_ws) 00179 { 00180 return hex_decode_locked(&input[0], input.size(), ignore_ws); 00181 } 00182 00183 std::vector<byte> hex_decode(const char input[], 00184 size_t input_length, 00185 bool ignore_ws) 00186 { 00187 std::vector<byte> bin(1 + input_length / 2); 00188 00189 size_t written = hex_decode(&bin[0], 00190 input, 00191 input_length, 00192 ignore_ws); 00193 00194 bin.resize(written); 00195 return bin; 00196 } 00197 00198 std::vector<byte> hex_decode(const std::string& input, 00199 bool ignore_ws) 00200 { 00201 return hex_decode(&input[0], input.size(), ignore_ws); 00202 } 00203 00204 }