summaryrefslogtreecommitdiffstats
path: root/source/core/slang-crypto.h
diff options
context:
space:
mode:
authorskallweitNV <64953474+skallweitNV@users.noreply.github.com>2022-12-02 16:34:53 +0100
committerGitHub <noreply@github.com>2022-12-02 16:34:53 +0100
commite9b7c66a541636e72659fbfcc9a3f20a85f2bee8 (patch)
treeb65942799ff6267ebe29c8b64056819461621be7 /source/core/slang-crypto.h
parent92ae4949fe1af28ef31331fd4116c8111c057420 (diff)
Cleanup crypto utilities (#2549)
* Consolidate crypto functions into single module * Migrate rest of code to new crypto module * Fix name conflict
Diffstat (limited to 'source/core/slang-crypto.h')
-rw-r--r--source/core/slang-crypto.h184
1 files changed, 184 insertions, 0 deletions
diff --git a/source/core/slang-crypto.h b/source/core/slang-crypto.h
new file mode 100644
index 000000000..0df02201c
--- /dev/null
+++ b/source/core/slang-crypto.h
@@ -0,0 +1,184 @@
+#pragma once
+#include "../../slang.h"
+#include "../core/slang-string.h"
+#include "../core/slang-blob.h"
+#include "../core/slang-list.h"
+
+namespace Slang
+{
+ struct DigestUtil
+ {
+ /// Convert a binary digest to a string (lower-case hexadecimal).
+ /// Returned string is double the length of the digest.
+ static String digestToString(const void* digest, SlangInt digestSize);
+
+ /// Convert a string to a binary digest.
+ /// Expects a string of double the length of the digest size in hexadecimal format.
+ /// Sets the digest to all zeros if the string is invalid.
+ /// Returns true if string was converted successfully.
+ static bool stringToDigest(const char* str, SlangInt strLength, void *digest, SlangInt digestSize);
+ };
+
+ /// Represents a hash digest. Only sizes of multiple of 4 are supported.
+ template<SlangInt N>
+ class HashDigest
+ {
+ public:
+ static_assert(N % 4 == 0, "size must be multiple of 4");
+ uint32_t data[N / 4] = { 0 };
+
+ HashDigest() = default;
+
+ HashDigest(const char* str)
+ {
+ DigestUtil::stringToDigest(str, ::strlen(str), data, N);
+ }
+
+ HashDigest(const String& str)
+ {
+ DigestUtil::stringToDigest(str.getBuffer(), str.getLength(), data, N);
+ }
+
+ HashDigest(const UnownedStringSlice& str)
+ {
+ DigestUtil::stringToDigest(str.begin(), str.getLength(), data, N);
+ }
+
+ HashDigest(ISlangBlob* blob)
+ {
+ if (blob->getBufferSize() == N)
+ {
+ ::memcpy(data, blob->getBufferPointer(), N);
+ }
+ }
+
+ String toString() const
+ {
+ return DigestUtil::digestToString(data, N);
+ }
+
+ ComPtr<ISlangBlob> toBlob() const
+ {
+ return RawBlob::create(data, sizeof(data));
+ }
+
+ bool operator==(const HashDigest& other) const
+ {
+ return ::memcmp(data, other.data, sizeof(data)) == 0;
+ }
+
+ bool operator!=(const HashDigest& other) const
+ {
+ return !(*this == other);
+ }
+
+ uint32_t getHashCode() const
+ {
+ return data[0];
+ }
+ };
+
+ /// MD5 hash generator implementing https://www.ietf.org/rfc/rfc1321.txt
+ class MD5
+ {
+ public:
+ using Digest = HashDigest<16>;
+
+ MD5();
+
+ void init();
+ void update(const void* data, SlangInt size);
+ Digest finalize();
+
+ static Digest compute(const void* data, SlangInt size);
+
+ private:
+ const void* processBlock(const void* data, SlangInt size);
+
+ uint32_t m_lo, m_hi;
+ uint32_t m_a, m_b, m_c, m_d;
+ uint32_t m_block[16];
+ uint8_t m_buffer[64];
+ };
+
+ /// SHA1 hash generator implementing https://www.ietf.org/rfc/rfc3174.txt
+ class SHA1
+ {
+ public:
+ using Digest = HashDigest<20>;
+
+ SHA1();
+
+ void init();
+ void update(const void* data, SlangInt size);
+ Digest finalize();
+
+ static Digest compute(const void* data, SlangInt size);
+
+ private:
+ void addByte(uint8_t x);
+ void processBlock(const uint8_t* ptr);
+
+ uint32_t m_index;
+ uint64_t m_bits;
+ uint32_t m_state[5];
+ uint8_t m_buf[64];
+ };
+
+ // Helper class for building hashes.
+ template<typename Hash>
+ struct DigestBuilder
+ {
+ public:
+ void append(const void* data, SlangInt size)
+ {
+ m_hash.update(data, size);
+ }
+
+ template<typename T, typename std::enable_if<std::is_arithmetic<T>::value || std::is_enum<T>::value, int>::type = 0>
+ void append(const T value)
+ {
+ append(&value, sizeof(T));
+ }
+
+ void append(const String& str)
+ {
+ append(str.getBuffer(), str.getLength());
+ }
+
+ void append(const StringSlice& str)
+ {
+ append(str.begin(), str.getLength());
+ }
+
+ void append(const UnownedStringSlice& str)
+ {
+ append(str.begin(), str.getLength());
+ }
+
+ void append(ISlangBlob* blob)
+ {
+ append(blob->getBufferPointer(), blob->getBufferSize());
+ }
+
+ template<SlangInt N>
+ void append(const HashDigest<N>& digest)
+ {
+ append(digest.data, sizeof(digest.data));
+ }
+
+ template<typename T, typename std::enable_if<std::is_pod<T>::value, int>::type = 0>
+ void append(const List<T>& list)
+ {
+ append(list.getBuffer(), list.getCount() * sizeof(T));
+ }
+
+ typename Hash::Digest finalize()
+ {
+ return m_hash.finalize();
+ }
+
+ private:
+ Hash m_hash;
+ };
+}