aboutsummaryrefslogtreecommitdiff
path: root/src/common/Cryptography/CryptoHash.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/Cryptography/CryptoHash.h')
-rw-r--r--src/common/Cryptography/CryptoHash.h119
1 files changed, 119 insertions, 0 deletions
diff --git a/src/common/Cryptography/CryptoHash.h b/src/common/Cryptography/CryptoHash.h
new file mode 100644
index 00000000000..8c9825ce2d8
--- /dev/null
+++ b/src/common/Cryptography/CryptoHash.h
@@ -0,0 +1,119 @@
+/*
+ * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
+ *
+ * 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/>.
+ */
+
+#ifndef TRINITY_CRYPTOHASH_H
+#define TRINITY_CRYPTOHASH_H
+
+#include "CryptoConstants.h"
+#include "Define.h"
+#include "Errors.h"
+#include <array>
+#include <string>
+#include <string_view>
+#include <openssl/evp.h>
+
+class BigNumber;
+
+namespace Trinity::Impl
+{
+ struct GenericHashImpl
+ {
+ typedef EVP_MD const* (*HashCreator)();
+
+#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L
+ static EVP_MD_CTX* MakeCTX() { return EVP_MD_CTX_create(); }
+ static void DestroyCTX(EVP_MD_CTX* ctx) { EVP_MD_CTX_destroy(ctx); }
+#else
+ static EVP_MD_CTX* MakeCTX() { return EVP_MD_CTX_new(); }
+ static void DestroyCTX(EVP_MD_CTX* ctx) { EVP_MD_CTX_free(ctx); }
+#endif
+ };
+
+ template <GenericHashImpl::HashCreator HashCreator, size_t DigestLength>
+ class GenericHash
+ {
+ public:
+ static constexpr size_t DIGEST_LENGTH = DigestLength;
+ using Digest = std::array<uint8, DIGEST_LENGTH>;
+
+ static Digest GetDigestOf(uint8 const* data, size_t len)
+ {
+ GenericHash hash;
+ hash.UpdateData(data, len);
+ hash.Finalize();
+ return hash.GetDigest();
+ }
+
+ template <typename... Ts>
+ static auto GetDigestOf(Ts&&... pack) -> std::enable_if_t<!(std::is_integral_v<std::decay_t<Ts>> || ...), Digest>
+ {
+ GenericHash hash;
+ (hash.UpdateData(std::forward<Ts>(pack)), ...);
+ hash.Finalize();
+ return hash.GetDigest();
+ }
+
+ GenericHash() : _ctx(GenericHashImpl::MakeCTX())
+ {
+ int result = EVP_DigestInit_ex(_ctx, HashCreator(), nullptr);
+ ASSERT(result == 1);
+ }
+
+ ~GenericHash()
+ {
+ if (!_ctx)
+ return;
+ GenericHashImpl::DestroyCTX(_ctx);
+ _ctx = nullptr;
+ }
+
+ void UpdateData(uint8 const* data, size_t len)
+ {
+ int result = EVP_DigestUpdate(_ctx, data, len);
+ ASSERT(result == 1);
+ }
+ void UpdateData(std::string_view str) { UpdateData(reinterpret_cast<uint8 const*>(str.data()), str.size()); }
+ void UpdateData(std::string const& str) { UpdateData(std::string_view(str)); } /* explicit overload to avoid using the container template */
+ void UpdateData(char const* str) { UpdateData(std::string_view(str)); } /* explicit overload to avoid using the container template */
+ template <typename Container>
+ void UpdateData(Container const& c) { UpdateData(std::data(c), std::size(c)); }
+
+ void Finalize()
+ {
+ uint32 length;
+ int result = EVP_DigestFinal_ex(_ctx, _digest.data(), &length);
+ ASSERT(result == 1);
+ ASSERT(length == DIGEST_LENGTH);
+ GenericHashImpl::DestroyCTX(_ctx);
+ _ctx = nullptr;
+ }
+
+ Digest const& GetDigest() const { return _digest; }
+
+ private:
+ EVP_MD_CTX* _ctx;
+ Digest _digest;
+ };
+}
+
+namespace Trinity::Crypto
+{
+ using SHA1 = Trinity::Impl::GenericHash<EVP_sha1, Constants::SHA1_DIGEST_LENGTH_BYTES>;
+ using SHA256 = Trinity::Impl::GenericHash<EVP_sha256, Constants::SHA256_DIGEST_LENGTH_BYTES>;
+}
+
+#endif