diff options
author | AnotherTest <ali.mpfard@gmail.com> | 2020-04-25 05:06:33 +0430 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-05-02 12:24:10 +0200 |
commit | 43a49f5fff72b519bdc3a87f0df610bcd9f405bf (patch) | |
tree | dc46f1e2fa39048658bc91d3ef266312bb9401c5 /Libraries/LibCrypto/Hash | |
parent | e997661e26d404132308addf21f499d35b787a1a (diff) | |
download | serenity-43a49f5fff72b519bdc3a87f0df610bcd9f405bf.zip |
LibCrypto: Add a Hash::Manager that can act as any one of the hashes
Diffstat (limited to 'Libraries/LibCrypto/Hash')
-rw-r--r-- | Libraries/LibCrypto/Hash/HashFunction.h | 6 | ||||
-rw-r--r-- | Libraries/LibCrypto/Hash/HashManager.h | 309 | ||||
-rw-r--r-- | Libraries/LibCrypto/Hash/MD5.h | 6 | ||||
-rw-r--r-- | Libraries/LibCrypto/Hash/SHA1.h | 4 | ||||
-rw-r--r-- | Libraries/LibCrypto/Hash/SHA2.h | 3 |
5 files changed, 324 insertions, 4 deletions
diff --git a/Libraries/LibCrypto/Hash/HashFunction.h b/Libraries/LibCrypto/Hash/HashFunction.h index 19c2f0db05..e6d5887484 100644 --- a/Libraries/LibCrypto/Hash/HashFunction.h +++ b/Libraries/LibCrypto/Hash/HashFunction.h @@ -37,7 +37,7 @@ template<size_t BlockS, typename DigestT> class HashFunction { public: static constexpr auto BlockSize = BlockS / 8; - static constexpr auto DigestSize = sizeof(DigestT); + static constexpr auto DigestSize = DigestT::Size; using DigestType = DigestT; @@ -45,8 +45,8 @@ public: static size_t digest_size() { return DigestSize; }; virtual void update(const u8*, size_t) = 0; - virtual void update(const ByteBuffer& buffer) = 0; - virtual void update(const StringView& string) = 0; + virtual void update(const ByteBuffer& buffer) { update(buffer.data(), buffer.size()); }; + virtual void update(const StringView& string) { update((const u8*)string.characters_without_null_termination(), string.length()); }; virtual DigestType peek() = 0; virtual DigestType digest() = 0; diff --git a/Libraries/LibCrypto/Hash/HashManager.h b/Libraries/LibCrypto/Hash/HashManager.h new file mode 100644 index 0000000000..fb01db77b9 --- /dev/null +++ b/Libraries/LibCrypto/Hash/HashManager.h @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2020, Ali Mohammad Pur <ali.mpfard@gmail.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include <AK/Optional.h> +#include <LibCrypto/Hash/HashFunction.h> +#include <LibCrypto/Hash/MD5.h> +#include <LibCrypto/Hash/SHA1.h> +#include <LibCrypto/Hash/SHA2.h> + +namespace Crypto { +namespace Hash { + +enum class HashKind { + None, + SHA1, + SHA256, + SHA512, + MD5, +}; + +struct MultiHashDigestVariant { + + constexpr static size_t Size = 0; + + MultiHashDigestVariant(SHA1::DigestType digest) + : sha1(digest) + , kind(HashKind::SHA1) + { + } + + MultiHashDigestVariant(SHA256::DigestType digest) + : sha256(digest) + , kind(HashKind::SHA256) + { + } + + MultiHashDigestVariant(SHA512::DigestType digest) + : sha512(digest) + , kind(HashKind::SHA512) + { + } + + MultiHashDigestVariant(MD5::DigestType digest) + : md5(digest) + , kind(HashKind::MD5) + { + } + + const u8* immutable_data() const + { + switch (kind) { + case HashKind::MD5: + return md5.value().immutable_data(); + case HashKind::SHA1: + return sha1.value().immutable_data(); + case HashKind::SHA256: + return sha256.value().immutable_data(); + case HashKind::SHA512: + return sha512.value().immutable_data(); + default: + case HashKind::None: + ASSERT_NOT_REACHED(); + break; + } + } + + size_t data_length() + { + switch (kind) { + case HashKind::MD5: + return md5.value().data_length(); + case HashKind::SHA1: + return sha1.value().data_length(); + case HashKind::SHA256: + return sha256.value().data_length(); + case HashKind::SHA512: + return sha512.value().data_length(); + default: + case HashKind::None: + ASSERT_NOT_REACHED(); + break; + } + } + + Optional<SHA1::DigestType> sha1; + Optional<SHA256::DigestType> sha256; + Optional<SHA512::DigestType> sha512; + Optional<MD5::DigestType> md5; + HashKind kind { HashKind::None }; +}; + +class Manager final : public HashFunction<0, MultiHashDigestVariant> { +public: + Manager() + { + m_pre_init_buffer = ByteBuffer::create_zeroed(0); + } + + Manager(const Manager& other) // NOT a copy constructor! + { + m_pre_init_buffer = ByteBuffer::create_zeroed(0); // will not be used + initialise(other.m_kind); + } + + Manager(HashKind kind) + { + m_pre_init_buffer = ByteBuffer::create_zeroed(0); + initialize(kind); + } + + ~Manager() + { + } + + virtual void update(const ByteBuffer& buffer) override { update(buffer.data(), buffer.size()); }; + virtual void update(const StringView& string) override { update((const u8*)string.characters_without_null_termination(), string.length()); }; + inline size_t digest_size() const + { + switch (m_kind) { + case HashKind::MD5: + return md5.value().digest_size(); + case HashKind::SHA1: + return sha1.value().digest_size(); + case HashKind::SHA256: + return sha256.value().digest_size(); + case HashKind::SHA512: + return sha512.value().digest_size(); + default: + case HashKind::None: + return 0; + } + } + inline size_t block_size() const + { + switch (m_kind) { + case HashKind::MD5: + return m_md5->block_size(); + case HashKind::SHA1: + return m_sha1->block_size(); + case HashKind::SHA256: + return m_sha256->block_size(); + case HashKind::SHA512: + return m_sha512->block_size(); + default: + case HashKind::None: + return 0; + } + } + inline void initialize(HashKind kind) + { + if (m_kind != HashKind::None) { + ASSERT_NOT_REACHED(); + } + + m_kind = kind; + switch (kind) { + case HashKind::MD5: + md5 = MD5 {}; + break; + case HashKind::SHA1: + sha1 = SHA1 {}; + break; + case HashKind::SHA256: + sha256 = SHA256 {}; + break; + case HashKind::SHA512: + sha512 = SHA512 {}; + break; + default: + case HashKind::None: + break; + } + } + + virtual void update(const u8* data, size_t length) override + { + switch (m_kind) { + case HashKind::MD5: + if (m_pre_init_buffer.size()) + md5.value().update(m_pre_init_buffer); + md5.value().update(data, length); + break; + case HashKind::SHA1: + if (m_pre_init_buffer.size()) + sha1.value().update(m_pre_init_buffer); + sha1.value().update(data, length); + break; + case HashKind::SHA256: + if (m_pre_init_buffer.size()) + sha256.value().update(m_pre_init_buffer); + sha256.value().update(data, length); + break; + case HashKind::SHA512: + if (m_pre_init_buffer.size()) + sha512.value().update(m_pre_init_buffer); + sha512.value().update(data, length); + break; + default: + case HashKind::None: + m_pre_init_buffer.append(data, length); + return; + } + m_pre_init_buffer.clear(); + } + + virtual DigestType peek() override + { + switch (m_kind) { + case HashKind::MD5: + return { md5.value().peek() }; + case HashKind::SHA1: + return { sha1.value().peek() }; + case HashKind::SHA256: + return { sha256.value().peek() }; + case HashKind::SHA512: + return { sha512.value().peek() }; + default: + case HashKind::None: + ASSERT_NOT_REACHED(); + break; + } + } + + virtual DigestType digest() override + { + auto digest = peek(); + reset(); + return digest; + } + + virtual void reset() override + { + switch (m_kind) { + case HashKind::MD5: + md5.value().reset(); + break; + case HashKind::SHA1: + sha1.value().reset(); + break; + case HashKind::SHA256: + sha256.value().reset(); + break; + case HashKind::SHA512: + sha512.value().reset(); + break; + default: + case HashKind::None: + break; + } + } + + virtual String class_name() const override + { + switch (m_kind) { + case HashKind::MD5: + return md5.value().class_name(); + case HashKind::SHA1: + return sha1.value().class_name(); + case HashKind::SHA256: + return sha256.value().class_name(); + case HashKind::SHA512: + return sha512.value().class_name(); + default: + case HashKind::None: + return "UninitializedHashManager"; + } + } + + inline bool is(HashKind kind) const + { + return m_kind == kind; + } + +private: + Optional<SHA1> sha1; + Optional<SHA256> sha256; + Optional<SHA512> sha512; + Optional<MD5> md5; + HashKind m_kind { HashKind::None }; + ByteBuffer m_pre_init_buffer; +}; + +} +} diff --git a/Libraries/LibCrypto/Hash/MD5.h b/Libraries/LibCrypto/Hash/MD5.h index 883029527c..3219cb9260 100644 --- a/Libraries/LibCrypto/Hash/MD5.h +++ b/Libraries/LibCrypto/Hash/MD5.h @@ -34,7 +34,11 @@ namespace Crypto { namespace Hash { struct MD5Digest { - u8 data[16]; + constexpr static size_t Size = 16; + u8 data[Size]; + + const u8* immutable_data() const { return data; } + size_t data_length() { return Size; } }; namespace MD5Constants { diff --git a/Libraries/LibCrypto/Hash/SHA1.h b/Libraries/LibCrypto/Hash/SHA1.h index fd15c6b962..bb37296612 100644 --- a/Libraries/LibCrypto/Hash/SHA1.h +++ b/Libraries/LibCrypto/Hash/SHA1.h @@ -48,6 +48,10 @@ constexpr static u32 RoundConstants[4] { template<size_t Bytes> struct SHA1Digest { u8 data[Bytes]; + constexpr static size_t Size = Bytes; + + const u8* immutable_data() const { return data; } + size_t data_length() { return Bytes; } }; class SHA1 final : public HashFunction<512, SHA1Digest<160 / 8>> { diff --git a/Libraries/LibCrypto/Hash/SHA2.h b/Libraries/LibCrypto/Hash/SHA2.h index 2437cc17cc..ebb38d9888 100644 --- a/Libraries/LibCrypto/Hash/SHA2.h +++ b/Libraries/LibCrypto/Hash/SHA2.h @@ -88,6 +88,9 @@ constexpr static u64 InitializationHashes[8] = { template<size_t Bytes> struct SHA2Digest { u8 data[Bytes]; + constexpr static size_t Size = Bytes; + const u8* immutable_data() const { return data; } + size_t data_length() { return Bytes; } }; // FIXME: I want template<size_t BlockSize> but the compiler gets confused |