Coverage Report

Created: 2026-08-14 08:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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