Remove Storage::Md5 and replace it with the one from Azure::Core. (#1618)

* Add MD5 hashing APIs to Azure::Core available from azure/core/md5.hpp.

* Add simplified header test for md5 and base64.

* Add changelog entry.

* Remove unnecessary include.

* Remove Storage::Md5 and replace it with the one from Azure::Core.

* Fix clang formatting.

* Add required cstdint include directive.

* Update storage based on recent changes to Md5 hash APIs.
This commit is contained in:
Ahson Khan 2021-02-08 20:04:25 -08:00 committed by GitHub
parent 306913ff1b
commit 5359e2793a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 26 additions and 154 deletions

View File

@ -7,6 +7,7 @@
#include <random>
#include <vector>
#include <azure/core/cryptography/hash.hpp>
#include <azure/storage/common/crypt.hpp>
#include <azure/storage/common/file_io.hpp>
@ -120,10 +121,12 @@ namespace Azure { namespace Storage { namespace Test {
auto res = m_blockBlobClient->Download(options);
ASSERT_TRUE(res->TransactionalContentHash.HasValue());
EXPECT_EQ(res->TransactionalContentHash.GetValue().Algorithm, HashAlgorithm::Md5);
EXPECT_EQ(
res->TransactionalContentHash.GetValue().Value,
Md5::Hash(m_blobContent.data(), downloadLength));
{
Azure::Core::Cryptography::Md5Hash instance;
EXPECT_EQ(
res->TransactionalContentHash.GetValue().Value,
instance.Final(m_blobContent.data(), downloadLength));
}
options.RangeHashAlgorithm = HashAlgorithm::Crc64;
res = m_blockBlobClient->Download(options);
ASSERT_TRUE(res->TransactionalContentHash.HasValue());

View File

@ -6,6 +6,7 @@
#include <future>
#include <vector>
#include <azure/core/cryptography/hash.hpp>
#include <azure/storage/blobs/blob_lease_client.hpp>
#include <azure/storage/common/crypt.hpp>
#include <azure/storage/common/file_io.hpp>
@ -251,7 +252,11 @@ namespace Azure { namespace Storage { namespace Test {
Blobs::UploadPageBlobPagesOptions options;
ContentHash hash;
hash.Algorithm = HashAlgorithm::Md5;
hash.Value = Md5::Hash(blobContent.data(), blobContent.size());
{
Azure::Core::Cryptography::Md5Hash instance;
hash.Value = instance.Final(blobContent.data(), blobContent.size());
}
options.TransactionalContentHash = hash;
EXPECT_NO_THROW(pageBlobClient.UploadPages(0, &pageContent, options));

View File

@ -2,6 +2,9 @@
## 12.0.0-beta.8 (Unreleased)
### 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`.
## 12.0.0-beta.7 (2021-02-03)

View File

@ -11,31 +11,6 @@
namespace Azure { namespace Storage {
class Md5 {
public:
Md5();
~Md5();
void Update(const uint8_t* data, std::size_t length);
std::vector<uint8_t> Digest() const;
static std::vector<uint8_t> Hash(const uint8_t* data, std::size_t length)
{
Md5 instance;
instance.Update(data, length);
return instance.Digest();
}
static std::vector<uint8_t> Hash(const std::string& data)
{
return Hash(reinterpret_cast<const uint8_t*>(data.data()), data.length());
}
private:
void* m_context;
};
class Crc64 {
public:
void Update(const uint8_t* data, std::size_t length);

View File

@ -18,7 +18,6 @@
#include <openssl/buffer.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#endif
@ -87,7 +86,6 @@ namespace Azure { namespace Storage {
{
HmacSha256,
Sha256,
Md5,
};
struct AlgorithmProviderInstance
@ -103,10 +101,6 @@ namespace Azure { namespace Storage {
{
algorithmId = BCRYPT_SHA256_ALGORITHM;
}
else if (type == AlgorithmType::Md5)
{
algorithmId = BCRYPT_MD5_ALGORITHM;
}
else
{
throw std::runtime_error("unknwon algorithm type");
@ -249,75 +243,6 @@ namespace Azure { namespace Storage {
}
} // namespace Details
struct Md5HashContext
{
std::string buffer;
BCRYPT_HASH_HANDLE hashHandle = nullptr;
std::size_t hashLength = 0;
};
Md5::Md5()
{
static Details::AlgorithmProviderInstance AlgorithmProvider(Details::AlgorithmType::Md5);
Md5HashContext* context = new Md5HashContext;
m_context = context;
context->buffer.resize(AlgorithmProvider.ContextSize);
context->hashLength = AlgorithmProvider.HashLength;
NTSTATUS status = BCryptCreateHash(
AlgorithmProvider.Handle,
&context->hashHandle,
reinterpret_cast<PUCHAR>(&context->buffer[0]),
static_cast<ULONG>(context->buffer.size()),
nullptr,
0,
0);
if (!BCRYPT_SUCCESS(status))
{
throw std::runtime_error("BCryptCreateHash failed");
}
}
Md5::~Md5()
{
Md5HashContext* context = static_cast<Md5HashContext*>(m_context);
BCryptDestroyHash(context->hashHandle);
delete context;
}
void Md5::Update(const uint8_t* data, std::size_t length)
{
Md5HashContext* context = static_cast<Md5HashContext*>(m_context);
NTSTATUS status = BCryptHashData(
context->hashHandle,
reinterpret_cast<PBYTE>(const_cast<uint8_t*>(data)),
static_cast<ULONG>(length),
0);
if (!BCRYPT_SUCCESS(status))
{
throw std::runtime_error("BCryptHashData failed");
}
}
std::vector<uint8_t> Md5::Digest() const
{
Md5HashContext* context = static_cast<Md5HashContext*>(m_context);
std::vector<uint8_t> hash;
hash.resize(context->hashLength);
NTSTATUS status = BCryptFinishHash(
context->hashHandle,
reinterpret_cast<PUCHAR>(&hash[0]),
static_cast<ULONG>(hash.size()),
0);
if (!BCRYPT_SUCCESS(status))
{
throw std::runtime_error("BCryptFinishHash failed");
}
return hash;
}
#elif defined(AZ_PLATFORM_POSIX)
namespace Details {
@ -352,33 +277,6 @@ namespace Azure { namespace Storage {
} // namespace Details
Md5::Md5()
{
MD5_CTX* context = new MD5_CTX;
m_context = context;
MD5_Init(context);
}
Md5::~Md5()
{
MD5_CTX* context = static_cast<MD5_CTX*>(m_context);
delete context;
}
void Md5::Update(const uint8_t* data, std::size_t length)
{
MD5_CTX* context = static_cast<MD5_CTX*>(m_context);
MD5_Update(context, data, length);
}
std::vector<uint8_t> Md5::Digest() const
{
MD5_CTX* context = static_cast<MD5_CTX*>(m_context);
unsigned char hash[MD5_DIGEST_LENGTH];
MD5_Final(hash, context);
return std::vector<uint8_t>(std::begin(hash), std::end(hash));
}
#endif
static constexpr uint64_t Crc64Poly = 0x9A6C9329AC4BC9B5ULL;

View File

@ -37,26 +37,6 @@ namespace Azure { namespace Storage { namespace Test {
"+SBESxQVhI53mSEdZJcCBpdBkaqwzfPaVYZMAf5LP3c=");
}
TEST(CryptFunctionsTest, Md5)
{
EXPECT_EQ(Azure::Core::Base64Encode(Md5::Hash("")), "1B2M2Y8AsgTpgAmY7PhCfg==");
EXPECT_EQ(Azure::Core::Base64Encode(Md5::Hash("Hello Azure!")), "Pz8543xut4RVSbb2g52Mww==");
auto data = RandomBuffer(static_cast<std::size_t>(16_MB));
Md5 md5Instance;
std::size_t length = 0;
while (length < data.size())
{
std::size_t s = static_cast<std::size_t>(RandomInt(0, 4_MB));
s = std::min(s, data.size() - length);
md5Instance.Update(&data[length], s);
md5Instance.Update(&data[length], 0);
length += s;
}
EXPECT_EQ(md5Instance.Digest(), Md5::Hash(data.data(), data.size()));
}
TEST(CryptFunctionsTest, Crc64)
{
EXPECT_EQ(Azure::Core::Base64Encode(Crc64::Hash("")), "AAAAAAAAAAA=");

View File

@ -7,6 +7,7 @@
#include <chrono>
#include <future>
#include <azure/core/cryptography/hash.hpp>
#include <azure/storage/common/crypt.hpp>
#include <azure/storage/common/file_io.hpp>
#include <azure/storage/common/storage_common.hpp>
@ -600,6 +601,12 @@ namespace Azure { namespace Storage { namespace Test {
}
}
static std::vector<uint8_t> Hash(const std::string& data)
{
Azure::Core::Cryptography::Md5Hash instance;
return instance.Final(reinterpret_cast<const uint8_t*>(data.data()), data.size());
}
TEST_F(FileShareFileClientTest, RangeUploadDownload)
{
auto rangeSize = 1 * 1024 * 1024;
@ -640,8 +647,9 @@ namespace Azure { namespace Storage { namespace Test {
{
// MD5 works.
memBodyStream.Rewind();
auto md5 = Md5::Hash(rangeContent.data(), rangeContent.size());
auto invalidMd5 = Md5::Hash(std::string("This is garbage."));
Azure::Core::Cryptography::Md5Hash instance;
auto md5 = instance.Final(rangeContent.data(), rangeContent.size());
auto invalidMd5 = Hash(std::string("This is garbage."));
auto fileClient
= m_shareClient->GetRootDirectoryClient().GetFileClient(LowercaseRandomString(10));
Files::Shares::UploadShareFileRangeOptions uploadOptions;