/src/kea/src/lib/util/encode/encode.h
Line | Count | Source |
1 | | // Copyright (C) 2024 Internet Systems Consortium, Inc. ("ISC") |
2 | | // |
3 | | // This Source Code Form is subject to the terms of the Mozilla Public |
4 | | // License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | // file, You can obtain one at http://mozilla.org/MPL/2.0/. |
6 | | |
7 | | #ifndef ENCODE_H |
8 | | #define ENCODE_H |
9 | | |
10 | | #include <stdint.h> |
11 | | #include <string> |
12 | | #include <vector> |
13 | | |
14 | | namespace isc { |
15 | | namespace util { |
16 | | namespace encode { |
17 | | |
18 | | /// @brief Class for encoding and decoding binary data using an algorithm |
19 | | /// described in RFC 4648. |
20 | | class BaseNEncoder { |
21 | | public: |
22 | | |
23 | | /// @brief Constructor |
24 | | /// |
25 | | /// @param algorithm name of the algorithm, used for logging |
26 | | /// @param digit_set set of digits (i.e. alphabet) used for encoding |
27 | | /// @param bits_table table to translate digits to data used during decoding |
28 | | /// @param bits_per_digit number of data bits represented by a digit |
29 | | /// @param digits_per_group number of digits contained in a group |
30 | | /// @param pad_char character used for padding out to group size (0 means no |
31 | | /// padding) |
32 | | /// @param max_pad maximum number of pad characters in a group |
33 | | /// @param case_sensitive indicates if the algorithm's digit set is |
34 | | /// case sensitive |
35 | | BaseNEncoder(const std::string& algorithm, |
36 | | const char* digit_set, |
37 | | const std::vector<uint8_t>& bits_table, |
38 | | size_t bits_per_digit, |
39 | | size_t digits_per_group, |
40 | | const char pad_char, |
41 | | size_t max_pad, |
42 | | bool case_sensitive); |
43 | | |
44 | | /// @brief Destructor |
45 | 39 | virtual ~BaseNEncoder() = default; |
46 | | |
47 | | /// @brief Encodes binary data using the encoder's algorithm |
48 | | /// |
49 | | /// @param input binary data to encode |
50 | | /// |
51 | | /// @return resultant encoded data string |
52 | | /// @throw BadValue if an error occurs during encoding |
53 | | std::string encode(const std::vector<uint8_t>& input); |
54 | | |
55 | | /// @brief Decodes an encoded string using the encoder's algorithm |
56 | | /// |
57 | | /// @param encoded_str encoded string to decode |
58 | | /// @param[out] output vector into which the decoded data is stored |
59 | | /// |
60 | | /// @throw BadValue if an error occurs during decoding |
61 | | void decode(const std::string& encoded_str, std::vector<uint8_t>& output); |
62 | | |
63 | | /// @brief Translate a byte of binary data into the appropriate algorithm digit |
64 | | /// |
65 | | /// @param bits binary value to translate |
66 | | /// |
67 | | /// @return char containing the digit corresponding to the binary value |
68 | | /// @throw BadValue if the bits value is out of range |
69 | | char bitsToDigit(uint8_t bits); |
70 | | |
71 | | /// @brief Translate a digit into the appropriate algorithm bit value |
72 | | /// |
73 | | /// Function maps all 256 ASCII chars to their corresponding algorithm-specific |
74 | | /// data value. A data value of 0xee marks a char as whitespace, 0xff marks a |
75 | | /// char is invalid. |
76 | | /// |
77 | | /// @param digit the algorithm digit to translate |
78 | | /// |
79 | | /// @return byte containing the binary value corresponding to the digit |
80 | | uint8_t digitToBits(uint8_t digit); |
81 | | |
82 | | /// @brief Get the algorithm name |
83 | | /// |
84 | | /// @return string containing the algorithm name |
85 | 0 | std::string getAlgorithm() const { |
86 | 0 | return (algorithm_); |
87 | 0 | } |
88 | | |
89 | | /// @brief Get the digit set |
90 | | /// |
91 | | /// @return string containing the set of digits |
92 | 0 | const char* getDigitSet() const { |
93 | 0 | return (digit_set_); |
94 | 0 | } |
95 | | |
96 | | /// @brief Get the digit lookup table |
97 | | /// |
98 | | /// @return vector containing the lookup table |
99 | 0 | const std::vector<uint8_t>& getBitsTable() const { |
100 | 0 | return (bits_table_); |
101 | 0 | } |
102 | | |
103 | | /// @brief Get the number of data bits represented by a digit |
104 | | /// |
105 | | /// @return number of data bits per digit |
106 | 0 | size_t getBitsPerDigit() { |
107 | 0 | return (bits_per_digit_); |
108 | 0 | } |
109 | | |
110 | | /// @brief Get the number of digits contained in a group |
111 | | /// |
112 | | /// @return number of digits per group |
113 | 0 | size_t getDigitsPerGroup() const { |
114 | 0 | return (digits_per_group_); |
115 | 0 | } |
116 | | |
117 | | /// @brief Get the character used for padding out to group size (0 means no padding) |
118 | | /// |
119 | | /// @return Character used as a pad byte |
120 | 0 | uint8_t getPadChar() const { |
121 | 0 | return (pad_char_); |
122 | 0 | } |
123 | | |
124 | | /// @brief Get the maximum number of pad characters in a group |
125 | | /// |
126 | | /// @return Maximum number of pad characters |
127 | 0 | size_t getMaxPad() { |
128 | 0 | return (max_pad_); |
129 | 0 | } |
130 | | |
131 | | /// @brief Get the maximum index value of the digit set |
132 | | /// |
133 | | /// @return Maximum index value of the digit set |
134 | 0 | size_t getMaxBitsToDigit() { |
135 | 0 | return (max_bits_to_digit_); |
136 | 0 | } |
137 | | |
138 | | /// @brief Get the maximum index value of the algorithm bit table |
139 | | /// |
140 | | /// @return Maximum index value of the algorithm bit table |
141 | 0 | size_t getMaxDigitToBits() { |
142 | 0 | return (max_digit_to_bits_); |
143 | 0 | } |
144 | | |
145 | | /// @brief Indicates whether or not the algorithm's digit set |
146 | | /// is case-sensitive. |
147 | | /// |
148 | | /// @return true if the digit set is case-sensitive, false otherwise |
149 | 0 | bool isCaseSensitive() { |
150 | 0 | return (case_sensitive_); |
151 | 0 | } |
152 | | |
153 | | protected: |
154 | | /// @brief Name of the algorithm, used for logging |
155 | | std::string algorithm_; |
156 | | |
157 | | /// @brief Set of digits (i.e. alphabet) used for encoding |
158 | | const char* digit_set_; |
159 | | |
160 | | /// @brief Table to translate digits to data used during decoding |
161 | | /// |
162 | | /// The table must map all 256 ASCII chars to their corresponding |
163 | | /// algorithm-specific data value. A data value of 0xee marks |
164 | | /// a char as whitespace, 0xff marks a char is invalid |
165 | | std::vector<uint8_t>bits_table_; |
166 | | |
167 | | /// @brief Number of data bits represented by a digit |
168 | | size_t bits_per_digit_; |
169 | | |
170 | | /// @brief Number of digits contained in a group |
171 | | size_t digits_per_group_; |
172 | | |
173 | | /// @brief Character used for padding out to group size (0 means no padding) |
174 | | const char pad_char_; |
175 | | |
176 | | /// @brief Maximum number of pad characters in a group |
177 | | size_t max_pad_; |
178 | | |
179 | | /// @brief Indicates whether or not the algorithm's digit set is case-sensitive |
180 | | bool case_sensitive_; |
181 | | |
182 | | /// @brief Maximum index value of the digit set |
183 | | size_t max_bits_to_digit_; |
184 | | |
185 | | /// @brief Maximum index value of the algorithm bit table |
186 | | size_t max_digit_to_bits_; |
187 | | }; |
188 | | |
189 | | /// @brief Class for encoding and decoding binary data using Base64 |
190 | | /// as described in RFC 4648. |
191 | | class Base64Encoder : public BaseNEncoder { |
192 | | public: |
193 | | /// @brief Set of digits used for encoding in Base64 |
194 | | static const char* DIGIT_SET; |
195 | | |
196 | | /// @brief Table that maps Base64 digits to their binary data value |
197 | | static const std::vector<uint8_t> BITS_TABLE; |
198 | | |
199 | | /// @brief Constructor |
200 | | Base64Encoder() |
201 | 5 | : BaseNEncoder("base64", DIGIT_SET, BITS_TABLE, 6, 4, '=', 2, true) { |
202 | 5 | } |
203 | | |
204 | | /// @brief Destructor |
205 | | ~Base64Encoder() = default; |
206 | | }; |
207 | | |
208 | | /// @brief Class for encoding and decoding binary data using Base32Hex |
209 | | /// as described in RFC 4648. |
210 | | class Base32HexEncoder : public BaseNEncoder { |
211 | | public: |
212 | | /// @brief Set of digits used for encoding in Base32Hex |
213 | | static const char* DIGIT_SET; |
214 | | |
215 | | /// @brief Table that maps Base32Hex digits to their binary data value |
216 | | static const std::vector<uint8_t> BITS_TABLE; |
217 | | |
218 | | /// @brief Constructor |
219 | | Base32HexEncoder() |
220 | 2 | : BaseNEncoder("base32Hex", DIGIT_SET, BITS_TABLE, 5, 8, '=', 6, false) { |
221 | 2 | } |
222 | | |
223 | | /// @brief Destructor |
224 | | ~Base32HexEncoder() = default; |
225 | | }; |
226 | | |
227 | | /// @brief Class for encoding and decoding binary data using Base16 (aka Hex) |
228 | | /// as described in RFC 4648. |
229 | | class Base16Encoder : public BaseNEncoder { |
230 | | public: |
231 | | /// @brief Set of digits used for encoding in Base16 |
232 | | static const char* DIGIT_SET; |
233 | | |
234 | | /// @brief Table that maps Base16 digits to their binary data value |
235 | | static const std::vector<uint8_t> BITS_TABLE; |
236 | | |
237 | | /// @brief Constructor |
238 | | Base16Encoder() |
239 | 32 | : BaseNEncoder("base16", DIGIT_SET, BITS_TABLE, 4, 2, '=', 0, false) { |
240 | 32 | } |
241 | | |
242 | | /// @brief Destructor |
243 | | ~Base16Encoder() = default; |
244 | | }; |
245 | | |
246 | | /// @brief Encode binary data in the base32-hex format. |
247 | | /// |
248 | | /// @param binary vector object storing the data to be encoded. |
249 | | /// @return string containing the base32-hex encoded value. |
250 | | std::string encodeBase32Hex(const std::vector<uint8_t>& binary); |
251 | | |
252 | | /// @brief Decode a base32-hex encoded string into binary data. |
253 | | /// |
254 | | /// @param encoded_str string containing a base32-hex encoded value. |
255 | | /// @param[out] output vector into which the decoded binary data is stored. |
256 | | /// |
257 | | /// @throw BadValue if the input string is invalid. |
258 | | void decodeBase32Hex(const std::string& encoded_str, std::vector<uint8_t>& output); |
259 | | |
260 | | /// @brief Encode binary data in the base64 format. |
261 | | /// |
262 | | /// @param binary vector object storing the data to be encoded. |
263 | | /// @return string containing the base64 encoded value. |
264 | | std::string encodeBase64(const std::vector<uint8_t>& binary); |
265 | | |
266 | | /// @brief Decode a base64 encoded string into binary data. |
267 | | /// |
268 | | /// @param encoded_str string containing a base64 encoded value. |
269 | | /// @param[out] output vector into which the decoded binary data is stored. |
270 | | /// |
271 | | /// @throw BadValue if the input string is invalid. |
272 | | void decodeBase64(const std::string& encoded_str, std::vector<uint8_t>& output); |
273 | | |
274 | | /// @brief Encode binary data in the base16 format. |
275 | | /// |
276 | | /// @param binary vector object containing the data to be encoded. |
277 | | /// @return string containing the base16 encoded value. |
278 | | std::string encodeHex(const std::vector<uint8_t>& binary); |
279 | | |
280 | | /// @brief Decode a base16 encoded string into binary data. |
281 | | /// |
282 | | /// @param encoded_str string containing a base16 encoded value. |
283 | | /// @param[out] output vector into which the decoded binary data is stored. |
284 | | /// |
285 | | /// @throw BadValue if the input string is invalid. |
286 | | void decodeHex(const std::string& encoded_str, std::vector<uint8_t>& output); |
287 | | |
288 | | /// @brief Encode in hexadecimal inline. |
289 | | /// |
290 | | /// @param value the value to encode. |
291 | | /// |
292 | | /// @return 0x followed by the value encoded in hex. |
293 | 0 | inline std::string toHex(std::string value) { |
294 | 0 | std::vector<uint8_t> bin(value.begin(), value.end()); |
295 | 0 | return ("0x" + encodeHex(bin)); |
296 | 0 | } |
297 | | |
298 | | } // namespace encode |
299 | | } // namespace util |
300 | | } // namespace isc |
301 | | |
302 | | #endif // ENCODE_H |