SourcePP
Several modern C++20 libraries for sanely parsing Valve's formats.
Loading...
Searching...
No Matches
RSA.cpp
Go to the documentation of this file.
2
3#include <array>
4#include <memory>
5#include <random>
6
7#include <tomcrypt.h>
8
10#include <sourcepp/String.h>
11
12using namespace sourcepp;
13
14namespace {
15
16constexpr auto SHA256_ENTROPY_SIZE = 64;
17
18} // namespace
19
20std::pair<std::string, std::string> crypto::computeSHA256KeyPair(uint16_t size) {
21 if (!LTM_MATH || SHA256_INDEX < 0 || YARROW_INDEX < 0 || size < 8) {
22 return {};
23 }
24 size /= 8;
25
26 const std::unique_ptr<prng_state, void(*)(prng_state*)> prng{new prng_state, [](prng_state* p) { yarrow_done(p); delete p; }};
27 yarrow_start(prng.get());
28 {
29 std::array<unsigned char, SHA256_ENTROPY_SIZE> entropy{};
30 std::random_device rd;
31 std::uniform_int_distribution<> dist{0, std::numeric_limits<unsigned char>::max()};
32 for (auto& i : entropy) {
33 i = static_cast<unsigned char>(dist(rd));
34 }
35 yarrow_add_entropy(entropy.data(), entropy.size(), prng.get());
36 }
37 yarrow_ready(prng.get());
38
39 const std::unique_ptr<rsa_key, void(*)(rsa_key*)> key{new rsa_key, [](rsa_key* k) { rsa_free(k); delete k; }};
40 if (rsa_make_key(prng.get(), YARROW_INDEX, size, 65537, key.get()) != CRYPT_OK) {
41 return {};
42 }
43
44 std::vector<unsigned char> privateKeyData(size * 16);
45 unsigned long privateKeyLen = privateKeyData.size();
46 if (rsa_export(privateKeyData.data(), &privateKeyLen, PK_PRIVATE, key.get()) != CRYPT_OK) {
47 return {};
48 }
49 privateKeyData.resize(privateKeyLen);
50
51 std::vector<unsigned char> publicKeyData(size * 16);
52 unsigned long publicKeyLen = publicKeyData.size();
53 if (rsa_export(publicKeyData.data(), &publicKeyLen, PK_PUBLIC, key.get()) != CRYPT_OK) {
54 return {};
55 }
56 publicKeyData.resize(publicKeyLen);
57
58 return {
59 string::encodeHex({reinterpret_cast<const std::byte*>(privateKeyData.data()), privateKeyData.size()}),
60 string::encodeHex({reinterpret_cast<const std::byte*>(publicKeyData.data()), publicKeyData.size()}),
61 };
62}
63
64bool crypto::verifySHA256PublicKey(std::span<const std::byte> buffer, std::span<const std::byte> publicKey, std::span<const std::byte> signature) {
65 if (!LTM_MATH || SHA256_INDEX < 0 || buffer.empty()) {
66 return false;
67 }
68
69 const std::unique_ptr<rsa_key, void(*)(rsa_key*)> key{new rsa_key, [](rsa_key* k) { rsa_free(k); delete k; }};
70 if (rsa_import(reinterpret_cast<const unsigned char*>(publicKey.data()), publicKey.size(), key.get()) != CRYPT_OK) {
71 return false;
72 }
73
74 const auto sha256 = computeSHA256(buffer);
75 ltc_rsa_op_parameters params{ .params = { .hash_idx = SHA256_INDEX }, .padding = LTC_PKCS_1_V1_5 };
76 int stat = 0;
77 return rsa_verify_hash_v2(reinterpret_cast<const unsigned char*>(signature.data()), signature.size(), reinterpret_cast<const unsigned char*>(sha256.data()), sha256.size(), &params, &stat, key.get()) == CRYPT_OK && stat;
78}
79
80std::vector<std::byte> crypto::signDataWithSHA256PrivateKey(std::span<const std::byte> buffer, std::span<const std::byte> privateKey) {
81 if (!LTM_MATH || SHA256_INDEX < 0 || buffer.empty()) {
82 return {};
83 }
84
85 const std::unique_ptr<rsa_key, void(*)(rsa_key*)> key{new rsa_key, [](rsa_key* k) { rsa_free(k); delete k; }};
86 if (rsa_import(reinterpret_cast<const unsigned char*>(privateKey.data()), privateKey.size(), key.get()) != CRYPT_OK) {
87 return {};
88 }
89
90 const auto sha256 = computeSHA256(buffer);
91 unsigned long signatureLen = rsa_get_size(key.get());
92 std::vector<std::byte> signature(signatureLen);
93 ltc_rsa_op_parameters params{ .params = { .hash_idx = SHA256_INDEX }, .padding = LTC_PKCS_1_V1_5 };
94 return rsa_sign_hash_v2(reinterpret_cast<const unsigned char*>(sha256.data()), sha256.size(), reinterpret_cast<unsigned char*>(signature.data()), &signatureLen, &params, key.get()) == CRYPT_OK ? signature : std::vector<std::byte>{};
95}
std::vector< std::byte > signDataWithSHA256PrivateKey(std::span< const std::byte > buffer, std::span< const std::byte > privateKey)
Definition RSA.cpp:80
const int YARROW_INDEX
Definition Globals.cpp:14
bool verifySHA256PublicKey(std::span< const std::byte > buffer, std::span< const std::byte > publicKey, std::span< const std::byte > signature)
Definition RSA.cpp:64
const bool LTM_MATH
Definition Globals.cpp:7
const int SHA256_INDEX
Definition Globals.cpp:13
std::array< std::byte, 32 > computeSHA256(std::span< const std::byte > buffer)
Definition SHA256.cpp:9
std::pair< std::string, std::string > computeSHA256KeyPair(uint16_t size=2048)
Definition RSA.cpp:20
std::string encodeHex(std::span< const std::byte > hex)
Definition String.cpp:281