C++ Utilities
5.36.0
Useful C++ classes and routines such as argument parser, IO and conversion utilities
Toggle main menu visibility
Loading...
Searching...
No Matches
misc
verification.h
Go to the documentation of this file.
1
#ifndef CPP_UTILITIES_MISC_VERIFICATION_H
2
#define CPP_UTILITIES_MISC_VERIFICATION_H
3
4
#include "
../conversion/stringconversion.h
"
5
6
#include <openssl/ec.h>
7
#include <openssl/err.h>
8
#include <openssl/evp.h>
9
#include <openssl/pem.h>
10
11
#include <algorithm>
12
#include <array>
13
#include <cctype>
14
#include <string>
15
#include <string_view>
16
17
namespace
CppUtilities
{
18
19
namespace
Detail
{
22
inline
std::string
getOpenSslError
()
23
{
24
const
auto
errCode = ERR_get_error();
25
if
(errCode == 0) {
26
return
"unknown OpenSSL error"
;
27
}
28
auto
buffer = std::array<char, 256>();
29
ERR_error_string_n(errCode, buffer.data(), buffer.size());
30
return
std::string(buffer.data());
31
}
32
35
inline
std::string
extractPemBody
(std::string_view pem, std::string_view header)
36
{
37
auto
body = std::string();
38
auto
begin = pem.find(header);
39
if
(begin == std::string_view::npos) {
40
return
body;
41
}
42
begin += header.size();
43
44
auto
end = pem.find(
"-----END"
, begin);
45
if
(end == std::string_view::npos) {
46
return
body;
47
}
48
49
body = std::string(pem.data() + begin, end - begin);
50
body.erase(std::remove_if(body.begin(), body.end(), ::isspace), body.end());
51
return
body;
52
}
53
56
inline
std::string
parsePemSignature
(std::string_view pemSignature, std::pair<std::unique_ptr<std::uint8_t[]>, std::uint32_t> &decodedSignature)
57
{
58
const
auto
pemSignatureBody =
extractPemBody
(pemSignature,
"-----BEGIN SIGNATURE-----"
);
59
if
(pemSignatureBody.empty()) {
60
return
"invalid or missing PEM signature block"
;
61
}
62
try
{
63
decodedSignature =
decodeBase64
(pemSignatureBody.data(),
static_cast<
std::uint32_t
>
(pemSignatureBody.size()));
64
return
std::string();
65
}
catch
(
const
ConversionException
&e) {
66
return
"unable to decode PEM signature block"
;
67
}
68
}
69
70
}
// namespace Detail
71
73
using
MainVerifyFunctionType
= std::string (*)(std::string_view, std::string_view, std::string_view);
74
107
inline
std::string
verifySignature
(std::string_view publicKeyPem, std::string_view signaturePem, std::string_view data)
108
{
109
auto
error = std::string();
110
auto
derSignature = std::pair<std::unique_ptr<std::uint8_t[]>, std::uint32_t>();
111
if
(error =
Detail::parsePemSignature
(signaturePem, derSignature); !error.empty()) {
112
return
error;
113
}
114
115
BIO *
const
keyBio = BIO_new_mem_buf(publicKeyPem.data(),
static_cast<
int
>
(publicKeyPem.size()));
116
if
(!keyBio) {
117
return
error =
"BIO_new_mem_buf failed: "
+
Detail::getOpenSslError
();
118
}
119
120
EVP_PKEY *
const
publicKey = PEM_read_bio_PUBKEY(keyBio,
nullptr
,
nullptr
,
nullptr
);
121
BIO_free(keyBio);
122
if
(!publicKey) {
123
return
error =
"PEM_read_bio_PUBKEY failed: "
+
Detail::getOpenSslError
();
124
}
125
126
EVP_MD_CTX *
const
mdCtx = EVP_MD_CTX_new();
127
if
(!mdCtx) {
128
EVP_PKEY_free(publicKey);
129
return
error =
"EVP_MD_CTX_new failed: "
+
Detail::getOpenSslError
();
130
}
131
132
if
(EVP_DigestVerifyInit(mdCtx,
nullptr
, EVP_sha256(),
nullptr
, publicKey) != 1) {
133
error =
"EVP_DigestVerifyInit failed: "
+
Detail::getOpenSslError
();
134
}
else
if
(EVP_DigestVerifyUpdate(mdCtx, data.data(), data.size()) != 1) {
135
error =
"EVP_DigestVerifyUpdate failed: "
+
Detail::getOpenSslError
();
136
}
else
{
137
switch
(EVP_DigestVerifyFinal(mdCtx, derSignature.first.get(), derSignature.second)) {
138
case
0:
139
error =
"incorrect signature"
;
140
break
;
141
case
1:
142
break
;
// signature is correct
143
default
:
144
error =
"EVP_DigestVerifyFinal failed: "
+
Detail::getOpenSslError
();
145
break
;
146
}
147
}
148
149
EVP_MD_CTX_free(mdCtx);
150
EVP_PKEY_free(publicKey);
151
return
error;
152
}
153
162
template
<
class
Keys,
class
VerifyFunction = MainVerifyFunctionType>
163
inline
std::string
verifySignature
(Keys &&publicKeysPem, std::string_view signaturePem, std::string_view data,
164
VerifyFunction &&verifyFunction =
static_cast<
MainVerifyFunctionType
>
(&
verifySignature
))
165
{
166
auto
error = std::string(
"no keys provided"
);
167
for
(
const
auto
publicKeyPem : publicKeysPem) {
168
if
((error = verifyFunction(publicKeyPem, signaturePem, data)).empty()) {
169
return
error;
170
}
171
}
172
return
error;
173
}
174
175
}
// namespace CppUtilities
176
177
#endif
// CPP_UTILITIES_MISC_VERIFICATION_H
CppUtilities::ConversionException
The ConversionException class is thrown by the various conversion functions of this library when a co...
Definition
conversionexception.h:11
CppUtilities::Detail
Definition
verification.h:19
CppUtilities::Detail::extractPemBody
std::string extractPemBody(std::string_view pem, std::string_view header)
Extracts the base64-encoded body from a PEM block.
Definition
verification.h:35
CppUtilities::Detail::parsePemSignature
std::string parsePemSignature(std::string_view pemSignature, std::pair< std::unique_ptr< std::uint8_t[]>, std::uint32_t > &decodedSignature)
Converts a PEM-encoded signature into a DER-encoded signature.
Definition
verification.h:56
CppUtilities::Detail::getOpenSslError
std::string getOpenSslError()
Returns the current OpenSSL error.
Definition
verification.h:22
CppUtilities
Contains all utilities provided by the c++utilities library.
Definition
argumentparser.h:18
CppUtilities::MainVerifyFunctionType
std::string(*)(std::string_view, std::string_view, std::string_view) MainVerifyFunctionType
The signature of the main verifySignature() function.
Definition
verification.h:73
CppUtilities::verifySignature
std::string verifySignature(std::string_view publicKeyPem, std::string_view signaturePem, std::string_view data)
Verifies data with the specified public key publicKeyPem and signature signaturePem.
Definition
verification.h:107
CppUtilities::decodeBase64
CPP_UTILITIES_EXPORT std::pair< std::unique_ptr< std::uint8_t[]>, std::uint32_t > decodeBase64(const char *encodedStr, const std::uint32_t strSize)
Decodes the specified Base64 encoded string.
Definition
stringconversion.cpp:427
stringconversion.h
Generated on
for C++ Utilities by
1.18.0