aboutsummaryrefslogtreecommitdiff
path: root/src/common/Cryptography/RSA.cpp
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2017-12-25 21:41:34 +0100
committerShauren <shauren.trinity@gmail.com>2017-12-25 21:41:34 +0100
commit61ca3d62354275b125abf9264e63f61729104a64 (patch)
tree4dd4e72773ab3961cb42c37d88bf828849eeeca3 /src/common/Cryptography/RSA.cpp
parentb12878cb5af4ef3feb134dac6ff11fcb66622e8d (diff)
Core/Crypto: Refactor RSA encryption to use openssl functions instead of doing it manually
Diffstat (limited to 'src/common/Cryptography/RSA.cpp')
-rw-r--r--src/common/Cryptography/RSA.cpp106
1 files changed, 106 insertions, 0 deletions
diff --git a/src/common/Cryptography/RSA.cpp b/src/common/Cryptography/RSA.cpp
new file mode 100644
index 00000000000..969d00dae0f
--- /dev/null
+++ b/src/common/Cryptography/RSA.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "RSA.h"
+#include <openssl/pem.h>
+
+#define CHECK_AND_DECLARE_FUNCTION_TYPE(name, publicKey, privateKey) \
+ static_assert(std::is_same<decltype(&publicKey), decltype(&privateKey)>::value, \
+ "Public key and private key functions must have the same signature"); \
+ using name ## _t = decltype(&publicKey); \
+ template <typename KeyTag> inline name ## _t get_ ## name () { return nullptr; } \
+ template <> inline name ## _t get_ ## name<Trinity::Crypto::RSA::PublicKey>() { return &publicKey; } \
+ template <> inline name ## _t get_ ## name<Trinity::Crypto::RSA::PrivateKey>() { return &privateKey; }
+
+namespace
+{
+struct BIODeleter
+{
+ void operator()(BIO* bio)
+ {
+ BIO_free(bio);
+ }
+};
+
+CHECK_AND_DECLARE_FUNCTION_TYPE(RSA_dup, RSAPublicKey_dup, RSAPrivateKey_dup);
+CHECK_AND_DECLARE_FUNCTION_TYPE(PEM_read, PEM_read_bio_RSAPublicKey, PEM_read_bio_RSAPrivateKey);
+CHECK_AND_DECLARE_FUNCTION_TYPE(RSA_encrypt, RSA_public_encrypt, RSA_private_encrypt);
+}
+
+Trinity::Crypto::RSA::RSA()
+{
+ _rsa = RSA_new();
+}
+
+Trinity::Crypto::RSA::RSA(RSA&& rsa)
+{
+ _rsa = rsa._rsa;
+ rsa._rsa = RSA_new();
+}
+
+Trinity::Crypto::RSA::~RSA()
+{
+ RSA_free(_rsa);
+}
+
+template <typename KeyTag>
+bool Trinity::Crypto::RSA::LoadFromFile(std::string const& fileName, KeyTag)
+{
+ std::unique_ptr<BIO, BIODeleter> keyBIO(BIO_new_file(fileName.c_str(), "r"));
+ if (!keyBIO)
+ return false;
+
+ if (!get_PEM_read<KeyTag>()(keyBIO.get(), &_rsa, nullptr, nullptr))
+ return false;
+
+ return true;
+}
+
+template <typename KeyTag>
+bool Trinity::Crypto::RSA::LoadFromString(std::string const& keyPem, KeyTag)
+{
+ std::unique_ptr<BIO, BIODeleter> keyBIO(BIO_new_mem_buf(keyPem.c_str(), keyPem.length() + 1));
+ if (!keyBIO)
+ return false;
+
+ if (!get_PEM_read<KeyTag>()(keyBIO.get(), &_rsa, nullptr, nullptr))
+ return false;
+
+ return true;
+}
+
+template <typename KeyTag>
+bool Trinity::Crypto::RSA::Encrypt(uint8 const* data, std::size_t dataLength, uint8* output, int32 paddingType)
+{
+ std::vector<uint8> inputData(std::make_reverse_iterator(data + dataLength), std::make_reverse_iterator(data));
+ int result = get_RSA_encrypt<KeyTag>()(inputData.size(), inputData.data(), output, _rsa, paddingType);
+ std::reverse(output, output + GetOutputSize());
+ return result != -1;
+}
+
+namespace Trinity
+{
+namespace Crypto
+{
+ template TC_COMMON_API bool RSA::LoadFromFile(std::string const& fileName, RSA::PublicKey);
+ template TC_COMMON_API bool RSA::LoadFromFile(std::string const& fileName, RSA::PrivateKey);
+ template TC_COMMON_API bool RSA::LoadFromString(std::string const& keyPem, RSA::PublicKey);
+ template TC_COMMON_API bool RSA::LoadFromString(std::string const& keyPem, RSA::PrivateKey);
+ template TC_COMMON_API bool RSA::Encrypt<RSA::PublicKey>(uint8 const* data, std::size_t dataLength, uint8* output, int32 paddingType);
+ template TC_COMMON_API bool RSA::Encrypt<RSA::PrivateKey>(uint8 const* data, std::size_t dataLength, uint8* output, int32 paddingType);
+}
+}