Kurlyk
Toggle main menu visibility
Loading...
Searching...
No Matches
pkce.hpp
Go to the documentation of this file.
1
#pragma once
2
#ifndef KURLYK_HEADER_KURLYK_UTILS_PKCE_HPP_INCLUDED
3
#define KURLYK_HEADER_KURLYK_UTILS_PKCE_HPP_INCLUDED
4
7
8
#include "
base64_url.hpp
"
9
#include <openssl/evp.h>
10
#include <openssl/rand.h>
11
#include <limits>
12
#include <stdexcept>
13
#include <string>
14
#include <vector>
15
#include <cstdint>
16
17
namespace
kurlyk
{
18
namespace
utils {
19
20
namespace
detail
{
21
25
inline
void
random_bytes
(uint8_t* data, std::size_t size) {
26
if
(size >
static_cast<
std::size_t
>
((std::numeric_limits<int>::max)()) ||
27
RAND_bytes(
28
reinterpret_cast<
unsigned
char
*
>
(data),
29
static_cast<
int
>
(size)) != 1) {
30
throw
std::runtime_error(
"OpenSSL RAND_bytes failed"
);
31
}
32
}
33
38
inline
std::vector<uint8_t>
sha256
(
const
void
* data, std::size_t size) {
39
std::vector<uint8_t> digest(EVP_MAX_MD_SIZE);
40
unsigned
int
digest_size = 0;
41
42
if
(EVP_Digest(
43
data,
44
size,
45
reinterpret_cast<
unsigned
char
*
>
(digest.data()),
46
&digest_size,
47
EVP_sha256(),
48
nullptr
) != 1) {
49
throw
std::runtime_error(
"OpenSSL SHA-256 digest failed"
);
50
}
51
52
digest.resize(digest_size);
53
return
digest;
54
}
55
56
}
// namespace detail
57
60
struct
PkcePair
{
61
std::string
code_verifier
;
62
std::string
code_challenge
;
63
std::string
code_challenge_method
=
"S256"
;
64
};
65
69
inline
std::string
generate_code_verifier
(std::size_t length = 64) {
70
static
const
char
allowed[] =
71
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~"
;
72
if
(length < 43) length = 43;
73
if
(length > 128) length = 128;
74
75
std::string verifier;
76
verifier.reserve(length);
77
78
const
std::size_t allowed_count =
sizeof
(allowed) - 1;
// exclude null terminator
79
const
std::size_t accepted_limit = 256 - (256 % allowed_count);
80
81
while
(verifier.size() < length) {
82
const
std::size_t remaining = length - verifier.size();
83
std::vector<uint8_t> random_data(remaining);
84
detail::random_bytes
(random_data.data(), random_data.size());
85
86
for
(std::size_t i = 0; i < random_data.size() && verifier.size() < length; ++i) {
87
if
(random_data[i] >= accepted_limit) {
88
continue
;
89
}
90
verifier.push_back(allowed[random_data[i] % allowed_count]);
91
}
92
}
93
return
verifier;
94
}
95
99
inline
std::string
make_s256_code_challenge
(
const
std::string& verifier) {
100
std::vector<uint8_t> digest =
detail::sha256
(verifier.data(), verifier.size());
101
return
base64url_encode
(digest.data(), digest.size());
102
}
103
106
inline
PkcePair
make_pkce_pair
() {
107
PkcePair
pair;
108
pair.
code_verifier
=
generate_code_verifier
();
109
pair.
code_challenge
=
make_s256_code_challenge
(pair.
code_verifier
);
110
return
pair;
111
}
112
113
}
// namespace utils
114
}
// namespace kurlyk
115
116
#endif
// KURLYK_HEADER_KURLYK_UTILS_PKCE_HPP_INCLUDED
base64_url.hpp
Provides Base64url encoding and decoding (RFC 4648, no padding).
kurlyk::utils::detail
Definition
pkce.hpp:20
kurlyk::utils::detail::random_bytes
void random_bytes(uint8_t *data, std::size_t size)
Fills a byte buffer with cryptographically secure random data.
Definition
pkce.hpp:25
kurlyk::utils::detail::sha256
std::vector< uint8_t > sha256(const void *data, std::size_t size)
Calculates a SHA-256 digest.
Definition
pkce.hpp:38
kurlyk::utils::base64url_encode
std::string base64url_encode(const uint8_t *data, std::size_t length)
Encodes a byte buffer using Base64url (RFC 4648) without padding.
Definition
base64_url.hpp:19
kurlyk::utils::make_s256_code_challenge
std::string make_s256_code_challenge(const std::string &verifier)
Creates an S256 code challenge from a verifier.
Definition
pkce.hpp:99
kurlyk::utils::make_pkce_pair
PkcePair make_pkce_pair()
Creates a PKCE pair with a freshly generated verifier.
Definition
pkce.hpp:106
kurlyk::utils::generate_code_verifier
std::string generate_code_verifier(std::size_t length=64)
Generates a cryptographically strong PKCE code verifier.
Definition
pkce.hpp:69
kurlyk
Primary namespace for the Kurlyk library, encompassing initialization, request management,...
kurlyk::utils::PkcePair
Stores PKCE verifier and challenge values.
Definition
pkce.hpp:60
kurlyk::utils::PkcePair::code_challenge_method
std::string code_challenge_method
Challenge method, always "S256".
Definition
pkce.hpp:63
kurlyk::utils::PkcePair::code_verifier
std::string code_verifier
Randomly generated code verifier.
Definition
pkce.hpp:61
kurlyk::utils::PkcePair::code_challenge
std::string code_challenge
Derived S256 code challenge.
Definition
pkce.hpp:62
include
kurlyk
utils
pkce.hpp
Generated by
1.18.0