Skip to content

Commit f3a2fa1

Browse files
committed
Add function to verify with while array of public keys
1 parent 830a7b9 commit f3a2fa1

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

misc/signingkeys.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,14 @@ namespace CppUtilities {
99
/*!
1010
* \brief Contains signing keys for verifying releases via OpenSSL or stsigtool.
1111
* \remarks
12-
* - Checkout the header file `verification.h` for verification with OpenSSL.
12+
* - Checkout the header file `verification.h` which contains the function verifySignature() for
13+
* verification with OpenSSL.
1314
* - Checkout the Syncthing library contained in Syncthing Tray for verification with stsigtool.
15+
* - The arrays may contain more than one key, e.g. when rotatiung keys and an old key is in progress
16+
* of being phased out.
17+
* - The concrete type of the contained key variables will change when the number of keys changes.
18+
* So do *not* use it in e.g. a function signature or member variable that will become part of
19+
* some public API/ABI. The variable is mereley supposed to be passed to verifySignature().
1420
* - This function is experimental and might be changed in incompatible ways (API and ABI wise) or be completely removed
1521
* in further minor/patch releases.
1622
*/

misc/verification.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ inline std::string parsePemSignature(std::string_view pemSignature, std::pair<st
6969

7070
} // namespace Detail
7171

72+
/// \brief The signature of the main verifySignature() function.
73+
using MainVerifyFunctionType = std::string (*)(std::string_view, std::string_view, std::string_view);
74+
7275
/*!
7376
* \brief Verifies \a data with the specified public key \a publicKeyPem and signature \a signaturePem.
7477
* \returns Returns an empty string if \a data and \a signature are correct and an error message otherwise.
@@ -104,7 +107,6 @@ inline std::string parsePemSignature(std::string_view pemSignature, std::pair<st
104107
inline std::string verifySignature(std::string_view publicKeyPem, std::string_view signaturePem, std::string_view data)
105108
{
106109
auto error = std::string();
107-
108110
auto derSignature = std::pair<std::unique_ptr<std::uint8_t[]>, std::uint32_t>();
109111
if (error = Detail::parsePemSignature(signaturePem, derSignature); !error.empty()) {
110112
return error;
@@ -149,6 +151,27 @@ inline std::string verifySignature(std::string_view publicKeyPem, std::string_vi
149151
return error;
150152
}
151153

154+
/*!
155+
* \brief Verifies \a data with the specified public keys \a publicKeysPem and signature \a signaturePem.
156+
* \returns Returns an empty string if \a data and \a signature are correct and an error message otherwise.
157+
* \remarks
158+
* - This is a version of verifySignature() that takes more than one public key trying out different keys.
159+
* This allows rotating keys once in a while without breaking verification by temporarily allowing the
160+
* old and new key at the same time.
161+
*/
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+
152175
} // namespace CppUtilities
153176

154177
#endif // CPP_UTILITIES_MISC_VERIFICATION_H

tests/misctests.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "../misc/multiarray.h"
44

55
#ifdef CPP_UTILITIES_HAS_OPENSSL_CRYPTO
6+
#include "../misc/signingkeys.h"
67
#include "../misc/verification.h"
78
#endif
89

@@ -205,6 +206,12 @@ sWB0iGdPa+oXbRish7HoNCU/k0lD3ffXaf8ueC78Zme9NFO18Ol+NWXJDA==
205206

206207
message[5] = '?';
207208
CPPUNIT_ASSERT_EQUAL_MESSAGE("manipulate message", "incorrect signature"s, verifySignature(key, signature, message));
209+
CPPUNIT_ASSERT_EQUAL_MESSAGE("manipulate message", "incorrect signature"s, verifySignature(key, signature, message));
210+
211+
CPPUNIT_ASSERT_EQUAL_MESSAGE(
212+
"verifySignature can be called with array of signatures", "incorrect signature"s, verifySignature(SigningKeys::openssl, signature, message));
213+
CPPUNIT_ASSERT_EQUAL_MESSAGE(
214+
"verifySignature can be called with empty vector", "no keys provided"s, verifySignature(std::vector<std::string_view>(), signature, message));
208215
}
209216
#endif
210217

0 commit comments

Comments
 (0)