azure-sdk-for-net: [BUG]BlobClient.UploadAsync trying to use "unsupported" System.Security.Cryptography.Algorithms

Describe the bug I am using BlobClient.UploadAsync to upload an image loaded into a stream to our Azure CDN storage service, but I get an error when I try to do this.

Expected behavior Blobs are uploaded to Azure storage that contain the data from the stream.

Actual behavior (include Exception or Stack Trace) When this function executes, I get an error saying “System.PlatformNotSupportedException: System.Security.Cryptography.Algorithms is not supported on this platform.” This happens whether I use the latest stable v12.6.0 release or the v12.7.0-preview.1 release of Azure.Storage.Blobs.

This may be related to the fact that HMAC encryption is not supported (https://www.gitmemory.com/issue/dotnet/runtime/40076/692559015)

If that’s the case, why is this built-in Azure library trying to implement this encryption algorithm, and how can I upload BLOBs without this happening using the SDK?

Here is the stack trace:

System.PlatformNotSupportedException: System.Security.Cryptography.Algorithms is not supported on this platform. at System.Security.Cryptography.HMACSHA256…ctor(Byte[] key) at Azure.Storage.StorageSharedKeyCredential.ComputeHMACSHA256(String message) at Azure.Storage.StorageSharedKeyCredential.ComputeSasSignature(StorageSharedKeyCredential credential, String message) at Azure.Storage.StorageSharedKeyCredentialInternals.ComputeSasSignature(StorageSharedKeyCredential credential, String message) at Azure.Storage.StorageSharedKeyPipelinePolicy.OnSendingRequest(HttpMessage message) at Azure.Core.Pipeline.HttpPipelineSynchronousPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory1 pipeline) at Azure.Core.Pipeline.HttpPipelineSynchronousPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory1 pipeline) at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory1 pipeline, Boolean async) at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory1 pipeline, Boolean async) at Azure.Core.Pipeline.HttpPipelineSynchronousPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory1 pipeline) at Azure.Core.Pipeline.HttpPipelineSynchronousPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory1 pipeline) at Azure.Core.Pipeline.HttpPipelineSynchronousPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory1 pipeline) at Azure.Storage.Blobs.BlobRestClient.BlockBlob.UploadAsync(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, Uri resourceUri, Stream body, Int64 contentLength, String version, Nullable1 timeout, Byte[] transactionalContentHash, String blobContentType, String blobContentEncoding, String blobContentLanguage, Byte[] blobContentHash, String blobCacheControl, IDictionary2 metadata, String leaseId, String blobContentDisposition, String encryptionKey, String encryptionKeySha256, Nullable1 encryptionAlgorithm, String encryptionScope, Nullable1 tier, Nullable1 ifModifiedSince, Nullable1 ifUnmodifiedSince, Nullable1 ifMatch, Nullable1 ifNoneMatch, String ifTags, String requestId, String blobTagsString, Boolean async, String operationName, CancellationToken cancellationToken) at Azure.Storage.Blobs.Specialized.BlockBlobClient.UploadInternal(Stream content, BlobHttpHeaders blobHttpHeaders, IDictionary2 metadata, IDictionary2 tags, BlobRequestConditions conditions, Nullable1 accessTier, IProgress`1 progressHandler, String operationName, Boolean async, CancellationToken cancellationToken) at Azure.Storage.Blobs.Specialized.BlockBlobClient.<>c__DisplayClass48_0.<<GetPartitionedUploaderBehaviors>b__0>d.MoveNext() — End of stack trace from previous location —

at Azure.Storage.PartitionedUploader`2.<UploadInternal>d__19[[Azure.Storage.Blobs.Models.BlobUploadOptions, Azure.Storage.Blobs, Version=12.6.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8],[Azure.Storage.Blobs.Models.BlobContentInfo, Azure.Storage.Blobs, Version=12.6.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8]].MoveNext() at Azure.Storage.Blobs.BlobClient.StagedUploadInternal(Stream content, BlobUploadOptions options, Boolean async, CancellationToken cancellationToken) at {the Razor page where I call UploadAsync}

To Reproduce Use blobClient.UploadAsync and pass a stream as the argument.

Environment: Azure.Storage.Blobs 12.7.0-preview.1 Visual Studio 16.8.0 Preview 3.2 Target framework: .NET 5.0

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 1
  • Comments: 18 (9 by maintainers)

Most upvoted comments

Here’s a resource that explains various ways to authenticate to storage: https://docs.microsoft.com/en-us/azure/storage/common/storage-auth .

For scenarios that run in browser (i.e. on client side, in environment you don’t control) usage of Shared Key/Connection String is dangerous and shouldn’t be attempted for security reasons. It is effectively exposing these secrets to public and anybody who intercepts them gains superuser access to your storage account.

For mentioned scenarios I suggest to explore the following options:

  • assuming that Blazor App talks to some backend, you could vend SAS from backend to an App that would be short lived and used for the lifespan of the App.
  • consider using Azure Active Directory (AAD) and one of suitable OAuth flows. (i.e. this one ).

Hello @jaschrep-msft. I am using BlobClient’s UploadAsync in the client-side part of a hosted Blazor WASM application to upload images directly from a client’s machine to an Azure CDN service. Since we last spoke, I have upgraded to the stable version of .NET Core 5 and all associated Nuget packages, and this problem still persists.

Hi @Multivac222, thanks for reporting this, we will investigate.

@jaschrep-msft.