Kurlyk
Loading...
Searching...
No Matches
Base64Url.hpp
Go to the documentation of this file.
1#pragma once
2#ifndef _KURLYK_UTILS_BASE64URL_HPP_INCLUDED
3#define _KURLYK_UTILS_BASE64URL_HPP_INCLUDED
4
7
8#include <string>
9#include <vector>
10#include <cstdint>
11
12namespace kurlyk {
13namespace utils {
14
19 inline std::string base64url_encode(const uint8_t* data, std::size_t length) {
20 static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
21 std::string result;
22 result.reserve(((length + 2) / 3) * 4);
23
24 std::size_t i = 0;
25 while (i + 2 < length) {
26 uint32_t b = (static_cast<uint32_t>(data[i]) << 16)
27 | (static_cast<uint32_t>(data[i + 1]) << 8)
28 | static_cast<uint32_t>(data[i + 2]);
29 result.push_back(table[(b >> 18) & 0x3F]);
30 result.push_back(table[(b >> 12) & 0x3F]);
31 result.push_back(table[(b >> 6) & 0x3F]);
32 result.push_back(table[b & 0x3F]);
33 i += 3;
34 }
35
36 if (i + 1 == length) {
37 uint32_t b = static_cast<uint32_t>(data[i]) << 16;
38 result.push_back(table[(b >> 18) & 0x3F]);
39 result.push_back(table[(b >> 12) & 0x3F]);
40 } else if (i + 2 == length) {
41 uint32_t b = (static_cast<uint32_t>(data[i]) << 16)
42 | (static_cast<uint32_t>(data[i + 1]) << 8);
43 result.push_back(table[(b >> 18) & 0x3F]);
44 result.push_back(table[(b >> 12) & 0x3F]);
45 result.push_back(table[(b >> 6) & 0x3F]);
46 }
47
48 return result;
49 }
50
54 inline std::string base64url_encode(const std::string& value) {
55 return base64url_encode(reinterpret_cast<const uint8_t*>(value.data()), value.size());
56 }
57
61 inline std::vector<uint8_t> base64url_decode(const std::string& value) {
62 static const int8_t decode_table[] = {
63 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
64 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
65 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1,
66 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
67 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
68 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63,
69 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
70 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
71 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
72 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
73 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
74 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
75 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
76 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
77 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
78 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
79 };
80
81 std::string padded = value;
82 while (padded.size() % 4 != 0) {
83 padded.push_back('=');
84 }
85
86 std::vector<uint8_t> result;
87 result.reserve((padded.size() / 4) * 3);
88
89 std::size_t i = 0;
90 while (i < padded.size()) {
91 int8_t c0 = (padded[i] < 128) ? decode_table[static_cast<uint8_t>(padded[i])] : int8_t(-1);
92 int8_t c1 = (padded[i + 1] < 128) ? decode_table[static_cast<uint8_t>(padded[i + 1])] : int8_t(-1);
93 int8_t c2 = (padded[i + 2] < 128) ? decode_table[static_cast<uint8_t>(padded[i + 2])] : int8_t(-1);
94 int8_t c3 = (padded[i + 3] < 128) ? decode_table[static_cast<uint8_t>(padded[i + 3])] : int8_t(-1);
95
96 if (c0 < 0 || c1 < 0) break;
97 if (c2 < 0 && padded[i + 2] != '=') break;
98 if (c3 < 0 && padded[i + 3] != '=') break;
99
100 uint32_t b = (static_cast<uint32_t>(c0) << 18)
101 | (static_cast<uint32_t>(c1) << 12)
102 | ((c2 >= 0 ? static_cast<uint32_t>(c2) : 0u) << 6)
103 | (c3 >= 0 ? static_cast<uint32_t>(c3) : 0u);
104
105 result.push_back(static_cast<uint8_t>((b >> 16) & 0xFF));
106 if (padded[i + 2] != '=') {
107 result.push_back(static_cast<uint8_t>((b >> 8) & 0xFF));
108 }
109 if (padded[i + 3] != '=') {
110 result.push_back(static_cast<uint8_t>(b & 0xFF));
111 }
112 i += 4;
113 }
114
115 return result;
116 }
117
118} // namespace utils
119} // namespace kurlyk
120
121#endif // _KURLYK_UTILS_BASE64URL_HPP_INCLUDED
std::vector< uint8_t > base64url_decode(const std::string &value)
Decodes a Base64url string (RFC 4648, no padding) into bytes.
Definition Base64Url.hpp:61
std::string base64url_encode(const uint8_t *data, std::size_t length)
Encodes a byte buffer using Base64url (RFC 4648) without padding.
Definition Base64Url.hpp:19
Primary namespace for the Kurlyk library, encompassing initialization, request management,...