From 81807646ca7c3ba294e439695c86bddf7e3ce2be Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Mon, 20 Mar 2023 11:22:50 +0100 Subject: [PATCH] ENH: additional SHA1Digest constructors and methods - data_bytes(), size_bytes() methods to support broadcasting or gather/scatter content. Additional construct from raw bytes to support transmitting content. --- .../primitives/hashes/SHA1/SHA1Digest.C | 85 +++++++++++++++++-- .../primitives/hashes/SHA1/SHA1Digest.H | 50 ++++++++--- 2 files changed, 118 insertions(+), 17 deletions(-) diff --git a/src/OpenFOAM/primitives/hashes/SHA1/SHA1Digest.C b/src/OpenFOAM/primitives/hashes/SHA1/SHA1Digest.C index d91aa119429..934cca0d986 100644 --- a/src/OpenFOAM/primitives/hashes/SHA1/SHA1Digest.C +++ b/src/OpenFOAM/primitives/hashes/SHA1/SHA1Digest.C @@ -76,9 +76,66 @@ static unsigned char readHexDigit(Istream& is) } // End namespace Foam -// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // +namespace +{ -bool Foam::SHA1Digest::isEqual(const char* hexdigits, std::size_t len) const +// Copy assign digest from content +bool assign +( + std::array<unsigned char, 20>& digest, + const unsigned char* content, + std::size_t len +) +{ + if (!content || !len) + { + return false; + } + + if (len == digest.size()) + { + // ie, std::copy + for (auto& val : digest) + { + val = *content; + ++content; + } + + return true; + } + + // Skip possible '_' prefix + if (*content == '_') + { + ++content; + --len; + } + + // Incorrect length - can never assign + if (len != 2*digest.size()) + { + return false; + } + + for (auto& val : digest) + { + const unsigned char upp = *content++; + const unsigned char low = *content++; + + val = (upp << 4) + low; + } + + return true; +} + + +// Byte-wise compare digest contents +bool isEqual +( + const std::array<unsigned char, 20>& digest, + const char* hexdigits, + std::size_t len +) { // Skip possible '_' prefix if (*hexdigits == '_') @@ -88,12 +145,12 @@ bool Foam::SHA1Digest::isEqual(const char* hexdigits, std::size_t len) const } // Incorrect length - can never match - if (len != 2*dig_.size()) + if (len != 2*digest.size()) { return false; } - for (const auto& byteVal : dig_) + for (const auto& byteVal : digest) { const char upp = hexChars[((byteVal >> 4) & 0xF)]; const char low = hexChars[(byteVal & 0xF)]; @@ -105,6 +162,8 @@ bool Foam::SHA1Digest::isEqual(const char* hexdigits, std::size_t len) const return true; } +} // End anonymous namespace + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // @@ -114,6 +173,20 @@ Foam::SHA1Digest::SHA1Digest() } +Foam::SHA1Digest::SHA1Digest(const char* content, std::size_t len) +{ + clear(); + assign(dig_, reinterpret_cast<const unsigned char*>(content), len); +} + + +Foam::SHA1Digest::SHA1Digest(const unsigned char* content, std::size_t len) +{ + clear(); + assign(dig_, content, len); +} + + Foam::SHA1Digest::SHA1Digest(Istream& is) { clear(); @@ -214,7 +287,7 @@ bool Foam::SHA1Digest::operator==(const std::string& hexdigits) const // Interpret empty string as '0000..' size_t len = hexdigits.length(); - return len ? isEqual(hexdigits.data(), len) : empty(); + return len ? isEqual(dig_, hexdigits.data(), len) : empty(); } @@ -223,7 +296,7 @@ bool Foam::SHA1Digest::operator==(const char* hexdigits) const // Interpret nullptr or empty string as '0000..' size_t len = (hexdigits ? strlen(hexdigits) : 0); - return len ? isEqual(hexdigits, len) : empty(); + return len ? isEqual(dig_, hexdigits, len) : empty(); } diff --git a/src/OpenFOAM/primitives/hashes/SHA1/SHA1Digest.H b/src/OpenFOAM/primitives/hashes/SHA1/SHA1Digest.H index c8d0e7fa278..f3b3535f5b8 100644 --- a/src/OpenFOAM/primitives/hashes/SHA1/SHA1Digest.H +++ b/src/OpenFOAM/primitives/hashes/SHA1/SHA1Digest.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2019 OpenCFD Ltd. + Copyright (C) 2019-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -68,18 +68,12 @@ class SHA1Digest // Private Member Functions - //- Pointer to the underlying digest data - unsigned char* data() - { - return dig_.data(); - } - - //- Byte-wise compare digest contents - bool isEqual(const char* hexdigits, std::size_t len) const; - // Permit SHA1 to calculate the digest friend class SHA1; + //- Raw digest data (20 bytes). Non-const access for SHA1 + unsigned char* data() noexcept { return dig_.data(); } + public: @@ -94,9 +88,19 @@ public: //- Default construct a zero digest SHA1Digest(); - //- Read construct a digest + //- Read construct a digest from stringified content explicit SHA1Digest(Istream& is); + //- Construct digest from raw or stringified content. + //- The length is 20 for raw digest content and 40 (or 41) for + //- stringified versions. + SHA1Digest(const char* content, std::size_t len); + + //- Construct digest from raw or stringified content. + //- The length is 20 for raw digest content and 40 (or 41) for + //- stringified versions. + SHA1Digest(const unsigned char* content, std::size_t len); + // Member Functions @@ -119,6 +123,30 @@ public: Ostream& write(Ostream& os, const bool prefixed=false) const; + // Low-level access + + //- Raw digest data (20 bytes) - const access + const unsigned char* cdata() const noexcept { return dig_.data(); } + + //- Raw digest data (20 bytes) - const access + const unsigned char* cdata_bytes() const noexcept + { + return dig_.data(); + } + + //- Raw digest data (20 bytes) - non-const access. Use with caution! + unsigned char* data_bytes() noexcept + { + return dig_.data(); + } + + //- The number of bytes in digest (20) + static constexpr unsigned size_bytes() noexcept { return 20; } + + //- The dimensioned size of the digest is always 20 bytes + static constexpr unsigned max_size() noexcept { return 20; } + + // Member Operators //- Equality operator -- GitLab