https://github.com/shader-slang/slang
Raw File
Tip revision: bfd3f39d04047d7a46e75206cd125ed87b3f3f99 authored by Lin Hsu on 08 November 2023, 03:04:36 UTC
Fix HitObject::GetInstanceIndex/ID() for glsl/spirv (#3315)
Tip revision: bfd3f39
slang-crypto.h
#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, SlangSizeT 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, SlangSizeT 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, std::enable_if_t<std::has_unique_object_representations_v<T>, int> = 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;
    };
}
back to top