From b40603dc4001e37908c7fd8a7d3e5d9cac0e0a3e Mon Sep 17 00:00:00 2001 From: Ahson Khan Date: Tue, 9 Feb 2021 22:06:11 -0800 Subject: [PATCH] Renamed `Crc64` to `Crc64Hash` and change it to derive from the `Azure::Core::Cryptography::Hash` class. (#1646) * Renamed `Crc64` to `Crc64Hash` and change it to derive from the `Azure::Core::Cryptography::Hash` class. * Add default dtor --- .../test/block_blob_client_test.cpp | 9 ++- .../test/page_blob_client_test.cpp | 6 +- sdk/storage/azure-storage-common/CHANGELOG.md | 3 +- .../inc/azure/storage/common/crypt.hpp | 23 ++----- .../azure-storage-common/src/crypt.cpp | 7 +- .../test/crypt_functions_test.cpp | 68 ++++++++++++++----- 6 files changed, 75 insertions(+), 41 deletions(-) diff --git a/sdk/storage/azure-storage-blobs/test/block_blob_client_test.cpp b/sdk/storage/azure-storage-blobs/test/block_blob_client_test.cpp index a1503ee09..50feaef52 100644 --- a/sdk/storage/azure-storage-blobs/test/block_blob_client_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/block_blob_client_test.cpp @@ -131,9 +131,12 @@ namespace Azure { namespace Storage { namespace Test { res = m_blockBlobClient->Download(options); ASSERT_TRUE(res->TransactionalContentHash.HasValue()); EXPECT_EQ(res->TransactionalContentHash.GetValue().Algorithm, HashAlgorithm::Crc64); - EXPECT_EQ( - res->TransactionalContentHash.GetValue().Value, - Crc64::Hash(m_blobContent.data(), downloadLength)); + { + Crc64Hash instance; + EXPECT_EQ( + res->TransactionalContentHash.GetValue().Value, + instance.Final(m_blobContent.data(), downloadLength)); + } } TEST_F(BlockBlobClientTest, DISABLED_LastAccessTime) diff --git a/sdk/storage/azure-storage-blobs/test/page_blob_client_test.cpp b/sdk/storage/azure-storage-blobs/test/page_blob_client_test.cpp index f8d80e4aa..ca28cdf27 100644 --- a/sdk/storage/azure-storage-blobs/test/page_blob_client_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/page_blob_client_test.cpp @@ -280,7 +280,11 @@ namespace Azure { namespace Storage { namespace Test { Blobs::UploadPageBlobPagesOptions options; ContentHash hash; hash.Algorithm = HashAlgorithm::Crc64; - hash.Value = Crc64::Hash(blobContent.data(), blobContent.size()); + + { + Crc64Hash instance; + hash.Value = instance.Final(blobContent.data(), blobContent.size()); + } options.TransactionalContentHash = hash; EXPECT_NO_THROW(pageBlobClient.UploadPages(0, &pageContent, options)); diff --git a/sdk/storage/azure-storage-common/CHANGELOG.md b/sdk/storage/azure-storage-common/CHANGELOG.md index 4c53ad7dd..33df251bb 100644 --- a/sdk/storage/azure-storage-common/CHANGELOG.md +++ b/sdk/storage/azure-storage-common/CHANGELOG.md @@ -4,7 +4,8 @@ ### Breaking Changes -- Remove the `Azure::Storage::Md5` class from `crypt.hpp`. Use the type from `Azure::Core::Cryptography` namespace instead, from `azure/core/cryptography/hash.hpp`. +- Removed the `Azure::Storage::Md5` class from `crypt.hpp`. Use the type from `Azure::Core::Cryptography` namespace instead, from `azure/core/cryptography/hash.hpp`. +- Renamed `Crc64` to `Crc64Hash` and change it to derive from the `Azure::Core::Cryptography::Hash` class. ## 12.0.0-beta.7 (2021-02-03) diff --git a/sdk/storage/azure-storage-common/inc/azure/storage/common/crypt.hpp b/sdk/storage/azure-storage-common/inc/azure/storage/common/crypt.hpp index 688f0aa0e..e13861d86 100644 --- a/sdk/storage/azure-storage-common/inc/azure/storage/common/crypt.hpp +++ b/sdk/storage/azure-storage-common/inc/azure/storage/common/crypt.hpp @@ -7,32 +7,23 @@ #include #include +#include "azure/core/cryptography/hash.hpp" #include namespace Azure { namespace Storage { - class Crc64 { + class Crc64Hash : public Azure::Core::Cryptography::Hash { public: - void Update(const uint8_t* data, std::size_t length); - void Concatenate(const Crc64& other); + void Concatenate(const Crc64Hash& other); - std::vector Digest() const; - - static std::vector Hash(const uint8_t* data, std::size_t length) - { - Crc64 instance; - instance.Update(data, length); - return instance.Digest(); - } - - static std::vector Hash(const std::string& data) - { - return Hash(reinterpret_cast(data.data()), data.length()); - } + ~Crc64Hash() override = default; private: uint64_t m_context = 0ULL; uint64_t m_length = 0ULL; + + void OnAppend(const uint8_t* data, std::size_t length) override; + std::vector OnFinal(const uint8_t* data, std::size_t length) override; }; namespace Details { diff --git a/sdk/storage/azure-storage-common/src/crypt.cpp b/sdk/storage/azure-storage-common/src/crypt.cpp index 8a6b61fbe..9898544d7 100644 --- a/sdk/storage/azure-storage-common/src/crypt.cpp +++ b/sdk/storage/azure-storage-common/src/crypt.cpp @@ -910,7 +910,7 @@ namespace Azure { namespace Storage { return vr[0] ^ vr[1]; } - void Crc64::Update(const uint8_t* data, std::size_t length) + void Crc64Hash::OnAppend(const uint8_t* data, std::size_t length) { m_length += length; @@ -1058,7 +1058,7 @@ namespace Azure { namespace Storage { m_context = uCrc ^ ~0ULL; } - void Crc64::Concatenate(const Crc64& other) + void Crc64Hash::Concatenate(const Crc64Hash& other) { m_length += other.m_length; @@ -1087,8 +1087,9 @@ namespace Azure { namespace Storage { m_context ^= other.m_context; } - std::vector Crc64::Digest() const + std::vector Crc64Hash::OnFinal(const uint8_t* data, std::size_t length) { + OnAppend(data, length); std::vector binary; binary.resize(sizeof(m_context)); for (std::size_t i = 0; i < sizeof(m_context); ++i) diff --git a/sdk/storage/azure-storage-common/test/crypt_functions_test.cpp b/sdk/storage/azure-storage-common/test/crypt_functions_test.cpp index 3569cdbc2..1b535db98 100644 --- a/sdk/storage/azure-storage-common/test/crypt_functions_test.cpp +++ b/sdk/storage/azure-storage-common/test/crypt_functions_test.cpp @@ -37,54 +37,66 @@ namespace Azure { namespace Storage { namespace Test { "+SBESxQVhI53mSEdZJcCBpdBkaqwzfPaVYZMAf5LP3c="); } - TEST(CryptFunctionsTest, Crc64) + static std::vector ComputeHash(const std::string& data) { - EXPECT_EQ(Azure::Core::Base64Encode(Crc64::Hash("")), "AAAAAAAAAAA="); - EXPECT_EQ(Azure::Core::Base64Encode(Crc64::Hash("Hello Azure!")), "DtjZpL9/o8c="); + const uint8_t* ptr = reinterpret_cast(data.data()); + Crc64Hash instance; + return instance.Final(ptr, data.length()); + } + + TEST(CryptFunctionsTest, Crc64Hash_Basic) + { + Crc64Hash crc64empty; + EXPECT_EQ(Azure::Core::Base64Encode(crc64empty.Final()), "AAAAAAAAAAA="); + + EXPECT_EQ(Azure::Core::Base64Encode(ComputeHash("")), "AAAAAAAAAAA="); + EXPECT_EQ(Azure::Core::Base64Encode(ComputeHash("Hello Azure!")), "DtjZpL9/o8c="); auto data = RandomBuffer(static_cast(16_MB)); - Crc64 crc64Instance; + Crc64Hash crc64Single; + Crc64Hash crc64Streaming; std::size_t length = 0; while (length < data.size()) { std::size_t s = static_cast(RandomInt(0, 4_MB)); s = std::min(s, data.size() - length); - crc64Instance.Update(&data[length], s); - crc64Instance.Update(&data[length], 0); + crc64Streaming.Append(&data[length], s); + crc64Streaming.Append(&data[length], 0); length += s; } - EXPECT_EQ(crc64Instance.Digest(), Crc64::Hash(data.data(), data.size())); + EXPECT_EQ(crc64Streaming.Final(), crc64Single.Final(data.data(), data.size())); // Test concatenate - crc64Instance = Crc64(); + crc64Single = Crc64Hash(); + crc64Streaming = Crc64Hash(); std::string allData; while (allData.length() < 16_MB) { { - Crc64 instance2; + Crc64Hash instance2; for (auto i = RandomInt(0, 5); i > 0; --i) { std::size_t s = static_cast(RandomInt(0, 512_KB)); std::string data2; data2.resize(s); RandomBuffer(&data2[0], s); - instance2.Update(reinterpret_cast(data2.data()), data2.length()); + instance2.Append(reinterpret_cast(data2.data()), data2.length()); allData += data2; } - crc64Instance.Concatenate(instance2); + crc64Streaming.Concatenate(instance2); } switch (RandomInt(0, 2)) { case 0: { std::string data2; - crc64Instance.Update(reinterpret_cast(data2.data()), data2.length()); + crc64Streaming.Append(reinterpret_cast(data2.data()), data2.length()); break; } case 1: { - Crc64 instance2; - crc64Instance.Concatenate(instance2); + Crc64Hash instance2; + crc64Streaming.Concatenate(instance2); break; } case 2: { @@ -92,7 +104,7 @@ namespace Azure { namespace Storage { namespace Test { std::string data2; data2.resize(s); RandomBuffer(&data2[0], s); - crc64Instance.Update(reinterpret_cast(data2.data()), data2.length()); + crc64Streaming.Append(reinterpret_cast(data2.data()), data2.length()); allData += data2; break; } @@ -102,8 +114,30 @@ namespace Azure { namespace Storage { namespace Test { } EXPECT_EQ( - crc64Instance.Digest(), - Crc64::Hash(reinterpret_cast(allData.data()), allData.size())); + crc64Streaming.Final(), + crc64Single.Final(reinterpret_cast(allData.data()), allData.size())); + } + + TEST(CryptFunctionsTest, Crc64Hash_ExpectThrow) + { + std::string data = ""; + const uint8_t* ptr = reinterpret_cast(data.data()); + Crc64Hash instance; + + EXPECT_THROW(instance.Final(nullptr, 1), std::invalid_argument); + EXPECT_THROW(instance.Append(nullptr, 1), std::invalid_argument); + + EXPECT_EQ(Azure::Core::Base64Encode(instance.Final(ptr, data.length())), "AAAAAAAAAAA="); + EXPECT_THROW(instance.Final(), std::runtime_error); + EXPECT_THROW(instance.Final(ptr, data.length()), std::runtime_error); + EXPECT_THROW(instance.Append(ptr, data.length()), std::runtime_error); + } + + TEST(CryptFunctionsTest, Crc64Hash_CtorDtor) + { + { + Crc64Hash instance; + } } }}} // namespace Azure::Storage::Test