summaryrefslogtreecommitdiff
path: root/src/buildtool/crypto/hasher.hpp
diff options
context:
space:
mode:
authorOliver Reiche <oliver.reiche@huawei.com>2022-06-15 18:51:47 +0200
committerOliver Reiche <oliver.reiche@huawei.com>2022-06-20 15:23:02 +0200
commit855affd9b681d98f248009ddb2c1abe987029f72 (patch)
tree6d4dbfc2c99020772313f381d2f793950d2b03f4 /src/buildtool/crypto/hasher.hpp
parent391d982f2fbd98a2973f14e0b5969f66c2abd756 (diff)
downloadjustbuild-855affd9b681d98f248009ddb2c1abe987029f72.tar.gz
Crypto: Refactor hash computation
... by renaming HashGenerator to (incremental) Hasher and dropping support for Git/MD5 hashes. The Hasher does not expose the actual hash implementation.
Diffstat (limited to 'src/buildtool/crypto/hasher.hpp')
-rw-r--r--src/buildtool/crypto/hasher.hpp104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/buildtool/crypto/hasher.hpp b/src/buildtool/crypto/hasher.hpp
new file mode 100644
index 00000000..0efe300f
--- /dev/null
+++ b/src/buildtool/crypto/hasher.hpp
@@ -0,0 +1,104 @@
+#ifndef INCLUDED_SRC_BUILDTOOL_CRYPTO_HASHER_HPP
+#define INCLUDED_SRC_BUILDTOOL_CRYPTO_HASHER_HPP
+
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+
+#include "src/buildtool/logging/logger.hpp"
+#include "src/utils/cpp/hex_string.hpp"
+
+/// \brief Incremental hasher.
+class Hasher {
+ public:
+ /// \brief Types of hash implementations supported by generator.
+ enum class HashType : std::uint8_t { SHA1, SHA256 };
+
+ /// \brief The universal hash digest.
+ /// The type of hash and the digest length depends on the hash
+ /// implementation used to generated this digest.
+ class HashDigest {
+ friend Hasher;
+
+ public:
+ /// \brief Get pointer to raw bytes of digest.
+ /// Length can be obtained using \ref Length.
+ [[nodiscard]] auto Bytes() const& -> std::string const& {
+ return bytes_;
+ }
+
+ [[nodiscard]] auto Bytes() && -> std::string {
+ return std::move(bytes_);
+ }
+
+ /// \brief Get hexadecimal string of digest.
+ /// Length is twice the length of raw bytes (\ref Length).
+ [[nodiscard]] auto HexString() const -> std::string {
+ return ToHexString(bytes_);
+ }
+
+ /// \brief Get digest length in raw bytes.
+ [[nodiscard]] auto Length() const -> std::size_t {
+ return bytes_.size();
+ }
+
+ private:
+ std::string bytes_{};
+
+ explicit HashDigest(std::string bytes) : bytes_{std::move(bytes)} {}
+ };
+
+ /// \brief Interface for hash implementations
+ class IHashImpl {
+ public:
+ IHashImpl() noexcept = default;
+ IHashImpl(IHashImpl const&) = delete;
+ IHashImpl(IHashImpl&&) = default;
+ auto operator=(IHashImpl const&) -> IHashImpl& = delete;
+ auto operator=(IHashImpl&&) -> IHashImpl& = default;
+ virtual ~IHashImpl() = default;
+
+ /// \brief Feed data to the incremental hashing.
+ [[nodiscard]] virtual auto Update(std::string const& data) noexcept
+ -> bool = 0;
+
+ /// \brief Finalize the hashing and return hash as string of raw bytes.
+ [[nodiscard]] virtual auto Finalize() && noexcept
+ -> std::optional<std::string> = 0;
+
+ /// \brief Compute the hash of data and return it as string of raw
+ /// bytes.
+ [[nodiscard]] virtual auto Compute(std::string const& data) && noexcept
+ -> std::string = 0;
+
+ static auto FatalError() noexcept -> void {
+ Logger::Log(LogLevel::Error, "Failed to compute hash.");
+ std::terminate();
+ }
+ };
+
+ explicit Hasher(HashType type) : impl_{CreateHashImpl(type)} {}
+
+ /// \brief Feed data to the hasher.
+ auto Update(std::string const& data) noexcept -> bool {
+ return impl_->Update(data);
+ }
+
+ /// \brief Finalize hash.
+ [[nodiscard]] auto Finalize() && noexcept -> HashDigest {
+ if (auto hash = std::move(*impl_).Finalize()) {
+ return HashDigest{std::move(*hash)};
+ }
+ IHashImpl::FatalError();
+ return HashDigest{{}};
+ }
+
+ private:
+ std::unique_ptr<IHashImpl> impl_;
+
+ [[nodiscard]] static auto CreateHashImpl(HashType type) noexcept
+ -> std::unique_ptr<IHashImpl>;
+};
+
+#endif // INCLUDED_SRC_BUILDTOOL_CRYPTO_HASHER_HPP