diff --git a/sdk/storage/azure-storage-blobs/CHANGELOG.md b/sdk/storage/azure-storage-blobs/CHANGELOG.md index c6ee2264f..5996ae5dc 100644 --- a/sdk/storage/azure-storage-blobs/CHANGELOG.md +++ b/sdk/storage/azure-storage-blobs/CHANGELOG.md @@ -47,6 +47,8 @@ - API signature for CommitBlockList has changed. `BlockType` doesn't need to be specified anymore. - `PageBlobClient::GetPageRanges` doesn't support getting difference between current blob and a snapshot anymore. Use `PageBlobClient::GetPageRangesDiff` instead. - Move Blob SAS into `Azure::Storage::Sas` namespace. +- Replace all transactional content MD5/CRC64 with `ContentHash` struct. +- `ContentMd5` HTTP header and `EncrytionKeySha256` are changed to binary(`std::vector`). ## 12.0.0-beta.5 (2020-11-13) diff --git a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_options.hpp b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_options.hpp index 52bc17ccd..4f05d6e3f 100644 --- a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_options.hpp +++ b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_options.hpp @@ -106,9 +106,9 @@ namespace Azure { namespace Storage { namespace Blobs { std::string Key; /** - * @brief Base64 encoded string of the AES256 encryption key's SHA256 hash. + * @brief SHA256 hash of the AES256 encryption key. */ - std::string KeyHash; + std::vector KeyHash; /** * @brief The algorithm for Azure Blob Storage to encrypt with. @@ -917,18 +917,11 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Context Context; /** - * @brief An MD5 hash of the blob content. This hash is used to verify the integrity of + * @brief Hash of the blob content. This hash is used to verify the integrity of * the blob during transport. When this header is specified, the storage service checks the hash * that has arrived with the one that was sent. */ - Azure::Core::Nullable TransactionalContentMd5; - - /** - * @brief A CRC64 hash of the blob content. This hash is used to verify the integrity of - * the blob during transport. When this header is specified, the storage service checks the hash - * that has arrived with the one that was sent. - */ - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; /** * @brief The standard HTTP header system properties to set. @@ -998,18 +991,11 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Context Context; /** - * @brief An MD5 hash of the blob content. This hash is used to verify the integrity of + * @brief Hash of the blob content. This hash is used to verify the integrity of * the blob during transport. When this header is specified, the storage service checks the hash * that has arrived with the one that was sent. */ - Azure::Core::Nullable TransactionalContentMd5; - - /** - * @brief A CRC64 hash of the blob content. This hash is used to verify the integrity of - * the blob during transport. When this header is specified, the storage service checks the hash - * that has arrived with the one that was sent. - */ - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; /** * @brief Optional conditions that must be met to perform this operation. @@ -1039,18 +1025,11 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable SourceLength; /** - * @brief An MD5 hash of the blob content. This hash is used to verify the integrity of + * @brief Hash of the blob content. This hash is used to verify the integrity of * the blob during transport. When this header is specified, the storage service checks the hash * that has arrived with the one that was sent. */ - Azure::Core::Nullable TransactionalContentMd5; - - /** - * @brief A CRC64 hash of the blob content. This hash is used to verify the integrity of - * the blob during transport. When this header is specified, the storage service checks the hash - * that has arrived with the one that was sent. - */ - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; /** * @brief Optional conditions that must be met to perform this operation. @@ -1157,18 +1136,11 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Context Context; /** - * @brief An MD5 hash of the blob content. This hash is used to verify the integrity of + * @brief Hash of the blob content. This hash is used to verify the integrity of * the blob during transport. When this header is specified, the storage service checks the hash * that has arrived with the one that was sent. */ - Azure::Core::Nullable TransactionalContentMd5; - - /** - * @brief A CRC64 hash of the blob content. This hash is used to verify the integrity of - * the blob during transport. When this header is specified, the storage service checks the hash - * that has arrived with the one that was sent. - */ - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; /** * @brief Optional conditions that must be met to perform this operation. @@ -1198,18 +1170,11 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable SourceLength; /** - * @brief An MD5 hash of the blob content. This hash is used to verify the integrity of + * @brief Hash of the blob content. This hash is used to verify the integrity of * the blob during transport. When this header is specified, the storage service checks the hash * that has arrived with the one that was sent. */ - Azure::Core::Nullable TransactionalContentMd5; - - /** - * @brief A CRC64 hash of the blob content. This hash is used to verify the integrity of - * the blob during transport. When this header is specified, the storage service checks the hash - * that has arrived with the one that was sent. - */ - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; /** * @brief Optional conditions that must be met to perform this operation. @@ -1281,18 +1246,11 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Context Context; /** - * @brief An MD5 hash of the blob content. This hash is used to verify the integrity of + * @brief Hash of the blob content. This hash is used to verify the integrity of * the blob during transport. When this header is specified, the storage service checks the hash * that has arrived with the one that was sent. */ - Azure::Core::Nullable TransactionalContentMd5; - - /** - * @brief A CRC64 hash of the blob content. This hash is used to verify the integrity of - * the blob during transport. When this header is specified, the storage service checks the hash - * that has arrived with the one that was sent. - */ - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; /** * @brief Optional conditions that must be met to perform this operation. @@ -1311,18 +1269,11 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Context Context; /** - * @brief An MD5 hash of the blob content. This hash is used to verify the integrity of + * @brief Hash of the blob content. This hash is used to verify the integrity of * the blob during transport. When this header is specified, the storage service checks the hash * that has arrived with the one that was sent. */ - Azure::Core::Nullable TransactionalContentMd5; - - /** - * @brief A CRC64 hash of the blob content. This hash is used to verify the integrity of - * the blob during transport. When this header is specified, the storage service checks the hash - * that has arrived with the one that was sent. - */ - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; /** * @brief Optional conditions that must be met to perform this operation. diff --git a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_responses.hpp b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_responses.hpp index 5d6164978..3a6014a7c 100644 --- a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_responses.hpp +++ b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_responses.hpp @@ -23,7 +23,7 @@ namespace Azure { namespace Storage { namespace Blobs { namespace Models { Storage::Metadata Metadata; Models::BlobType BlobType = Models::BlobType::Unknown; Azure::Core::Nullable ServerEncrypted; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; }; using UploadBlockBlobFromResult = UploadBlockBlobResult; diff --git a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/protocol/blob_rest_client.hpp b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/protocol/blob_rest_client.hpp index 7b95b2ac8..34112db7d 100644 --- a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/protocol/blob_rest_client.hpp +++ b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/protocol/blob_rest_client.hpp @@ -85,12 +85,11 @@ namespace Azure { namespace Storage { namespace Blobs { { std::string ETag; std::string LastModified; - Azure::Core::Nullable TransactionalContentMd5; - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; int64_t AppendOffset = 0; int64_t CommittedBlockCount = 0; Azure::Core::Nullable ServerEncrypted; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionScope; }; // struct AppendBlockFromUriResult @@ -98,12 +97,11 @@ namespace Azure { namespace Storage { namespace Blobs { { std::string ETag; std::string LastModified; - Azure::Core::Nullable TransactionalContentMd5; - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; int64_t AppendOffset = 0; int64_t CommittedBlockCount = 0; Azure::Core::Nullable ServerEncrypted; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionScope; }; // struct AppendBlockResult @@ -142,7 +140,7 @@ namespace Azure { namespace Storage { namespace Blobs { std::string ContentType; std::string ContentEncoding; std::string ContentLanguage; - std::string ContentMd5; + std::vector ContentMd5; std::string CacheControl; std::string ContentDisposition; }; // struct BlobHttpHeaders @@ -245,7 +243,7 @@ namespace Azure { namespace Storage { namespace Blobs { std::string LastModified; int64_t SequenceNumber = 0; Azure::Core::Nullable ServerEncrypted; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionScope; }; // struct ClearPageBlobPagesResult @@ -255,10 +253,9 @@ namespace Azure { namespace Storage { namespace Blobs { std::string LastModified; Azure::Core::Nullable VersionId; Azure::Core::Nullable ServerEncrypted; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionScope; - Azure::Core::Nullable TransactionalContentMd5; - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; }; // struct CommitBlockListResult enum class CopyStatus @@ -274,7 +271,7 @@ namespace Azure { namespace Storage { namespace Blobs { std::string LastModified; Azure::Core::Nullable VersionId; Azure::Core::Nullable ServerEncrypted; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionScope; }; // struct CreateAppendBlobResult @@ -291,7 +288,7 @@ namespace Azure { namespace Storage { namespace Blobs { std::string LastModified; Azure::Core::Nullable VersionId; Azure::Core::Nullable ServerEncrypted; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionScope; }; // struct CreateBlobSnapshotResult @@ -301,7 +298,7 @@ namespace Azure { namespace Storage { namespace Blobs { std::string LastModified; Azure::Core::Nullable VersionId; Azure::Core::Nullable ServerEncrypted; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionScope; Azure::Core::Nullable SequenceNumber; }; // struct CreatePageBlobResult @@ -563,19 +560,17 @@ namespace Azure { namespace Storage { namespace Blobs { struct StageBlockFromUriResult { - Azure::Core::Nullable TransactionalContentMd5; - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; Azure::Core::Nullable ServerEncrypted; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionScope; }; // struct StageBlockFromUriResult struct StageBlockResult { - Azure::Core::Nullable TransactionalContentMd5; - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; Azure::Core::Nullable ServerEncrypted; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionScope; }; // struct StageBlockResult @@ -598,21 +593,19 @@ namespace Azure { namespace Storage { namespace Blobs { std::string LastModified; Azure::Core::Nullable VersionId; Azure::Core::Nullable ServerEncrypted; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionScope; - Azure::Core::Nullable TransactionalContentMd5; - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; }; // struct UploadBlockBlobResult struct UploadPageBlobPagesFromUriResult { std::string ETag; std::string LastModified; - Azure::Core::Nullable TransactionalContentMd5; - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; int64_t SequenceNumber = 0; Azure::Core::Nullable ServerEncrypted; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionScope; }; // struct UploadPageBlobPagesFromUriResult @@ -620,11 +613,10 @@ namespace Azure { namespace Storage { namespace Blobs { { std::string ETag; std::string LastModified; - Azure::Core::Nullable TransactionalContentMd5; - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; int64_t SequenceNumber = 0; Azure::Core::Nullable ServerEncrypted; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionScope; }; // struct UploadPageBlobPagesResult @@ -807,7 +799,7 @@ namespace Azure { namespace Storage { namespace Blobs { BlobLeaseState LeaseState = BlobLeaseState::Available; Azure::Core::Nullable LeaseDuration; Azure::Core::Nullable ServerEncrypted; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionScope; Azure::Core::Nullable SequenceNumber; // only for page blobd Azure::Core::Nullable IsSealed; // only for append blob @@ -830,13 +822,12 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable CommittedBlockCount; // only for append blob Azure::Core::Nullable IsSealed; // only for append blob Blobs::Models::BlobType BlobType = Blobs::Models::BlobType::Unknown; - Azure::Core::Nullable TransactionalContentMd5; // Md5 for the downloaded range - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; // hash for the downloaded range Azure::Core::Nullable LeaseDuration; Azure::Core::Nullable LeaseState; Azure::Core::Nullable LeaseStatus; Azure::Core::Nullable ServerEncrypted; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionScope; Azure::Core::Nullable ObjectReplicationDestinationPolicyId; // only valid for replication destination blob @@ -863,7 +854,7 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable CommittedBlockCount; // only for append blob Azure::Core::Nullable IsSealed; // only for append blob Azure::Core::Nullable ServerEncrypted; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionScope; Azure::Core::Nullable Tier; Azure::Core::Nullable AccessTierInferred; @@ -4871,7 +4862,7 @@ namespace Azure { namespace Storage { namespace Blobs { path.size() == 2 && path[0] == XmlTagName::k_Properties && path[1] == XmlTagName::k_ContentMD5) { - ret.HttpHeaders.ContentMd5 = node.Value; + ret.HttpHeaders.ContentMd5 = Base64Decode(node.Value); } else if ( path.size() == 2 && path[0] == XmlTagName::k_Properties @@ -4967,7 +4958,7 @@ namespace Azure { namespace Storage { namespace Blobs { path.size() == 2 && path[0] == XmlTagName::k_Properties && path[1] == XmlTagName::k_EncryptionKeySHA256) { - ret.EncryptionKeySha256 = node.Value; + ret.EncryptionKeySha256 = Base64Decode(node.Value); } else if ( path.size() == 2 && path[0] == XmlTagName::k_Properties @@ -5260,7 +5251,7 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable Timeout; Azure::Core::Nullable> Range; Azure::Core::Nullable EncryptionKey; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable LeaseId; Azure::Core::Nullable IfModifiedSince; @@ -5305,7 +5296,8 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.EncryptionKeySha256.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySha256.GetValue()); + request.AddHeader( + "x-ms-encryption-key-sha256", Base64Encode(options.EncryptionKeySha256.GetValue())); } if (options.EncryptionAlgorithm.HasValue()) { @@ -5350,18 +5342,24 @@ namespace Azure { namespace Storage { namespace Blobs { response.BodyStream = httpResponse.GetBodyStream(); response.ETag = httpResponse.GetHeaders().at("etag"); response.LastModified = httpResponse.GetHeaders().at("last-modified"); - auto response_transactional_content_md5_iterator - = httpResponse.GetHeaders().find("content-md5"); - if (response_transactional_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.TransactionalContentMd5 = response_transactional_content_md5_iterator->second; - } - auto response_transactional_content_crc64_iterator - = httpResponse.GetHeaders().find("x-ms-content-crc64"); - if (response_transactional_content_crc64_iterator != httpResponse.GetHeaders().end()) - { - response.TransactionalContentCrc64 - = response_transactional_content_crc64_iterator->second; + const auto& headers = httpResponse.GetHeaders(); + auto content_md5_iterator = headers.find("Content-MD5"); + if (content_md5_iterator != headers.end()) + { + ContentHash hash; + hash.Algorithm = HashAlgorithm::Md5; + hash.Value = Base64Decode(content_md5_iterator->second); + response.TransactionalContentHash = std::move(hash); + } + auto x_ms_content_crc64_iterator = headers.find("x-ms-content-crc64"); + if (x_ms_content_crc64_iterator != headers.end()) + { + ContentHash hash; + hash.Algorithm = HashAlgorithm::Crc64; + hash.Value = Base64Decode(x_ms_content_crc64_iterator->second); + response.TransactionalContentHash = std::move(hash); + } } auto response_http_headers_content_type_iterator = httpResponse.GetHeaders().find("content-type"); @@ -5394,13 +5392,14 @@ namespace Azure { namespace Storage { namespace Blobs { = httpResponse.GetHeaders().find("content-md5"); if (response_http_headers_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.HttpHeaders.ContentMd5 = response_http_headers_content_md5_iterator->second; + response.HttpHeaders.ContentMd5 + = Base64Decode(response_http_headers_content_md5_iterator->second); } auto x_ms_blob_content_md5_iterator = httpResponse.GetHeaders().find("x-ms-blob-content-md5"); if (x_ms_blob_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.HttpHeaders.ContentMd5 = x_ms_blob_content_md5_iterator->second; + response.HttpHeaders.ContentMd5 = Base64Decode(x_ms_blob_content_md5_iterator->second); } auto response_http_headers_content_disposition_iterator = httpResponse.GetHeaders().find("content-disposition"); @@ -5425,7 +5424,8 @@ namespace Azure { namespace Storage { namespace Blobs { = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySha256 = response_encryption_key_sha256_iterator->second; + response.EncryptionKeySha256 + = Base64Decode(response_encryption_key_sha256_iterator->second); } auto response_encryption_scope_iterator = httpResponse.GetHeaders().find("x-ms-encryption-scope"); @@ -5700,7 +5700,7 @@ namespace Azure { namespace Storage { namespace Blobs { { Azure::Core::Nullable Timeout; Azure::Core::Nullable EncryptionKey; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable LeaseId; Azure::Core::Nullable IfModifiedSince; @@ -5730,7 +5730,8 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.EncryptionKeySha256.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySha256.GetValue()); + request.AddHeader( + "x-ms-encryption-key-sha256", Base64Encode(options.EncryptionKeySha256.GetValue())); } if (options.EncryptionAlgorithm.HasValue()) { @@ -5842,13 +5843,14 @@ namespace Azure { namespace Storage { namespace Blobs { = httpResponse.GetHeaders().find("content-md5"); if (response_http_headers_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.HttpHeaders.ContentMd5 = response_http_headers_content_md5_iterator->second; + response.HttpHeaders.ContentMd5 + = Base64Decode(response_http_headers_content_md5_iterator->second); } auto x_ms_blob_content_md5_iterator = httpResponse.GetHeaders().find("x-ms-blob-content-md5"); if (x_ms_blob_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.HttpHeaders.ContentMd5 = x_ms_blob_content_md5_iterator->second; + response.HttpHeaders.ContentMd5 = Base64Decode(x_ms_blob_content_md5_iterator->second); } auto response_http_headers_content_disposition_iterator = httpResponse.GetHeaders().find("content-disposition"); @@ -5885,7 +5887,8 @@ namespace Azure { namespace Storage { namespace Blobs { = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySha256 = response_encryption_key_sha256_iterator->second; + response.EncryptionKeySha256 + = Base64Decode(response_encryption_key_sha256_iterator->second); } auto response_encryption_scope_iterator = httpResponse.GetHeaders().find("x-ms-encryption-scope"); @@ -6034,9 +6037,10 @@ namespace Azure { namespace Storage { namespace Blobs { { request.AddHeader("x-ms-blob-cache-control", options.HttpHeaders.CacheControl); } - if (!options.HttpHeaders.ContentMd5.empty()) + if (!Base64Encode(options.HttpHeaders.ContentMd5).empty()) { - request.AddHeader("x-ms-blob-content-md5", options.HttpHeaders.ContentMd5); + request.AddHeader( + "x-ms-blob-content-md5", Base64Encode(options.HttpHeaders.ContentMd5)); } if (!options.HttpHeaders.ContentDisposition.empty()) { @@ -6094,7 +6098,7 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable Timeout; Storage::Metadata Metadata; Azure::Core::Nullable EncryptionKey; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; Azure::Core::Nullable LeaseId; @@ -6131,7 +6135,8 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.EncryptionKeySha256.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySha256.GetValue()); + request.AddHeader( + "x-ms-encryption-key-sha256", Base64Encode(options.EncryptionKeySha256.GetValue())); } if (options.EncryptionAlgorithm.HasValue()) { @@ -6429,7 +6434,7 @@ namespace Azure { namespace Storage { namespace Blobs { Storage::Metadata Metadata; Azure::Core::Nullable LeaseId; Azure::Core::Nullable EncryptionKey; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; Azure::Core::Nullable IfModifiedSince; @@ -6461,7 +6466,8 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.EncryptionKeySha256.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySha256.GetValue()); + request.AddHeader( + "x-ms-encryption-key-sha256", Base64Encode(options.EncryptionKeySha256.GetValue())); } if (options.EncryptionAlgorithm.HasValue()) { @@ -6523,7 +6529,8 @@ namespace Azure { namespace Storage { namespace Blobs { = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySha256 = response_encryption_key_sha256_iterator->second; + response.EncryptionKeySha256 + = Base64Decode(response_encryption_key_sha256_iterator->second); } auto response_encryption_scope_iterator = httpResponse.GetHeaders().find("x-ms-encryption-scope"); @@ -7123,14 +7130,13 @@ namespace Azure { namespace Storage { namespace Blobs { struct UploadBlockBlobOptions { Azure::Core::Nullable Timeout; - Azure::Core::Nullable TransactionalContentMd5; - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; BlobHttpHeaders HttpHeaders; Storage::Metadata Metadata; Azure::Core::Nullable LeaseId; Azure::Core::Nullable Tier; Azure::Core::Nullable EncryptionKey; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; Azure::Core::Nullable IfModifiedSince; @@ -7163,7 +7169,8 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.EncryptionKeySha256.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySha256.GetValue()); + request.AddHeader( + "x-ms-encryption-key-sha256", Base64Encode(options.EncryptionKeySha256.GetValue())); } if (options.EncryptionAlgorithm.HasValue()) { @@ -7175,13 +7182,19 @@ namespace Azure { namespace Storage { namespace Blobs { { request.AddHeader("x-ms-encryption-scope", options.EncryptionScope.GetValue()); } - if (options.TransactionalContentMd5.HasValue()) + if (options.TransactionalContentHash.HasValue()) { - request.AddHeader("Content-MD5", options.TransactionalContentMd5.GetValue()); - } - if (options.TransactionalContentCrc64.HasValue()) - { - request.AddHeader("x-ms-content-crc64", options.TransactionalContentCrc64.GetValue()); + if (options.TransactionalContentHash.GetValue().Algorithm == HashAlgorithm::Md5) + { + request.AddHeader( + "Content-MD5", Base64Encode(options.TransactionalContentHash.GetValue().Value)); + } + else if (options.TransactionalContentHash.GetValue().Algorithm == HashAlgorithm::Crc64) + { + request.AddHeader( + "x-ms-content-crc64", + Base64Encode(options.TransactionalContentHash.GetValue().Value)); + } } if (!options.HttpHeaders.ContentType.empty()) { @@ -7199,9 +7212,10 @@ namespace Azure { namespace Storage { namespace Blobs { { request.AddHeader("x-ms-blob-cache-control", options.HttpHeaders.CacheControl); } - if (!options.HttpHeaders.ContentMd5.empty()) + if (!Base64Encode(options.HttpHeaders.ContentMd5).empty()) { - request.AddHeader("x-ms-blob-content-md5", options.HttpHeaders.ContentMd5); + request.AddHeader( + "x-ms-blob-content-md5", Base64Encode(options.HttpHeaders.ContentMd5)); } if (!options.HttpHeaders.ContentDisposition.empty()) { @@ -7253,18 +7267,24 @@ namespace Azure { namespace Storage { namespace Blobs { } response.ETag = httpResponse.GetHeaders().at("etag"); response.LastModified = httpResponse.GetHeaders().at("last-modified"); - auto response_transactional_content_md5_iterator - = httpResponse.GetHeaders().find("content-md5"); - if (response_transactional_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.TransactionalContentMd5 = response_transactional_content_md5_iterator->second; - } - auto response_transactional_content_crc64_iterator - = httpResponse.GetHeaders().find("x-ms-content-crc64"); - if (response_transactional_content_crc64_iterator != httpResponse.GetHeaders().end()) - { - response.TransactionalContentCrc64 - = response_transactional_content_crc64_iterator->second; + const auto& headers = httpResponse.GetHeaders(); + auto content_md5_iterator = headers.find("Content-MD5"); + if (content_md5_iterator != headers.end()) + { + ContentHash hash; + hash.Algorithm = HashAlgorithm::Md5; + hash.Value = Base64Decode(content_md5_iterator->second); + response.TransactionalContentHash = std::move(hash); + } + auto x_ms_content_crc64_iterator = headers.find("x-ms-content-crc64"); + if (x_ms_content_crc64_iterator != headers.end()) + { + ContentHash hash; + hash.Algorithm = HashAlgorithm::Crc64; + hash.Value = Base64Decode(x_ms_content_crc64_iterator->second); + response.TransactionalContentHash = std::move(hash); + } } auto response_version_id_iterator = httpResponse.GetHeaders().find("x-ms-version-id"); if (response_version_id_iterator != httpResponse.GetHeaders().end()) @@ -7281,7 +7301,8 @@ namespace Azure { namespace Storage { namespace Blobs { = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySha256 = response_encryption_key_sha256_iterator->second; + response.EncryptionKeySha256 + = Base64Decode(response_encryption_key_sha256_iterator->second); } auto response_encryption_scope_iterator = httpResponse.GetHeaders().find("x-ms-encryption-scope"); @@ -7297,11 +7318,10 @@ namespace Azure { namespace Storage { namespace Blobs { { Azure::Core::Nullable Timeout; std::string BlockId; - Azure::Core::Nullable TransactionalContentMd5; - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; Azure::Core::Nullable LeaseId; Azure::Core::Nullable EncryptionKey; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; }; // struct StageBlockOptions @@ -7326,13 +7346,19 @@ namespace Azure { namespace Storage { namespace Blobs { request.GetUrl().AppendQueryParameter( "timeout", std::to_string(options.Timeout.GetValue())); } - if (options.TransactionalContentMd5.HasValue()) + if (options.TransactionalContentHash.HasValue()) { - request.AddHeader("Content-MD5", options.TransactionalContentMd5.GetValue()); - } - if (options.TransactionalContentCrc64.HasValue()) - { - request.AddHeader("x-ms-content-crc64", options.TransactionalContentCrc64.GetValue()); + if (options.TransactionalContentHash.GetValue().Algorithm == HashAlgorithm::Md5) + { + request.AddHeader( + "Content-MD5", Base64Encode(options.TransactionalContentHash.GetValue().Value)); + } + else if (options.TransactionalContentHash.GetValue().Algorithm == HashAlgorithm::Crc64) + { + request.AddHeader( + "x-ms-content-crc64", + Base64Encode(options.TransactionalContentHash.GetValue().Value)); + } } if (options.LeaseId.HasValue()) { @@ -7344,7 +7370,8 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.EncryptionKeySha256.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySha256.GetValue()); + request.AddHeader( + "x-ms-encryption-key-sha256", Base64Encode(options.EncryptionKeySha256.GetValue())); } if (options.EncryptionAlgorithm.HasValue()) { @@ -7366,18 +7393,24 @@ namespace Azure { namespace Storage { namespace Blobs { { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } - auto response_transactional_content_md5_iterator - = httpResponse.GetHeaders().find("content-md5"); - if (response_transactional_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.TransactionalContentMd5 = response_transactional_content_md5_iterator->second; - } - auto response_transactional_content_crc64_iterator - = httpResponse.GetHeaders().find("x-ms-content-crc64"); - if (response_transactional_content_crc64_iterator != httpResponse.GetHeaders().end()) - { - response.TransactionalContentCrc64 - = response_transactional_content_crc64_iterator->second; + const auto& headers = httpResponse.GetHeaders(); + auto content_md5_iterator = headers.find("Content-MD5"); + if (content_md5_iterator != headers.end()) + { + ContentHash hash; + hash.Algorithm = HashAlgorithm::Md5; + hash.Value = Base64Decode(content_md5_iterator->second); + response.TransactionalContentHash = std::move(hash); + } + auto x_ms_content_crc64_iterator = headers.find("x-ms-content-crc64"); + if (x_ms_content_crc64_iterator != headers.end()) + { + ContentHash hash; + hash.Algorithm = HashAlgorithm::Crc64; + hash.Value = Base64Decode(x_ms_content_crc64_iterator->second); + response.TransactionalContentHash = std::move(hash); + } } auto response_server_encrypted_iterator = httpResponse.GetHeaders().find("x-ms-request-server-encrypted"); @@ -7389,7 +7422,8 @@ namespace Azure { namespace Storage { namespace Blobs { = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySha256 = response_encryption_key_sha256_iterator->second; + response.EncryptionKeySha256 + = Base64Decode(response_encryption_key_sha256_iterator->second); } auto response_encryption_scope_iterator = httpResponse.GetHeaders().find("x-ms-encryption-scope"); @@ -7407,11 +7441,10 @@ namespace Azure { namespace Storage { namespace Blobs { std::string BlockId; std::string SourceUri; Azure::Core::Nullable> SourceRange; - Azure::Core::Nullable TransactionalContentMd5; - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; Azure::Core::Nullable LeaseId; Azure::Core::Nullable EncryptionKey; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; Azure::Core::Nullable SourceIfModifiedSince; @@ -7454,15 +7487,20 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-source_range", "bytes=" + std::to_string(startOffset) + "-"); } } - if (options.TransactionalContentMd5.HasValue()) + if (options.TransactionalContentHash.HasValue()) { - request.AddHeader( - "x-ms-source-content-md5", options.TransactionalContentMd5.GetValue()); - } - if (options.TransactionalContentCrc64.HasValue()) - { - request.AddHeader( - "x-ms-source-content-crc64", options.TransactionalContentCrc64.GetValue()); + if (options.TransactionalContentHash.GetValue().Algorithm == HashAlgorithm::Md5) + { + request.AddHeader( + "x-ms-source-content-md5", + Base64Encode(options.TransactionalContentHash.GetValue().Value)); + } + else if (options.TransactionalContentHash.GetValue().Algorithm == HashAlgorithm::Crc64) + { + request.AddHeader( + "x-ms-source-content-crc64", + Base64Encode(options.TransactionalContentHash.GetValue().Value)); + } } if (options.LeaseId.HasValue()) { @@ -7474,7 +7512,8 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.EncryptionKeySha256.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySha256.GetValue()); + request.AddHeader( + "x-ms-encryption-key-sha256", Base64Encode(options.EncryptionKeySha256.GetValue())); } if (options.EncryptionAlgorithm.HasValue()) { @@ -7514,18 +7553,24 @@ namespace Azure { namespace Storage { namespace Blobs { { throw StorageException::CreateFromResponse(std::move(pHttpResponse)); } - auto response_transactional_content_md5_iterator - = httpResponse.GetHeaders().find("content-md5"); - if (response_transactional_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.TransactionalContentMd5 = response_transactional_content_md5_iterator->second; - } - auto response_transactional_content_crc64_iterator - = httpResponse.GetHeaders().find("x-ms-content-crc64"); - if (response_transactional_content_crc64_iterator != httpResponse.GetHeaders().end()) - { - response.TransactionalContentCrc64 - = response_transactional_content_crc64_iterator->second; + const auto& headers = httpResponse.GetHeaders(); + auto content_md5_iterator = headers.find("Content-MD5"); + if (content_md5_iterator != headers.end()) + { + ContentHash hash; + hash.Algorithm = HashAlgorithm::Md5; + hash.Value = Base64Decode(content_md5_iterator->second); + response.TransactionalContentHash = std::move(hash); + } + auto x_ms_content_crc64_iterator = headers.find("x-ms-content-crc64"); + if (x_ms_content_crc64_iterator != headers.end()) + { + ContentHash hash; + hash.Algorithm = HashAlgorithm::Crc64; + hash.Value = Base64Decode(x_ms_content_crc64_iterator->second); + response.TransactionalContentHash = std::move(hash); + } } auto response_server_encrypted_iterator = httpResponse.GetHeaders().find("x-ms-request-server-encrypted"); @@ -7537,7 +7582,8 @@ namespace Azure { namespace Storage { namespace Blobs { = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySha256 = response_encryption_key_sha256_iterator->second; + response.EncryptionKeySha256 + = Base64Decode(response_encryption_key_sha256_iterator->second); } auto response_encryption_scope_iterator = httpResponse.GetHeaders().find("x-ms-encryption-scope"); @@ -7557,7 +7603,7 @@ namespace Azure { namespace Storage { namespace Blobs { Storage::Metadata Metadata; Azure::Core::Nullable LeaseId; Azure::Core::Nullable EncryptionKey; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; Azure::Core::Nullable IfModifiedSince; @@ -7610,9 +7656,10 @@ namespace Azure { namespace Storage { namespace Blobs { { request.AddHeader("x-ms-blob-cache-control", options.HttpHeaders.CacheControl); } - if (!options.HttpHeaders.ContentMd5.empty()) + if (!Base64Encode(options.HttpHeaders.ContentMd5).empty()) { - request.AddHeader("x-ms-blob-content-md5", options.HttpHeaders.ContentMd5); + request.AddHeader( + "x-ms-blob-content-md5", Base64Encode(options.HttpHeaders.ContentMd5)); } if (!options.HttpHeaders.ContentDisposition.empty()) { @@ -7633,7 +7680,8 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.EncryptionKeySha256.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySha256.GetValue()); + request.AddHeader( + "x-ms-encryption-key-sha256", Base64Encode(options.EncryptionKeySha256.GetValue())); } if (options.EncryptionAlgorithm.HasValue()) { @@ -7696,7 +7744,8 @@ namespace Azure { namespace Storage { namespace Blobs { = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySha256 = response_encryption_key_sha256_iterator->second; + response.EncryptionKeySha256 + = Base64Decode(response_encryption_key_sha256_iterator->second); } auto response_encryption_scope_iterator = httpResponse.GetHeaders().find("x-ms-encryption-scope"); @@ -7932,7 +7981,7 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable LeaseId; Azure::Core::Nullable Tier; Azure::Core::Nullable EncryptionKey; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; Azure::Core::Nullable IfModifiedSince; @@ -7973,9 +8022,10 @@ namespace Azure { namespace Storage { namespace Blobs { { request.AddHeader("x-ms-blob-cache-control", options.HttpHeaders.CacheControl); } - if (!options.HttpHeaders.ContentMd5.empty()) + if (!Base64Encode(options.HttpHeaders.ContentMd5).empty()) { - request.AddHeader("x-ms-blob-content-md5", options.HttpHeaders.ContentMd5); + request.AddHeader( + "x-ms-blob-content-md5", Base64Encode(options.HttpHeaders.ContentMd5)); } if (!options.HttpHeaders.ContentDisposition.empty()) { @@ -8007,7 +8057,8 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.EncryptionKeySha256.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySha256.GetValue()); + request.AddHeader( + "x-ms-encryption-key-sha256", Base64Encode(options.EncryptionKeySha256.GetValue())); } if (options.EncryptionAlgorithm.HasValue()) { @@ -8066,7 +8117,8 @@ namespace Azure { namespace Storage { namespace Blobs { = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySha256 = response_encryption_key_sha256_iterator->second; + response.EncryptionKeySha256 + = Base64Decode(response_encryption_key_sha256_iterator->second); } auto response_encryption_scope_iterator = httpResponse.GetHeaders().find("x-ms-encryption-scope"); @@ -8082,14 +8134,13 @@ namespace Azure { namespace Storage { namespace Blobs { { Azure::Core::Nullable Timeout; std::pair Range; - Azure::Core::Nullable TransactionalContentMd5; - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; Azure::Core::Nullable LeaseId; Azure::Core::Nullable IfSequenceNumberLessThanOrEqualTo; Azure::Core::Nullable IfSequenceNumberLessThan; Azure::Core::Nullable IfSequenceNumberEqualTo; Azure::Core::Nullable EncryptionKey; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; Azure::Core::Nullable IfModifiedSince; @@ -8121,13 +8172,19 @@ namespace Azure { namespace Storage { namespace Blobs { "x-ms-range", "bytes=" + std::to_string(options.Range.first) + "-" + std::to_string(options.Range.second)); - if (options.TransactionalContentMd5.HasValue()) + if (options.TransactionalContentHash.HasValue()) { - request.AddHeader("Content-MD5", options.TransactionalContentMd5.GetValue()); - } - if (options.TransactionalContentCrc64.HasValue()) - { - request.AddHeader("x-ms-content-crc64", options.TransactionalContentCrc64.GetValue()); + if (options.TransactionalContentHash.GetValue().Algorithm == HashAlgorithm::Md5) + { + request.AddHeader( + "Content-MD5", Base64Encode(options.TransactionalContentHash.GetValue().Value)); + } + else if (options.TransactionalContentHash.GetValue().Algorithm == HashAlgorithm::Crc64) + { + request.AddHeader( + "x-ms-content-crc64", + Base64Encode(options.TransactionalContentHash.GetValue().Value)); + } } request.AddHeader("x-ms-page-write", "update"); if (options.LeaseId.HasValue()) @@ -8158,7 +8215,8 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.EncryptionKeySha256.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySha256.GetValue()); + request.AddHeader( + "x-ms-encryption-key-sha256", Base64Encode(options.EncryptionKeySha256.GetValue())); } if (options.EncryptionAlgorithm.HasValue()) { @@ -8202,18 +8260,24 @@ namespace Azure { namespace Storage { namespace Blobs { } response.ETag = httpResponse.GetHeaders().at("etag"); response.LastModified = httpResponse.GetHeaders().at("last-modified"); - auto response_transactional_content_md5_iterator - = httpResponse.GetHeaders().find("content-md5"); - if (response_transactional_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.TransactionalContentMd5 = response_transactional_content_md5_iterator->second; - } - auto response_transactional_content_crc64_iterator - = httpResponse.GetHeaders().find("x-ms-content-crc64"); - if (response_transactional_content_crc64_iterator != httpResponse.GetHeaders().end()) - { - response.TransactionalContentCrc64 - = response_transactional_content_crc64_iterator->second; + const auto& headers = httpResponse.GetHeaders(); + auto content_md5_iterator = headers.find("Content-MD5"); + if (content_md5_iterator != headers.end()) + { + ContentHash hash; + hash.Algorithm = HashAlgorithm::Md5; + hash.Value = Base64Decode(content_md5_iterator->second); + response.TransactionalContentHash = std::move(hash); + } + auto x_ms_content_crc64_iterator = headers.find("x-ms-content-crc64"); + if (x_ms_content_crc64_iterator != headers.end()) + { + ContentHash hash; + hash.Algorithm = HashAlgorithm::Crc64; + hash.Value = Base64Decode(x_ms_content_crc64_iterator->second); + response.TransactionalContentHash = std::move(hash); + } } response.SequenceNumber = std::stoll(httpResponse.GetHeaders().at("x-ms-blob-sequence-number")); @@ -8227,7 +8291,8 @@ namespace Azure { namespace Storage { namespace Blobs { = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySha256 = response_encryption_key_sha256_iterator->second; + response.EncryptionKeySha256 + = Base64Decode(response_encryption_key_sha256_iterator->second); } auto response_encryption_scope_iterator = httpResponse.GetHeaders().find("x-ms-encryption-scope"); @@ -8245,14 +8310,13 @@ namespace Azure { namespace Storage { namespace Blobs { std::string SourceUri; std::pair SourceRange; std::pair Range; - Azure::Core::Nullable TransactionalContentMd5; - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; Azure::Core::Nullable LeaseId; Azure::Core::Nullable IfSequenceNumberLessThanOrEqualTo; Azure::Core::Nullable IfSequenceNumberLessThan; Azure::Core::Nullable IfSequenceNumberEqualTo; Azure::Core::Nullable EncryptionKey; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; Azure::Core::Nullable IfModifiedSince; @@ -8287,15 +8351,20 @@ namespace Azure { namespace Storage { namespace Blobs { "x-ms-source-range", "bytes=" + std::to_string(options.SourceRange.first) + "-" + std::to_string(options.SourceRange.second)); - if (options.TransactionalContentMd5.HasValue()) + if (options.TransactionalContentHash.HasValue()) { - request.AddHeader( - "x-ms-source-content-md5", options.TransactionalContentMd5.GetValue()); - } - if (options.TransactionalContentCrc64.HasValue()) - { - request.AddHeader( - "x-ms-source-content-crc64", options.TransactionalContentCrc64.GetValue()); + if (options.TransactionalContentHash.GetValue().Algorithm == HashAlgorithm::Md5) + { + request.AddHeader( + "x-ms-source-content-md5", + Base64Encode(options.TransactionalContentHash.GetValue().Value)); + } + else if (options.TransactionalContentHash.GetValue().Algorithm == HashAlgorithm::Crc64) + { + request.AddHeader( + "x-ms-source-content-crc64", + Base64Encode(options.TransactionalContentHash.GetValue().Value)); + } } request.AddHeader("x-ms-page-write", "update"); if (options.LeaseId.HasValue()) @@ -8326,7 +8395,8 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.EncryptionKeySha256.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySha256.GetValue()); + request.AddHeader( + "x-ms-encryption-key-sha256", Base64Encode(options.EncryptionKeySha256.GetValue())); } if (options.EncryptionAlgorithm.HasValue()) { @@ -8370,18 +8440,24 @@ namespace Azure { namespace Storage { namespace Blobs { } response.ETag = httpResponse.GetHeaders().at("etag"); response.LastModified = httpResponse.GetHeaders().at("last-modified"); - auto response_transactional_content_md5_iterator - = httpResponse.GetHeaders().find("content-md5"); - if (response_transactional_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.TransactionalContentMd5 = response_transactional_content_md5_iterator->second; - } - auto response_transactional_content_crc64_iterator - = httpResponse.GetHeaders().find("x-ms-content-crc64"); - if (response_transactional_content_crc64_iterator != httpResponse.GetHeaders().end()) - { - response.TransactionalContentCrc64 - = response_transactional_content_crc64_iterator->second; + const auto& headers = httpResponse.GetHeaders(); + auto content_md5_iterator = headers.find("Content-MD5"); + if (content_md5_iterator != headers.end()) + { + ContentHash hash; + hash.Algorithm = HashAlgorithm::Md5; + hash.Value = Base64Decode(content_md5_iterator->second); + response.TransactionalContentHash = std::move(hash); + } + auto x_ms_content_crc64_iterator = headers.find("x-ms-content-crc64"); + if (x_ms_content_crc64_iterator != headers.end()) + { + ContentHash hash; + hash.Algorithm = HashAlgorithm::Crc64; + hash.Value = Base64Decode(x_ms_content_crc64_iterator->second); + response.TransactionalContentHash = std::move(hash); + } } response.SequenceNumber = std::stoll(httpResponse.GetHeaders().at("x-ms-blob-sequence-number")); @@ -8395,7 +8471,8 @@ namespace Azure { namespace Storage { namespace Blobs { = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySha256 = response_encryption_key_sha256_iterator->second; + response.EncryptionKeySha256 + = Base64Decode(response_encryption_key_sha256_iterator->second); } auto response_encryption_scope_iterator = httpResponse.GetHeaders().find("x-ms-encryption-scope"); @@ -8416,7 +8493,7 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable IfSequenceNumberLessThan; Azure::Core::Nullable IfSequenceNumberEqualTo; Azure::Core::Nullable EncryptionKey; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; Azure::Core::Nullable IfModifiedSince; @@ -8475,7 +8552,8 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.EncryptionKeySha256.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySha256.GetValue()); + request.AddHeader( + "x-ms-encryption-key-sha256", Base64Encode(options.EncryptionKeySha256.GetValue())); } if (options.EncryptionAlgorithm.HasValue()) { @@ -8531,7 +8609,8 @@ namespace Azure { namespace Storage { namespace Blobs { = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySha256 = response_encryption_key_sha256_iterator->second; + response.EncryptionKeySha256 + = Base64Decode(response_encryption_key_sha256_iterator->second); } auto response_encryption_scope_iterator = httpResponse.GetHeaders().find("x-ms-encryption-scope"); @@ -8552,7 +8631,7 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable IfSequenceNumberLessThan; Azure::Core::Nullable IfSequenceNumberEqualTo; Azure::Core::Nullable EncryptionKey; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; Azure::Core::Nullable IfModifiedSince; @@ -8607,7 +8686,8 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.EncryptionKeySha256.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySha256.GetValue()); + request.AddHeader( + "x-ms-encryption-key-sha256", Base64Encode(options.EncryptionKeySha256.GetValue())); } if (options.EncryptionAlgorithm.HasValue()) { @@ -9016,7 +9096,7 @@ namespace Azure { namespace Storage { namespace Blobs { Storage::Metadata Metadata; Azure::Core::Nullable LeaseId; Azure::Core::Nullable EncryptionKey; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; Azure::Core::Nullable IfModifiedSince; @@ -9057,9 +9137,10 @@ namespace Azure { namespace Storage { namespace Blobs { { request.AddHeader("x-ms-blob-cache-control", options.HttpHeaders.CacheControl); } - if (!options.HttpHeaders.ContentMd5.empty()) + if (!Base64Encode(options.HttpHeaders.ContentMd5).empty()) { - request.AddHeader("x-ms-blob-content-md5", options.HttpHeaders.ContentMd5); + request.AddHeader( + "x-ms-blob-content-md5", Base64Encode(options.HttpHeaders.ContentMd5)); } if (!options.HttpHeaders.ContentDisposition.empty()) { @@ -9081,7 +9162,8 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.EncryptionKeySha256.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySha256.GetValue()); + request.AddHeader( + "x-ms-encryption-key-sha256", Base64Encode(options.EncryptionKeySha256.GetValue())); } if (options.EncryptionAlgorithm.HasValue()) { @@ -9140,7 +9222,8 @@ namespace Azure { namespace Storage { namespace Blobs { = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySha256 = response_encryption_key_sha256_iterator->second; + response.EncryptionKeySha256 + = Base64Decode(response_encryption_key_sha256_iterator->second); } auto response_encryption_scope_iterator = httpResponse.GetHeaders().find("x-ms-encryption-scope"); @@ -9155,13 +9238,12 @@ namespace Azure { namespace Storage { namespace Blobs { struct AppendBlockOptions { Azure::Core::Nullable Timeout; - Azure::Core::Nullable TransactionalContentMd5; - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; Azure::Core::Nullable LeaseId; Azure::Core::Nullable MaxSize; Azure::Core::Nullable AppendPosition; Azure::Core::Nullable EncryptionKey; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; Azure::Core::Nullable IfModifiedSince; @@ -9189,13 +9271,19 @@ namespace Azure { namespace Storage { namespace Blobs { request.GetUrl().AppendQueryParameter( "timeout", std::to_string(options.Timeout.GetValue())); } - if (options.TransactionalContentMd5.HasValue()) + if (options.TransactionalContentHash.HasValue()) { - request.AddHeader("Content-MD5", options.TransactionalContentMd5.GetValue()); - } - if (options.TransactionalContentCrc64.HasValue()) - { - request.AddHeader("x-ms-content-crc64", options.TransactionalContentCrc64.GetValue()); + if (options.TransactionalContentHash.GetValue().Algorithm == HashAlgorithm::Md5) + { + request.AddHeader( + "Content-MD5", Base64Encode(options.TransactionalContentHash.GetValue().Value)); + } + else if (options.TransactionalContentHash.GetValue().Algorithm == HashAlgorithm::Crc64) + { + request.AddHeader( + "x-ms-content-crc64", + Base64Encode(options.TransactionalContentHash.GetValue().Value)); + } } if (options.LeaseId.HasValue()) { @@ -9217,7 +9305,8 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.EncryptionKeySha256.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySha256.GetValue()); + request.AddHeader( + "x-ms-encryption-key-sha256", Base64Encode(options.EncryptionKeySha256.GetValue())); } if (options.EncryptionAlgorithm.HasValue()) { @@ -9261,18 +9350,24 @@ namespace Azure { namespace Storage { namespace Blobs { } response.ETag = httpResponse.GetHeaders().at("etag"); response.LastModified = httpResponse.GetHeaders().at("last-modified"); - auto response_transactional_content_md5_iterator - = httpResponse.GetHeaders().find("content-md5"); - if (response_transactional_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.TransactionalContentMd5 = response_transactional_content_md5_iterator->second; - } - auto response_transactional_content_crc64_iterator - = httpResponse.GetHeaders().find("x-ms-content-crc64"); - if (response_transactional_content_crc64_iterator != httpResponse.GetHeaders().end()) - { - response.TransactionalContentCrc64 - = response_transactional_content_crc64_iterator->second; + const auto& headers = httpResponse.GetHeaders(); + auto content_md5_iterator = headers.find("Content-MD5"); + if (content_md5_iterator != headers.end()) + { + ContentHash hash; + hash.Algorithm = HashAlgorithm::Md5; + hash.Value = Base64Decode(content_md5_iterator->second); + response.TransactionalContentHash = std::move(hash); + } + auto x_ms_content_crc64_iterator = headers.find("x-ms-content-crc64"); + if (x_ms_content_crc64_iterator != headers.end()) + { + ContentHash hash; + hash.Algorithm = HashAlgorithm::Crc64; + hash.Value = Base64Decode(x_ms_content_crc64_iterator->second); + response.TransactionalContentHash = std::move(hash); + } } response.AppendOffset = std::stoll(httpResponse.GetHeaders().at("x-ms-blob-append-offset")); @@ -9288,7 +9383,8 @@ namespace Azure { namespace Storage { namespace Blobs { = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySha256 = response_encryption_key_sha256_iterator->second; + response.EncryptionKeySha256 + = Base64Decode(response_encryption_key_sha256_iterator->second); } auto response_encryption_scope_iterator = httpResponse.GetHeaders().find("x-ms-encryption-scope"); @@ -9305,13 +9401,12 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable Timeout; std::string SourceUri; Azure::Core::Nullable> SourceRange; - Azure::Core::Nullable TransactionalContentMd5; - Azure::Core::Nullable TransactionalContentCrc64; + Azure::Core::Nullable TransactionalContentHash; Azure::Core::Nullable LeaseId; Azure::Core::Nullable MaxSize; Azure::Core::Nullable AppendPosition; Azure::Core::Nullable EncryptionKey; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; Azure::Core::Nullable EncryptionScope; Azure::Core::Nullable IfModifiedSince; @@ -9353,15 +9448,20 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-source-range", "bytes=" + std::to_string(startOffset) + "-"); } } - if (options.TransactionalContentMd5.HasValue()) + if (options.TransactionalContentHash.HasValue()) { - request.AddHeader( - "x-ms-source-content-md5", options.TransactionalContentMd5.GetValue()); - } - if (options.TransactionalContentCrc64.HasValue()) - { - request.AddHeader( - "x-ms-source-content-crc64", options.TransactionalContentCrc64.GetValue()); + if (options.TransactionalContentHash.GetValue().Algorithm == HashAlgorithm::Md5) + { + request.AddHeader( + "x-ms-source-content-md5", + Base64Encode(options.TransactionalContentHash.GetValue().Value)); + } + else if (options.TransactionalContentHash.GetValue().Algorithm == HashAlgorithm::Crc64) + { + request.AddHeader( + "x-ms-source-content-crc64", + Base64Encode(options.TransactionalContentHash.GetValue().Value)); + } } if (options.LeaseId.HasValue()) { @@ -9383,7 +9483,8 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.EncryptionKeySha256.HasValue()) { - request.AddHeader("x-ms-encryption-key-sha256", options.EncryptionKeySha256.GetValue()); + request.AddHeader( + "x-ms-encryption-key-sha256", Base64Encode(options.EncryptionKeySha256.GetValue())); } if (options.EncryptionAlgorithm.HasValue()) { @@ -9427,18 +9528,24 @@ namespace Azure { namespace Storage { namespace Blobs { } response.ETag = httpResponse.GetHeaders().at("etag"); response.LastModified = httpResponse.GetHeaders().at("last-modified"); - auto response_transactional_content_md5_iterator - = httpResponse.GetHeaders().find("content-md5"); - if (response_transactional_content_md5_iterator != httpResponse.GetHeaders().end()) { - response.TransactionalContentMd5 = response_transactional_content_md5_iterator->second; - } - auto response_transactional_content_crc64_iterator - = httpResponse.GetHeaders().find("x-ms-content-crc64"); - if (response_transactional_content_crc64_iterator != httpResponse.GetHeaders().end()) - { - response.TransactionalContentCrc64 - = response_transactional_content_crc64_iterator->second; + const auto& headers = httpResponse.GetHeaders(); + auto content_md5_iterator = headers.find("Content-MD5"); + if (content_md5_iterator != headers.end()) + { + ContentHash hash; + hash.Algorithm = HashAlgorithm::Md5; + hash.Value = Base64Decode(content_md5_iterator->second); + response.TransactionalContentHash = std::move(hash); + } + auto x_ms_content_crc64_iterator = headers.find("x-ms-content-crc64"); + if (x_ms_content_crc64_iterator != headers.end()) + { + ContentHash hash; + hash.Algorithm = HashAlgorithm::Crc64; + hash.Value = Base64Decode(x_ms_content_crc64_iterator->second); + response.TransactionalContentHash = std::move(hash); + } } response.AppendOffset = std::stoll(httpResponse.GetHeaders().at("x-ms-blob-append-offset")); @@ -9454,7 +9561,8 @@ namespace Azure { namespace Storage { namespace Blobs { = httpResponse.GetHeaders().find("x-ms-encryption-key-sha256"); if (response_encryption_key_sha256_iterator != httpResponse.GetHeaders().end()) { - response.EncryptionKeySha256 = response_encryption_key_sha256_iterator->second; + response.EncryptionKeySha256 + = Base64Decode(response_encryption_key_sha256_iterator->second); } auto response_encryption_scope_iterator = httpResponse.GetHeaders().find("x-ms-encryption-scope"); diff --git a/sdk/storage/azure-storage-blobs/src/append_blob_client.cpp b/sdk/storage/azure-storage-blobs/src/append_blob_client.cpp index 2a180e97f..5b5ad80cd 100644 --- a/sdk/storage/azure-storage-blobs/src/append_blob_client.cpp +++ b/sdk/storage/azure-storage-blobs/src/append_blob_client.cpp @@ -121,8 +121,7 @@ namespace Azure { namespace Storage { namespace Blobs { const AppendBlockOptions& options) const { Details::BlobRestClient::AppendBlob::AppendBlockOptions protocolLayerOptions; - protocolLayerOptions.TransactionalContentMd5 = options.TransactionalContentMd5; - protocolLayerOptions.TransactionalContentCrc64 = options.TransactionalContentCrc64; + protocolLayerOptions.TransactionalContentHash = options.TransactionalContentHash; protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId; protocolLayerOptions.MaxSize = options.AccessConditions.IfMaxSizeLessThanOrEqual; protocolLayerOptions.AppendPosition = options.AccessConditions.IfAppendPositionEqual; @@ -161,8 +160,7 @@ namespace Azure { namespace Storage { namespace Blobs { std::numeric_limits< std::remove_reference_t>::max()); } - protocolLayerOptions.TransactionalContentMd5 = options.TransactionalContentMd5; - protocolLayerOptions.TransactionalContentCrc64 = options.TransactionalContentCrc64; + protocolLayerOptions.TransactionalContentHash = options.TransactionalContentHash; protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId; protocolLayerOptions.MaxSize = options.AccessConditions.IfMaxSizeLessThanOrEqual; protocolLayerOptions.AppendPosition = options.AccessConditions.IfAppendPositionEqual; diff --git a/sdk/storage/azure-storage-blobs/src/blob_sas_builder.cpp b/sdk/storage/azure-storage-blobs/src/blob_sas_builder.cpp index 5f177ea08..0efc035de 100644 --- a/sdk/storage/azure-storage-blobs/src/blob_sas_builder.cpp +++ b/sdk/storage/azure-storage-blobs/src/blob_sas_builder.cpp @@ -134,8 +134,9 @@ namespace Azure { namespace Storage { namespace Sas { + CacheControl + "\n" + ContentDisposition + "\n" + ContentEncoding + "\n" + ContentLanguage + "\n" + ContentType; - std::string signature = Base64Encode( - Storage::Details::HmacSha256(stringToSign, Base64Decode(credential.GetAccountKey()))); + std::string signature = Base64Encode(Storage::Details::HmacSha256( + std::vector(stringToSign.begin(), stringToSign.end()), + Base64Decode(credential.GetAccountKey()))); Azure::Core::Http::Url builder; builder.AppendQueryParameter( @@ -225,8 +226,9 @@ namespace Azure { namespace Storage { namespace Sas { + CacheControl + "\n" + ContentDisposition + "\n" + ContentEncoding + "\n" + ContentLanguage + "\n" + ContentType; - std::string signature = Base64Encode( - Storage::Details::HmacSha256(stringToSign, Base64Decode(userDelegationKey.Value))); + std::string signature = Base64Encode(Storage::Details::HmacSha256( + std::vector(stringToSign.begin(), stringToSign.end()), + Base64Decode(userDelegationKey.Value))); Azure::Core::Http::Url builder; builder.AppendQueryParameter( diff --git a/sdk/storage/azure-storage-blobs/src/block_blob_client.cpp b/sdk/storage/azure-storage-blobs/src/block_blob_client.cpp index 5859cfaa5..d012e8bbe 100644 --- a/sdk/storage/azure-storage-blobs/src/block_blob_client.cpp +++ b/sdk/storage/azure-storage-blobs/src/block_blob_client.cpp @@ -81,8 +81,7 @@ namespace Azure { namespace Storage { namespace Blobs { const UploadBlockBlobOptions& options) const { Details::BlobRestClient::BlockBlob::UploadBlockBlobOptions protocolLayerOptions; - protocolLayerOptions.TransactionalContentMd5 = options.TransactionalContentMd5; - protocolLayerOptions.TransactionalContentCrc64 = options.TransactionalContentCrc64; + protocolLayerOptions.TransactionalContentHash = options.TransactionalContentHash; protocolLayerOptions.HttpHeaders = options.HttpHeaders; protocolLayerOptions.Metadata = options.Metadata; protocolLayerOptions.Tier = options.Tier; @@ -269,8 +268,7 @@ namespace Azure { namespace Storage { namespace Blobs { { Details::BlobRestClient::BlockBlob::StageBlockOptions protocolLayerOptions; protocolLayerOptions.BlockId = blockId; - protocolLayerOptions.TransactionalContentMd5 = options.TransactionalContentMd5; - protocolLayerOptions.TransactionalContentCrc64 = options.TransactionalContentCrc64; + protocolLayerOptions.TransactionalContentHash = options.TransactionalContentHash; protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId; if (m_customerProvidedKey.HasValue()) { @@ -304,8 +302,7 @@ namespace Azure { namespace Storage { namespace Blobs { std::numeric_limits< std::remove_reference_t>::max()); } - protocolLayerOptions.TransactionalContentMd5 = options.TransactionalContentMd5; - protocolLayerOptions.TransactionalContentCrc64 = options.TransactionalContentCrc64; + protocolLayerOptions.TransactionalContentHash = options.TransactionalContentHash; protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId; protocolLayerOptions.SourceIfModifiedSince = options.SourceConditions.IfModifiedSince; protocolLayerOptions.SourceIfUnmodifiedSince = options.SourceConditions.IfUnmodifiedSince; diff --git a/sdk/storage/azure-storage-blobs/src/page_blob_client.cpp b/sdk/storage/azure-storage-blobs/src/page_blob_client.cpp index c685ef1a5..d435e8709 100644 --- a/sdk/storage/azure-storage-blobs/src/page_blob_client.cpp +++ b/sdk/storage/azure-storage-blobs/src/page_blob_client.cpp @@ -130,8 +130,7 @@ namespace Azure { namespace Storage { namespace Blobs { { Details::BlobRestClient::PageBlob::UploadPageBlobPagesOptions protocolLayerOptions; protocolLayerOptions.Range = std::make_pair(offset, offset + content->Length() - 1); - protocolLayerOptions.TransactionalContentMd5 = options.TransactionalContentMd5; - protocolLayerOptions.TransactionalContentCrc64 = options.TransactionalContentCrc64; + protocolLayerOptions.TransactionalContentHash = options.TransactionalContentHash; protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId; protocolLayerOptions.IfModifiedSince = options.AccessConditions.IfModifiedSince; protocolLayerOptions.IfUnmodifiedSince = options.AccessConditions.IfUnmodifiedSince; @@ -163,8 +162,7 @@ namespace Azure { namespace Storage { namespace Blobs { = std::make_pair(sourceOffset, sourceOffset + sourceLength - 1); protocolLayerOptions.Range = std::make_pair(destinationOffset, destinationOffset + sourceLength - 1); - protocolLayerOptions.TransactionalContentMd5 = options.TransactionalContentMd5; - protocolLayerOptions.TransactionalContentCrc64 = options.TransactionalContentCrc64; + protocolLayerOptions.TransactionalContentHash = options.TransactionalContentHash; protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId; protocolLayerOptions.IfModifiedSince = options.AccessConditions.IfModifiedSince; protocolLayerOptions.IfUnmodifiedSince = options.AccessConditions.IfUnmodifiedSince; diff --git a/sdk/storage/azure-storage-blobs/test/append_blob_client_test.cpp b/sdk/storage/azure-storage-blobs/test/append_blob_client_test.cpp index 2de5162ac..685509ae8 100644 --- a/sdk/storage/azure-storage-blobs/test/append_blob_client_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/append_blob_client_test.cpp @@ -27,7 +27,7 @@ namespace Azure { namespace Storage { namespace Test { m_blobUploadOptions.HttpHeaders.ContentDisposition = "attachment"; m_blobUploadOptions.HttpHeaders.CacheControl = "no-cache"; m_blobUploadOptions.HttpHeaders.ContentEncoding = "identify"; - m_blobUploadOptions.HttpHeaders.ContentMd5 = ""; + m_blobUploadOptions.HttpHeaders.ContentMd5.clear(); m_appendBlobClient->Create(m_blobUploadOptions); auto blockContent = Azure::Core::Http::MemoryBodyStream(m_blobContent.data(), m_blobContent.size()); diff --git a/sdk/storage/azure-storage-blobs/test/blob_container_client_test.cpp b/sdk/storage/azure-storage-blobs/test/blob_container_client_test.cpp index a7e10b0d8..4f4d2b2e2 100644 --- a/sdk/storage/azure-storage-blobs/test/blob_container_client_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/blob_container_client_test.cpp @@ -519,11 +519,11 @@ namespace Azure { namespace Storage { namespace Test { { auto getRandomCustomerProvidedKey = []() { Blobs::EncryptionKey key; - std::string aes256Key; + std::vector aes256Key; aes256Key.resize(32); RandomBuffer(&aes256Key[0], aes256Key.size()); key.Key = Base64Encode(aes256Key); - key.KeyHash = Base64Encode(Details::Sha256(aes256Key)); + key.KeyHash = Details::Sha256(aes256Key); key.Algorithm = Blobs::Models::EncryptionAlgorithmType::Aes256; return key; }; 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 b2702b62e..a3fc8757a 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 @@ -45,7 +45,7 @@ namespace Azure { namespace Storage { namespace Test { m_blobUploadOptions.HttpHeaders.ContentDisposition = "attachment"; m_blobUploadOptions.HttpHeaders.CacheControl = "no-cache"; m_blobUploadOptions.HttpHeaders.ContentEncoding = "identity"; - m_blobUploadOptions.HttpHeaders.ContentMd5 = ""; + m_blobUploadOptions.HttpHeaders.ContentMd5.clear(); m_blobUploadOptions.Tier = Azure::Storage::Blobs::Models::AccessTier::Hot; auto blobContent = Azure::Core::Http::MemoryBodyStream(m_blobContent.data(), m_blobContent.size()); 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 0675d4d8d..9e58cf972 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 @@ -33,7 +33,7 @@ namespace Azure { namespace Storage { namespace Test { m_blobUploadOptions.HttpHeaders.ContentDisposition = "attachment"; m_blobUploadOptions.HttpHeaders.CacheControl = "no-cache"; m_blobUploadOptions.HttpHeaders.ContentEncoding = "identity"; - m_blobUploadOptions.HttpHeaders.ContentMd5 = ""; + m_blobUploadOptions.HttpHeaders.ContentMd5.clear(); m_pageBlobClient->Create(m_blobContent.size(), m_blobUploadOptions); auto pageContent = Azure::Core::Http::MemoryBodyStream(m_blobContent.data(), m_blobContent.size()); @@ -219,12 +219,15 @@ namespace Azure { namespace Storage { namespace Test { auto pageContent = Azure::Core::Http::MemoryBodyStream(blobContent.data(), blobContent.size()); Blobs::UploadPageBlobPagesOptions options; - options.TransactionalContentMd5 - = Base64Encode(Md5::Hash(blobContent.data(), blobContent.size())); + ContentHash hash; + hash.Algorithm = HashAlgorithm::Md5; + hash.Value = Md5::Hash(blobContent.data(), blobContent.size()); + options.TransactionalContentHash = hash; EXPECT_NO_THROW(pageBlobClient.UploadPages(0, &pageContent, options)); pageContent.Rewind(); - options.TransactionalContentMd5 = DummyMd5; + hash.Value = Base64Decode(DummyMd5); + options.TransactionalContentHash = hash; EXPECT_THROW(pageBlobClient.UploadPages(0, &pageContent, options), StorageException); } @@ -240,12 +243,15 @@ namespace Azure { namespace Storage { namespace Test { auto pageContent = Azure::Core::Http::MemoryBodyStream(blobContent.data(), blobContent.size()); Blobs::UploadPageBlobPagesOptions options; - options.TransactionalContentCrc64 - = Base64Encode(Crc64::Hash(blobContent.data(), blobContent.size())); + ContentHash hash; + hash.Algorithm = HashAlgorithm::Crc64; + hash.Value = Crc64::Hash(blobContent.data(), blobContent.size()); + options.TransactionalContentHash = hash; EXPECT_NO_THROW(pageBlobClient.UploadPages(0, &pageContent, options)); pageContent.Rewind(); - options.TransactionalContentCrc64 = DummyCrc64; + hash.Value = Base64Decode(DummyCrc64); + options.TransactionalContentHash = hash; EXPECT_THROW(pageBlobClient.UploadPages(0, &pageContent, options), StorageException); } diff --git a/sdk/storage/azure-storage-common/CHANGELOG.md b/sdk/storage/azure-storage-common/CHANGELOG.md index 62166722e..dffd71d3c 100644 --- a/sdk/storage/azure-storage-common/CHANGELOG.md +++ b/sdk/storage/azure-storage-common/CHANGELOG.md @@ -7,6 +7,7 @@ - Move `StorageRetryPolicy`, `StoragePerRetryPolicy` and `SharedKeyPolicy` to `Details` namespace. - Remove `StorageRetryOptions`, use `Azure::Core::Http::RetryOptions` instead. - Move Account SAS into `Azure::Storage::Sas` namespace. +- Add new type `ContentHash`. ## 12.0.0-beta.5 (2020-11-13) diff --git a/sdk/storage/azure-storage-common/CMakeLists.txt b/sdk/storage/azure-storage-common/CMakeLists.txt index 4ea513b2d..0b92416f2 100644 --- a/sdk/storage/azure-storage-common/CMakeLists.txt +++ b/sdk/storage/azure-storage-common/CMakeLists.txt @@ -75,17 +75,18 @@ target_include_directories( $ ) +# libxml2 headers and libraries will be changed to PRIVATE in the future. target_include_directories(azure-storage-common PUBLIC ${LIBXML2_INCLUDE_DIRS}) target_link_libraries(azure-storage-common PUBLIC Azure::azure-core) target_link_libraries(azure-storage-common INTERFACE Threads::Threads ${LIBXML2_LIBRARIES}) if(MSVC) - target_link_libraries(azure-storage-common INTERFACE bcrypt) + target_link_libraries(azure-storage-common PRIVATE bcrypt) # C28020 and C28204 are introduced by nlohmann/json target_compile_options(azure-storage-common PUBLIC /wd28204 /wd28020) else() find_package(OpenSSL REQUIRED) - target_link_libraries(azure-storage-common INTERFACE OpenSSL::SSL OpenSSL::Crypto) + target_link_libraries(azure-storage-common PRIVATE OpenSSL::SSL OpenSSL::Crypto) endif() get_az_version("${CMAKE_CURRENT_SOURCE_DIR}/inc/azure/storage/common/version.hpp") 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 ff7f90011..16a0e0efe 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 @@ -5,11 +5,16 @@ #include #include +#include namespace Azure { namespace Storage { - std::string Base64Encode(const std::string& text); - std::string Base64Decode(const std::string& text); + std::string Base64Encode(const std::vector& data); + inline std::string Base64Encode(const std::string& text) + { + return Base64Encode(std::vector(text.begin(), text.end())); + } + std::vector Base64Decode(const std::string& text); class Md5 { public: @@ -18,16 +23,16 @@ namespace Azure { namespace Storage { void Update(const uint8_t* data, std::size_t length); - std::string Digest() const; + std::vector Digest() const; - static std::string Hash(const uint8_t* data, std::size_t length) + static std::vector Hash(const uint8_t* data, std::size_t length) { Md5 instance; instance.Update(data, length); return instance.Digest(); } - static std::string Hash(const std::string& data) + static std::vector Hash(const std::string& data) { return Hash(reinterpret_cast(data.data()), data.length()); } @@ -41,16 +46,16 @@ namespace Azure { namespace Storage { void Update(const uint8_t* data, std::size_t length); void Concatenate(const Crc64& other); - std::string Digest() const; + std::vector Digest() const; - static std::string Hash(const uint8_t* data, std::size_t length) + static std::vector Hash(const uint8_t* data, std::size_t length) { Crc64 instance; instance.Update(data, length); return instance.Digest(); } - static std::string Hash(const std::string& data) + static std::vector Hash(const std::string& data) { return Hash(reinterpret_cast(data.data()), data.length()); } @@ -61,8 +66,10 @@ namespace Azure { namespace Storage { }; namespace Details { - std::string Sha256(const std::string& text); - std::string HmacSha256(const std::string& text, const std::string& key); + std::vector Sha256(const std::vector& data); + std::vector HmacSha256( + const std::vector& data, + const std::vector& key); std::string UrlEncodeQueryParameter(const std::string& value); std::string UrlEncodePath(const std::string& value); } // namespace Details diff --git a/sdk/storage/azure-storage-common/inc/azure/storage/common/storage_common.hpp b/sdk/storage/azure-storage-common/inc/azure/storage/common/storage_common.hpp index 76d2b8e37..1ccd3baf4 100644 --- a/sdk/storage/azure-storage-common/inc/azure/storage/common/storage_common.hpp +++ b/sdk/storage/azure-storage-common/inc/azure/storage/common/storage_common.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "azure/core/strings.hpp" @@ -34,4 +35,36 @@ namespace Azure { namespace Storage { } // namespace Details using Metadata = std::map; + /** + * @brief The algorithm used for hash. + */ + enum class HashAlgorithm + { + /** + * @brief MD5 message digest algorithm. + */ + Md5, + + /** + * @brief Cyclic redundancy check. + */ + Crc64, + }; + + /** + * @brief Hash used to check content integrity. + */ + struct ContentHash + { + /** + * @brief Binary hash value. + */ + std::vector Value; + + /** + * @brief The algorithm used for hash. + */ + HashAlgorithm Algorithm; + }; + }} // namespace Azure::Storage diff --git a/sdk/storage/azure-storage-common/src/account_sas_builder.cpp b/sdk/storage/azure-storage-common/src/account_sas_builder.cpp index 070e58261..120b87135 100644 --- a/sdk/storage/azure-storage-common/src/account_sas_builder.cpp +++ b/sdk/storage/azure-storage-common/src/account_sas_builder.cpp @@ -94,8 +94,9 @@ namespace Azure { namespace Storage { namespace Sas { + "\n" + (IPRange.HasValue() ? IPRange.GetValue() : "") + "\n" + protocol + "\n" + Storage::Details::DefaultSasVersion + "\n"; - std::string signature = Base64Encode( - Storage::Details::HmacSha256(stringToSign, Base64Decode(credential.GetAccountKey()))); + std::string signature = Base64Encode(Storage::Details::HmacSha256( + std::vector(stringToSign.begin(), stringToSign.end()), + Base64Decode(credential.GetAccountKey()))); Azure::Core::Http::Url builder; builder.AppendQueryParameter( diff --git a/sdk/storage/azure-storage-common/src/crypt.cpp b/sdk/storage/azure-storage-common/src/crypt.cpp index d8f61d07e..0077c21e3 100644 --- a/sdk/storage/azure-storage-common/src/crypt.cpp +++ b/sdk/storage/azure-storage-common/src/crypt.cpp @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // SPDX-License-Identifier: MIT -#include - #include "azure/storage/common/crypt.hpp" +#include "azure/core/platform.hpp" + #if defined(AZ_PLATFORM_WINDOWS) #if !defined(NOMINMAX) #define NOMINMAX @@ -154,7 +154,7 @@ namespace Azure { namespace Storage { ~AlgorithmProviderInstance() { BCryptCloseAlgorithmProvider(Handle, 0); } }; - std::string Sha256(const std::string& text) + std::vector Sha256(const std::vector& data) { static AlgorithmProviderInstance AlgorithmProvider(AlgorithmType::Sha256); @@ -177,18 +177,18 @@ namespace Azure { namespace Storage { status = BCryptHashData( hashHandle, - reinterpret_cast(const_cast(&text[0])), - static_cast(text.length()), + reinterpret_cast(const_cast(data.data())), + static_cast(data.size()), 0); if (!BCRYPT_SUCCESS(status)) { throw std::runtime_error("BCryptHashData failed"); } - std::string hash; + std::vector hash; hash.resize(AlgorithmProvider.HashLength); status = BCryptFinishHash( - hashHandle, reinterpret_cast(&hash[0]), static_cast(hash.length()), 0); + hashHandle, reinterpret_cast(&hash[0]), static_cast(hash.size()), 0); if (!BCRYPT_SUCCESS(status)) { throw std::runtime_error("BCryptFinishHash failed"); @@ -199,7 +199,9 @@ namespace Azure { namespace Storage { return hash; } - std::string HmacSha256(const std::string& text, const std::string& key) + std::vector HmacSha256( + const std::vector& data, + const std::vector& key) { static AlgorithmProviderInstance AlgorithmProvider(AlgorithmType::HmacSha256); @@ -213,8 +215,8 @@ namespace Azure { namespace Storage { &hashHandle, reinterpret_cast(&context[0]), static_cast(context.size()), - reinterpret_cast(const_cast(&key[0])), - static_cast(key.length()), + reinterpret_cast(const_cast(&key[0])), + static_cast(key.size()), 0); if (!BCRYPT_SUCCESS(status)) { @@ -223,18 +225,18 @@ namespace Azure { namespace Storage { status = BCryptHashData( hashHandle, - reinterpret_cast(const_cast(&text[0])), - static_cast(text.length()), + reinterpret_cast(const_cast(data.data())), + static_cast(data.size()), 0); if (!BCRYPT_SUCCESS(status)) { throw std::runtime_error("BCryptHashData failed"); } - std::string hash; + std::vector hash; hash.resize(AlgorithmProvider.HashLength); status = BCryptFinishHash( - hashHandle, reinterpret_cast(&hash[0]), static_cast(hash.length()), 0); + hashHandle, reinterpret_cast(&hash[0]), static_cast(hash.size()), 0); if (!BCRYPT_SUCCESS(status)) { throw std::runtime_error("BCryptFinishHash failed"); @@ -298,15 +300,15 @@ namespace Azure { namespace Storage { } } - std::string Md5::Digest() const + std::vector Md5::Digest() const { Md5HashContext* context = static_cast(m_context); - std::string hash; + std::vector hash; hash.resize(context->hashLength); NTSTATUS status = BCryptFinishHash( context->hashHandle, reinterpret_cast(&hash[0]), - static_cast(hash.length()), + static_cast(hash.size()), 0); if (!BCRYPT_SUCCESS(status)) { @@ -315,16 +317,16 @@ namespace Azure { namespace Storage { return hash; } - std::string Base64Encode(const std::string& text) + std::string Base64Encode(const std::vector& data) { std::string encoded; // According to RFC 4648, the encoded length should be ceiling(n / 3) * 4 - DWORD encodedLength = static_cast((text.length() + 2) / 3 * 4); + DWORD encodedLength = static_cast((data.size() + 2) / 3 * 4); encoded.resize(encodedLength); CryptBinaryToStringA( - reinterpret_cast(text.data()), - static_cast(text.length()), + reinterpret_cast(data.data()), + static_cast(data.size()), CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, static_cast(&encoded[0]), &encodedLength); @@ -332,9 +334,9 @@ namespace Azure { namespace Storage { return encoded; } - std::string Base64Decode(const std::string& text) + std::vector Base64Decode(const std::string& text) { - std::string decoded; + std::vector decoded; // According to RFC 4648, the encoded length should be ceiling(n / 3) * 4, so we can infer an // upper bound here DWORD decodedLength = DWORD(text.length() / 4 * 3); @@ -344,7 +346,7 @@ namespace Azure { namespace Storage { text.data(), static_cast(text.length()), CRYPT_STRING_BASE64 | CRYPT_STRING_STRICT, - reinterpret_cast(&decoded[0]), + reinterpret_cast(decoded.data()), &decodedLength, nullptr, nullptr); @@ -356,30 +358,32 @@ namespace Azure { namespace Storage { namespace Details { - std::string Sha256(const std::string& text) + std::vector Sha256(const std::vector& data) { SHA256_CTX context; SHA256_Init(&context); - SHA256_Update(&context, text.data(), text.length()); + SHA256_Update(&context, data.data(), data.size()); unsigned char hash[SHA256_DIGEST_LENGTH]; SHA256_Final(hash, &context); - return std::string(std::begin(hash), std::end(hash)); + return std::vector(std::begin(hash), std::end(hash)); } - std::string HmacSha256(const std::string& text, const std::string& key) + std::vector HmacSha256( + const std::vector& data, + const std::vector& key) { - char hash[EVP_MAX_MD_SIZE]; + uint8_t hash[EVP_MAX_MD_SIZE]; unsigned int hashLength = 0; HMAC( EVP_sha256(), key.data(), - static_cast(key.length()), - reinterpret_cast(text.data()), - text.length(), + static_cast(key.size()), + reinterpret_cast(data.data()), + data.size(), reinterpret_cast(&hash[0]), &hashLength); - return std::string(hash, hashLength); + return std::vector(std::begin(hash), std::begin(hash) + hashLength); } } // namespace Details @@ -403,20 +407,20 @@ namespace Azure { namespace Storage { MD5_Update(context, data, length); } - std::string Md5::Digest() const + std::vector Md5::Digest() const { MD5_CTX* context = static_cast(m_context); unsigned char hash[MD5_DIGEST_LENGTH]; MD5_Final(hash, context); - return std::string(std::begin(hash), std::end(hash)); + return std::vector(std::begin(hash), std::end(hash)); } - std::string Base64Encode(const std::string& text) + std::string Base64Encode(const std::vector& data) { BIO* bio = BIO_new(BIO_s_mem()); bio = BIO_push(BIO_new(BIO_f_base64()), bio); BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); - BIO_write(bio, text.data(), static_cast(text.length())); + BIO_write(bio, data.data(), static_cast(data.size())); BIO_flush(bio); BUF_MEM* bufferPtr; BIO_get_mem_ptr(bio, &bufferPtr); @@ -426,9 +430,9 @@ namespace Azure { namespace Storage { return std::string(bufferPtr->data, bufferPtr->length); } - std::string Base64Decode(const std::string& text) + std::vector Base64Decode(const std::string& text) { - std::string decoded; + std::vector decoded; // According to RFC 4648, the encoded length should be ceiling(n / 3) * 4, so we can infer an // upper bound here std::size_t maxDecodedLength = text.length() / 4 * 3; @@ -1254,9 +1258,9 @@ namespace Azure { namespace Storage { m_context ^= other.m_context; } - std::string Crc64::Digest() const + std::vector Crc64::Digest() const { - std::string binary; + 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/src/shared_key_policy.cpp b/sdk/storage/azure-storage-common/src/shared_key_policy.cpp index 20f4aa0c4..91ddd30d7 100644 --- a/sdk/storage/azure-storage-common/src/shared_key_policy.cpp +++ b/sdk/storage/azure-storage-common/src/shared_key_policy.cpp @@ -79,7 +79,8 @@ namespace Azure { namespace Storage { namespace Details { // remove last linebreak string_to_sign.pop_back(); - return Base64Encode( - Details::HmacSha256(string_to_sign, Base64Decode(m_credential->GetAccountKey()))); + return Base64Encode(Details::HmacSha256( + std::vector(string_to_sign.begin(), string_to_sign.end()), + Base64Decode(m_credential->GetAccountKey()))); } }}} // namespace Azure::Storage::Details 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 aefb019ca..a1fdbbddc 100644 --- a/sdk/storage/azure-storage-common/test/crypt_functions_test.cpp +++ b/sdk/storage/azure-storage-common/test/crypt_functions_test.cpp @@ -1,37 +1,49 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // SPDX-License-Identifier: MIT +#include + #include "azure/storage/common/crypt.hpp" #include "test_base.hpp" namespace Azure { namespace Storage { namespace Test { + std::vector ToBinaryVector(const char* text) + { + const uint8_t* start = reinterpret_cast(text); + return std::vector(start, start + strlen(text)); + } + TEST(CryptFunctionsTest, Base64) { for (std::size_t len : {0, 10, 100, 1000, 10000}) { - std::string data; + std::vector data; data.resize(len); - RandomBuffer(&data[0], data.length()); + RandomBuffer(data.data(), data.size()); EXPECT_EQ(Base64Decode(Base64Encode(data)), data); } } TEST(CryptFunctionsTest, Sha256) { - EXPECT_EQ(Base64Encode(Details::Sha256("")), "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="); EXPECT_EQ( - Base64Encode(Details::Sha256("Hello Azure!")), + Base64Encode(Details::Sha256(ToBinaryVector(""))), + "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="); + EXPECT_EQ( + Base64Encode(Details::Sha256(ToBinaryVector("Hello Azure!"))), "Mjzwx2mqGHb9FSgjm33ShNmXYndkgvwA6tQmEiskOHg="); } TEST(CryptFunctionsTest, HmacSha256) { std::string key = "8CwtGFF1mGR4bPEP9eZ0x1fxKiQ3Ca5N"; + std::vector binaryKey(key.begin(), key.end()); EXPECT_EQ( - Base64Encode(Details::HmacSha256("", key)), "fFy2T+EuCvAgouw/vB/RAJ75z7jwTj+uiURebkFKF5M="); + Base64Encode(Details::HmacSha256(ToBinaryVector(""), binaryKey)), + "fFy2T+EuCvAgouw/vB/RAJ75z7jwTj+uiURebkFKF5M="); EXPECT_EQ( - Base64Encode(Details::HmacSha256("Hello Azure!", key)), + Base64Encode(Details::HmacSha256(ToBinaryVector("Hello Azure!"), binaryKey)), "+SBESxQVhI53mSEdZJcCBpdBkaqwzfPaVYZMAf5LP3c="); } diff --git a/sdk/storage/azure-storage-common/test/test_base.hpp b/sdk/storage/azure-storage-common/test/test_base.hpp index b2d0d6435..bdcd6eb40 100644 --- a/sdk/storage/azure-storage-common/test/test_base.hpp +++ b/sdk/storage/azure-storage-common/test/test_base.hpp @@ -55,6 +55,10 @@ namespace Azure { namespace Storage { namespace Test { Storage::Metadata RandomMetadata(size_t size = 5); void RandomBuffer(char* buffer, std::size_t length); + inline void RandomBuffer(uint8_t* buffer, std::size_t length) + { + RandomBuffer(reinterpret_cast(buffer), length); + } std::vector RandomBuffer(std::size_t length); inline std::vector ReadBodyStream(std::unique_ptr& stream) diff --git a/sdk/storage/azure-storage-files-datalake/CHANGELOG.md b/sdk/storage/azure-storage-files-datalake/CHANGELOG.md index 82976c37a..c078f7fad 100644 --- a/sdk/storage/azure-storage-files-datalake/CHANGELOG.md +++ b/sdk/storage/azure-storage-files-datalake/CHANGELOG.md @@ -5,6 +5,7 @@ ### Breaking Changes - Move DataLake SAS into `Azure::Storage::Sas` namespace. +- `EncrytionKeySha256` are changed to binary(`std::vector`). ## 12.0.0-beta.5 (2020-11-13) diff --git a/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_responses.hpp b/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_responses.hpp index 593c5ee4b..35522c332 100644 --- a/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_responses.hpp +++ b/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/datalake_responses.hpp @@ -86,7 +86,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { nam Azure::Core::Nullable LeaseStatus; DataLakeHttpHeaders HttpHeaders; Azure::Core::Nullable ServerEncrypted; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable AccessTierInferred; Azure::Core::Nullable AccessTierChangeTime; Azure::Core::Nullable CopyId; @@ -168,7 +168,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { nam DataLakeHttpHeaders HttpHeaders; Storage::Metadata Metadata; Azure::Core::Nullable ServerEncrypted; - Azure::Core::Nullable EncryptionKeySha256; + Azure::Core::Nullable> EncryptionKeySha256; }; using CreateFileResult = CreatePathResult; diff --git a/sdk/storage/azure-storage-files-datalake/src/datalake_file_client.cpp b/sdk/storage/azure-storage-files-datalake/src/datalake_file_client.cpp index a5384ef5b..bb43105b1 100644 --- a/sdk/storage/azure-storage-files-datalake/src/datalake_file_client.cpp +++ b/sdk/storage/azure-storage-files-datalake/src/datalake_file_client.cpp @@ -322,7 +322,10 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } ret.RangeOffset = RangeOffset; ret.RangeLength = RangeLength; - ret.TransactionalMd5 = std::move(result->TransactionalContentMd5); + if (result->TransactionalContentHash.HasValue()) + { + ret.TransactionalMd5 = Base64Encode(result->TransactionalContentHash.GetValue().Value); + } ret.ETag = std::move(result->ETag); ret.LastModified = std::move(result->LastModified); ret.LeaseDuration = std::move(result->LeaseDuration); diff --git a/sdk/storage/azure-storage-files-datalake/src/datalake_sas_builder.cpp b/sdk/storage/azure-storage-files-datalake/src/datalake_sas_builder.cpp index d8b205c86..816cf5e0c 100644 --- a/sdk/storage/azure-storage-files-datalake/src/datalake_sas_builder.cpp +++ b/sdk/storage/azure-storage-files-datalake/src/datalake_sas_builder.cpp @@ -128,8 +128,9 @@ namespace Azure { namespace Storage { namespace Sas { + Storage::Details::DefaultSasVersion + "\n" + resource + "\n" + "\n" + CacheControl + "\n" + ContentDisposition + "\n" + ContentEncoding + "\n" + ContentLanguage + "\n" + ContentType; - std::string signature = Base64Encode( - Storage::Details::HmacSha256(stringToSign, Base64Decode(credential.GetAccountKey()))); + std::string signature = Base64Encode(Storage::Details::HmacSha256( + std::vector(stringToSign.begin(), stringToSign.end()), + Base64Decode(credential.GetAccountKey()))); Azure::Core::Http::Url builder; builder.AppendQueryParameter( @@ -208,8 +209,9 @@ namespace Azure { namespace Storage { namespace Sas { + CacheControl + "\n" + ContentDisposition + "\n" + ContentEncoding + "\n" + ContentLanguage + "\n" + ContentType; - std::string signature = Base64Encode( - Storage::Details::HmacSha256(stringToSign, Base64Decode(userDelegationKey.Value))); + std::string signature = Base64Encode(Storage::Details::HmacSha256( + std::vector(stringToSign.begin(), stringToSign.end()), + Base64Decode(userDelegationKey.Value))); Azure::Core::Http::Url builder; builder.AppendQueryParameter( diff --git a/sdk/storage/azure-storage-files-shares/src/share_sas_builder.cpp b/sdk/storage/azure-storage-files-shares/src/share_sas_builder.cpp index 625a6bc25..5a2acdeda 100644 --- a/sdk/storage/azure-storage-files-shares/src/share_sas_builder.cpp +++ b/sdk/storage/azure-storage-files-shares/src/share_sas_builder.cpp @@ -89,8 +89,9 @@ namespace Azure { namespace Storage { namespace Sas { + Storage::Details::DefaultSasVersion + "\n" + CacheControl + "\n" + ContentDisposition + "\n" + ContentEncoding + "\n" + ContentLanguage + "\n" + ContentType; - std::string signature = Base64Encode( - Storage::Details::HmacSha256(stringToSign, Base64Decode(credential.GetAccountKey()))); + std::string signature = Base64Encode(Storage::Details::HmacSha256( + std::vector(stringToSign.begin(), stringToSign.end()), + Base64Decode(credential.GetAccountKey()))); Azure::Core::Http::Url builder; builder.AppendQueryParameter(