1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
|
/*****************************************************************************
* Copyright (c) 2014-2022 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include "TestData.h"
#include "helpers/StringHelpers.hpp"
#include <gtest/gtest.h>
#include <openrct2/core/Crypt.h>
#include <openrct2/core/File.h>
#include <openrct2/core/Path.hpp>
#include <openrct2/network/NetworkKey.h>
#include <string>
class CryptTests : public testing::Test
{
public:
template<typename T> void AssertHash(std::string expected, T hash)
{
auto actual = StringToHex(hash);
ASSERT_EQ(expected, actual);
}
template<typename T> std::string StringToHex(T input)
{
std::string result;
result.reserve(input.size() * 2);
for (auto b : input)
{
static_assert(sizeof(b) == 1);
char buf[3];
snprintf(buf, 3, "%02x", b);
result.append(buf);
}
return result;
}
std::string GetTestPrivateKeyPath()
{
return Path::Combine(TestData::GetBasePath(), u8"keys", u8"Player.privkey");
}
std::string GetTestPublicKeyPath()
{
return Path::Combine(TestData::GetBasePath(), u8"keys", u8"Player-56f4afb74622a23bd2539ee701fe1b2c13d7e6ba.pubkey");
}
};
TEST_F(CryptTests, SHA1_Basic)
{
std::string input = "The quick brown fox jumped over the lazy dog.";
auto result = Crypt::SHA1(input.data(), input.size());
AssertHash("c0854fb9fb03c41cce3802cb0d220529e6eef94e", result);
}
TEST_F(CryptTests, SHA1_Multiple)
{
std::string input[] = {
"Merry-go-round 2 looks too intense for me",
"This park is really clean and tidy",
"This balloon from Balloon Stall 1 is really good value",
};
auto alg = Crypt::CreateSHA1();
for (const auto& s : input)
{
alg->Update(s.data(), s.size());
}
auto result = alg->Finish();
AssertHash("758a238d9a4748f80cc81f12be3885d5e45d34c2", result);
}
TEST_F(CryptTests, SHA1_WithClear)
{
std::string inputA = "Merry-go-round 2 looks too intense for me";
std::string inputB = "This park is really clean and tidy";
auto alg = Crypt::CreateSHA1();
alg->Update(inputA.data(), inputA.size());
alg->Clear();
alg->Update(inputB.data(), inputB.size());
AssertHash("203986d57ebdbcdc8a45b7ee74c665960fd7ff48", alg->Finish());
}
TEST_F(CryptTests, SHA1_Many)
{
auto alg = Crypt::CreateSHA1();
// First digest
std::string inputA[] = {
"Merry-go-round 2 looks too intense for me",
"This park is really clean and tidy",
"This balloon from Balloon Stall 1 is really good value",
};
for (const auto& s : inputA)
{
alg->Update(s.data(), s.size());
}
AssertHash("758a238d9a4748f80cc81f12be3885d5e45d34c2", alg->Finish());
// No need to clear after a finish
// Second digest
std::string inputB[] = {
"This balloon from Balloon Stall 1 is really good value"
"This park is really clean and tidy",
"Merry-go-round 2 looks too intense for me",
};
for (const auto& s : inputB)
{
alg->Update(s.data(), s.size());
}
AssertHash("ac46948f97d69fa766706e932ce82562b4f73aa7", alg->Finish());
}
TEST_F(CryptTests, RSA_Basic)
{
std::vector<uint8_t> data = { 0, 1, 2, 3, 4, 5, 6, 7 };
auto file = File::ReadAllText(GetTestPrivateKeyPath());
auto key = Crypt::CreateRSAKey();
key->SetPrivate(std::string_view(file.data(), file.size()));
auto rsa = Crypt::CreateRSA();
auto signature = rsa->SignData(*key, data.data(), data.size());
bool verified = rsa->VerifyData(*key, data.data(), data.size(), signature.data(), signature.size());
ASSERT_TRUE(verified);
}
TEST_F(CryptTests, RSA_VerifyWithPublic)
{
std::vector<uint8_t> data = { 7, 6, 5, 4, 3, 2, 1, 0 };
auto privateFile = File::ReadAllText(GetTestPrivateKeyPath());
auto privateKey = Crypt::CreateRSAKey();
privateKey->SetPrivate(std::string_view(privateFile.data(), privateFile.size()));
auto publicFile = File::ReadAllText(GetTestPublicKeyPath());
auto publicKey = Crypt::CreateRSAKey();
publicKey->SetPublic(std::string_view(publicFile.data(), publicFile.size()));
auto rsa = Crypt::CreateRSA();
auto signature = rsa->SignData(*privateKey, data.data(), data.size());
bool verified = rsa->VerifyData(*publicKey, data.data(), data.size(), signature.data(), signature.size());
ASSERT_TRUE(verified);
}
TEST_F(CryptTests, RSAKey_GetPublic)
{
auto inPem = NormaliseLineEndings(File::ReadAllText(GetTestPublicKeyPath()));
auto publicKey = Crypt::CreateRSAKey();
publicKey->SetPublic(inPem);
auto outPem = publicKey->GetPublic();
ASSERT_EQ(inPem, outPem);
}
TEST_F(CryptTests, RSAKey_Generate)
{
auto key = Crypt::CreateRSAKey();
// Test generate twice, first checking if the PEMs contain expected strings
key->Generate();
auto privatePem1 = key->GetPrivate();
auto publicPem1 = key->GetPublic();
ASSERT_NE(privatePem1.find("RSA PRIVATE KEY"), std::string::npos);
ASSERT_NE(publicPem1.find("RSA PUBLIC KEY"), std::string::npos);
key->Generate();
auto privatePem2 = key->GetPrivate();
auto publicPem2 = key->GetPublic();
ASSERT_NE(privatePem2.find("RSA PRIVATE KEY"), std::string::npos);
ASSERT_NE(publicPem2.find("RSA PUBLIC KEY"), std::string::npos);
// Now check that generate gives a different key each time
ASSERT_STRNE(privatePem1.c_str(), privatePem2.c_str());
ASSERT_STRNE(publicPem1.c_str(), publicPem2.c_str());
}
|