Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Padding is invalid and cannot be removed while doing client side encryption for storage blob data using keyvault key #23082

Closed
PPrabinKumarPatro opened this issue Aug 3, 2021 · 23 comments
Labels
bug This issue requires a change to an existing behavior in the product in order to be resolved. Client This issue points to a problem in the data-plane of the library. customer-reported Issues that are reported by GitHub users external to the Azure organization. needs-team-attention Workflow: This issue needs attention from Azure service team or SDK team Service Attention Workflow: This issue is responsible by Azure service team. Storage Storage Service (Queues, Blobs, Files)

Comments

@PPrabinKumarPatro
Copy link

PPrabinKumarPatro commented Aug 3, 2021

Describe the bug
We are doing client side encryption for storage blob data using keyvault key. This is the bug "#16298" i intially filled for SNI. We were able to get it done but we are getting "Padding is invalid and cannot be removed" error now

Expected behavior
Should successfully decrypt and encrypt the data

Actual behavior (include Exception or Stack Trace)
Padding is invalid and cannot be removed error

To Reproduce
Steps to reproduce the behavior (include a code snippet, screenshot, or any additional information that might help us reproduce the issue)

code snippet is exactly explained here except we are using SNI
#16298

Environment:

  • Name and version of the Library package used: [e.g. Azure.Storage.Blobs 12.2.0]
    Azure.Storage.Blobs : 12.8.0
    Azure.Identity is 1.4.0-beta.1
    Azure.Security.KeyVault.Keys 4.2.0-beta.2
  • Hosting platform or OS and .NET runtime version (dotnet --info output for .NET Core projects): [e.g. Azure AppService or Windows 10 .NET Framework 4.8]
    .Net core
  • IDE and version : [e.g. Visual Studio 16.3]
    Visual Studi 2019

Call stack:

System.Security.Cryptography.CryptographicException:
   at Internal.Cryptography.UniversalCryptoDecryptor.DepadBlock (System.Security.Cryptography.Algorithms, Version=4.3.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
   at Internal.Cryptography.UniversalCryptoDecryptor.UncheckedTransformFinalBlock (System.Security.Cryptography.Algorithms, Version=4.3.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
   at Internal.Cryptography.UniversalCryptoTransform.TransformFinalBlock (System.Security.Cryptography.Algorithms, Version=4.3.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
   at System.Security.Cryptography.CryptoStream+<ReadAsyncCore>d__42.MoveNext (System.Security.Cryptography.Primitives, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Security.Cryptography.CryptoStream+<ReadAsyncInternal>d__37.MoveNext (System.Security.Cryptography.Primitives, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at Azure.Storage.Shared.WindowStream+<ReadInternal>d__18.MoveNext (Azure.Storage.Blobs, Version=12.8.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at Azure.Storage.Shared.WindowStream+<ReadAsync>d__17.MoveNext (Azure.Storage.Blobs, Version=12.8.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.IO.Stream+<CopyToAsyncInternal>d__30.MoveNext (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at Azure.Storage.Blobs.PartitionedDownloader+<CopyToAsync>d__9.MoveNext (Azure.Storage.Blobs, Version=12.8.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at Azure.Storage.Blobs.PartitionedDownloader+<DownloadToAsync>d__5.MoveNext (Azure.Storage.Blobs, Version=12.8.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at Azure.Storage.Blobs.Specialized.BlobBaseClient+<StagedDownloadAsync>d__74.MoveNext (Azure.Storage.Blobs, Version=12.8.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at Azure.Storage.Blobs.Specialized.BlobBaseClient+<DownloadToAsync>d__72.MoveNext (Azure.Storage.Blobs, Version=12.8.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at Azure.Storage.Blobs.Specialized.BlobBaseClient+<DownloadToAsync>d__68.MoveNext (Azure.Storage.Blobs, Version=12.8.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at Microsoft.AzureMonitor.Billing.Common.Storage.AzureBlobStorageClient+<**DownloadStreamAsync**>d__11.MoveNext (Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null: C:\source\src\Common\Storage\AzureBlobStorageClient.cs:78)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at Microsoft.AzureMonitor.Billing.LogAnalyticsCollectorBusiness.BlobHelper+<DownloadEHInfoFromBlobAsync>d__15.MoveNext (LogAnalyticsCollectorService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null: C:\source\src\LogAnalyticsCollectorService\Business\BlobHelper.cs:244)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at Microsoft.AzureMonitor.Billing.LogAnalyticsCollectorBusiness.BlobHelper+<CompareEHInfoWithBlob>d__13.MoveNext (LogAnalyticsCollectorService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null: C:\source\src\LogAnalyticsCollectorService\Business\BlobHelper.cs:221)
@ghost ghost added needs-triage Workflow: This is a new issue that needs to be triaged to the appropriate team. customer-reported Issues that are reported by GitHub users external to the Azure organization. question The issue doesn't require a change to the product in order to be resolved. Most issues start as that labels Aug 3, 2021
@PPrabinKumarPatro
Copy link
Author

@jsquire @schaabs can you help here ? Thanks.

@jsquire jsquire added Azure.Identity Client This issue points to a problem in the data-plane of the library. needs-team-attention Workflow: This issue needs attention from Azure service team or SDK team labels Aug 4, 2021
@ghost ghost removed the needs-triage Workflow: This is a new issue that needs to be triaged to the appropriate team. label Aug 4, 2021
@jsquire
Copy link
Member

jsquire commented Aug 4, 2021

Hi @PPrabinKumarPatro. Thank you for your feedback and we regret that you're experiencing difficulties. I'm not sure the source of your error - specifically if you're seeing this when acquiring the token as you were with #16298 or if this is being surfaced by the KeyVault or Storage libraries. If you're able to share a stack trace and any other context that you have, it would be helpful in finding the right people to assist.

For now, I've looped in our Azure.Identity experts for their thoughts.

@jsquire jsquire added the needs-author-feedback Workflow: More information is needed from author to address the issue. label Aug 4, 2021
@ghost ghost removed the needs-team-attention Workflow: This issue needs attention from Azure service team or SDK team label Aug 4, 2021
@PPrabinKumarPatro
Copy link
Author

updated with call stack

@ghost ghost added needs-team-attention Workflow: This issue needs attention from Azure service team or SDK team and removed needs-author-feedback Workflow: More information is needed from author to address the issue. labels Aug 4, 2021
@jsquire
Copy link
Member

jsquire commented Aug 4, 2021

Thank you! The call stack appears to imply that this is occurring in the Storage SDK. Rerouting to the storage team for assistance.

@jsquire jsquire added Service Attention Workflow: This issue is responsible by Azure service team. Storage Storage Service (Queues, Blobs, Files) and removed Azure.Identity labels Aug 4, 2021
@ghost
Copy link

ghost commented Aug 4, 2021

Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc @xgithubtriage.

Issue Details

Describe the bug
We are doing client side encryption for storage blob data using keyvault key. This is the bug "#16298" i intially filled for SNI. We were able to get it done but we are getting "Padding is invalid and cannot be removed" error now

Expected behavior
Should successfully decrypt and encrypt the data

Actual behavior (include Exception or Stack Trace)
Padding is invalid and cannot be removed error

To Reproduce
Steps to reproduce the behavior (include a code snippet, screenshot, or any additional information that might help us reproduce the issue)

code snippet is exactly explained here except we are using SNI
#16298

Environment:

  • Name and version of the Library package used: [e.g. Azure.Storage.Blobs 12.2.0]
    Azure.Storage.Blobs : 12.8.0
    Azure.Identity is 1.4.0-beta.1
    Azure.Security.KeyVault.Keys 4.2.0-beta.2
  • Hosting platform or OS and .NET runtime version (dotnet --info output for .NET Core projects): [e.g. Azure AppService or Windows 10 .NET Framework 4.8]
    .Net core
  • IDE and version : [e.g. Visual Studio 16.3]
    Visual Studi 2019

Call stack:
System.Security.Cryptography.CryptographicException:
at Internal.Cryptography.UniversalCryptoDecryptor.DepadBlock (System.Security.Cryptography.Algorithms, Version=4.3.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
at Internal.Cryptography.UniversalCryptoDecryptor.UncheckedTransformFinalBlock (System.Security.Cryptography.Algorithms, Version=4.3.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
at Internal.Cryptography.UniversalCryptoTransform.TransformFinalBlock (System.Security.Cryptography.Algorithms, Version=4.3.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
at System.Security.Cryptography.CryptoStream+d__42.MoveNext (System.Security.Cryptography.Primitives, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Security.Cryptography.CryptoStream+d__37.MoveNext (System.Security.Cryptography.Primitives, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Azure.Storage.Shared.WindowStream+d__18.MoveNext (Azure.Storage.Blobs, Version=12.8.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Azure.Storage.Shared.WindowStream+d__17.MoveNext (Azure.Storage.Blobs, Version=12.8.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.IO.Stream+d__30.MoveNext (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Azure.Storage.Blobs.PartitionedDownloader+d__9.MoveNext (Azure.Storage.Blobs, Version=12.8.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Azure.Storage.Blobs.PartitionedDownloader+d__5.MoveNext (Azure.Storage.Blobs, Version=12.8.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Azure.Storage.Blobs.Specialized.BlobBaseClient+d__74.MoveNext (Azure.Storage.Blobs, Version=12.8.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Azure.Storage.Blobs.Specialized.BlobBaseClient+d__72.MoveNext (Azure.Storage.Blobs, Version=12.8.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Azure.Storage.Blobs.Specialized.BlobBaseClient+d__68.MoveNext (Azure.Storage.Blobs, Version=12.8.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Microsoft.AzureMonitor.Billing.Common.Storage.AzureBlobStorageClient+d__11.MoveNext (Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null: C:\source\src\Common\Storage\AzureBlobStorageClient.cs:78)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Microsoft.AzureMonitor.Billing.LogAnalyticsCollectorBusiness.BlobHelper+d__15.MoveNext (LogAnalyticsCollectorService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null: C:\source\src\LogAnalyticsCollectorService\Business\BlobHelper.cs:244)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Microsoft.AzureMonitor.Billing.LogAnalyticsCollectorBusiness.BlobHelper+d__13.MoveNext (LogAnalyticsCollectorService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null: C:\source\src\LogAnalyticsCollectorService\Business\BlobHelper.cs:221)

Author: PPrabinKumarPatro
Assignees: -
Labels:

Client, Service Attention, Storage, customer-reported, needs-team-attention, question

Milestone: -

@PPrabinKumarPatro
Copy link
Author

PPrabinKumarPatro commented Aug 5, 2021

HI Storage team, can you help here as we are having issues in most of prod regions including EUS, It would be challenging if it became bigger issue. Thanks.

@amnguye
Copy link
Member

amnguye commented Aug 5, 2021

Can you provide a more detailed code snippet where the key is being passed to the BlobBaseClient, I can tell you're doing a DownloadToAsync but the error "Padding is invalid.." is not included in the stack trace, but you said that this is the error that appears for you.

I wonder what's wrong with the key being passed to the BlobBaseClient to be causing this error with the Cryptography library.
@jaschrep-msft Feel free to chime in about this.

@jaschrep-msft
Copy link
Member

"Padding is invalid" is the hardest issue to track down. It essentially means that the last 16 byte encryption block was an unexpected value according to the AES specification and so there was some sort of error. Something could have gone wrong during encryption, decryption, key wrapping, key unwrapping, upload, download, or even blob metadata management; some piece of data is incorrect in the whole process.

In the past, this has come up when users are working with their own IKeyEncryptionKey and IKeyEncryptionKeyResolver implementations and they made an error developing them. This doesn't appear to be the case here, though, since you're using KeyVault SDK.

Additionally, you point us to your other issue for code snippets, but there isn't any code in there that uses the storage SDK. That will likely be necessary to figure out what is happening.

@PPrabinKumarPatro
Copy link
Author

Hi, what information do you need here to debug? Also can you ping me over teams for quick fix. We are still having the issue but in different region. The issue auto resolves in some regions by itself.

@PPrabinKumarPatro
Copy link
Author

below is the code and we use storage SDK ( BlobClient blobClient = containerClient.GetBlobClient("test").WithClientSideEncryptionOptions(clientSideOptions);)

//Create CryptographyClient using Key Vault Key
CryptographyClient cryptographyClient = new CryptographyClient(clientSideKeyVaultKeyUri, credential);

        //Set up Client Side Encryption Options used for Client Side Encryption
        ClientSideEncryptionOptions clientSideOptions = new ClientSideEncryptionOptions(ClientSideEncryptionVersion.V1_0)
        {
            // KeyEncryptionKey = cryptographyClient,
            //KeyWrapAlgorithm = "RS256"
            KeyEncryptionKey = cryptographyClient,
           // KeyResolver = keyResolver,
            // string the storage client will use when calling IKeyEncryptionKey.WrapKey()
            KeyWrapAlgorithm = "RSA1_5"
        };


        //Create Blob Service Client
        BlobServiceClient blobServiceClient = new BlobServiceClient(storageConnectionString);

        BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient("example");
        //Create BlobClient with Client Side Encryption Options to upload client side encrypted data
        BlobClient blobClient = containerClient.GetBlobClient("test").WithClientSideEncryptionOptions(clientSideOptions);
        blobClient.Upload(stream);

@PPrabinKumarPatro
Copy link
Author

Any update here?

@jaschrep-msft
Copy link
Member

Taken offline. Will update here when conclusions are reached.

@irinasmt
Copy link

irinasmt commented Oct 7, 2021

Any updates, please I am getting the same error.

@irinasmt
Copy link

irinasmt commented Oct 7, 2021

@PPrabinKumarPatro Did you find any quick fix for this issue?

@wonderphil
Copy link

wonderphil commented Oct 11, 2021

Any updates on this please???

@jaschrep-msft
Copy link
Member

If someone has a consistent reproduction of this error they can provide, that would help immensely. As stated earlier in this thread, this is a difficult issue to track because the actual issue has come and gone by the time this exception is raised.

@wonderphil
Copy link

@jaschrep-msft I do, let me copy some stuff in for you and let me know what else if anything you need. If you need the actual blobs/data, we will need to go through Microsoft Support so NDA is in place.

@wonderphil
Copy link

wonderphil commented Oct 11, 2021

So I am basically running an Azure function, where it goes gets a list of blobs and pushes that into a queue, then the processing of that blob is to download it, decrypt it and encrypted it with a new Key Vault Key, or a new version of the Key and re-upload it to the container.

We are doing this for a few reasons, one key comprised (not likely but have to have the process), changing key or the main reason wanting to re-encrypt all the data that was using standard RSA key to RSA-HSM key.

The errors I am getting are as follows:

2021-10-11T16:02:53.972 [Error] Executed 'EncryptBlobData' (Failed, Id=e978418c-5d72-42df-858b-8f4436313757, Duration=902ms)Padding is invalid and cannot be removed.

2021-10-11T16:02:53.976 [Error] at Internal.Cryptography.UniversalCryptoDecryptor.DepadBlock(Byte[] block, Int32 offset,
Int32 count)at Internal.Cryptography.UniversalCryptoDecryptor.UncheckedTransformFinalBlock(Byte[] inputBuffer, Int32 
inputOffset, Int32 inputCount)at Internal.Cryptography.UniversalCryptoTransform.TransformFinalBlock(Byte[] inputBuffer, 
Int32 inputOffset, Int32 inputCount)at System.Security.Cryptography.CryptoStream.ReadAsyncCore(Byte[] buffer, Int32 
offset, Int32 count, CancellationToken cancellationToken, Boolean useAsync)at 
System.Security.Cryptography.CryptoStream.ReadAsyncInternal(Byte[] buffer, Int32 offset, Int32 count, 
CancellationToken cancellationToken)at Azure.Storage.Shared.WindowStream.ReadInternal(Byte[] buffer, 
Int32 offset, Int32 count, Boolean async, CancellationToken cancellationToken)at 
Azure.Storage.Shared.WindowStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken
 cancellationToken)at System.IO.Stream.CopyToAsyncInternal(Stream destination, Int32 bufferSize, 
CancellationToken cancellationToken)at Azure.Storage.Blobs.PartitionedDownloader.CopyToAsync(BlobDownloadStreamingResult result, 
Stream destination, CancellationToken cancellationToken)at Azure.Storage.Blobs.PartitionedDownloader.DownloadToAsync(Stream destination, BlobRequestConditions conditions, 
CancellationToken cancellationToken)at Azure.Storage.Blobs.Specialized.BlobBaseClient.StagedDownloadAsync(Stream 
destination, BlobRequestConditions conditions, StorageTransferOptions transferOptions, Boolean async, CancellationToken 
cancellationToken)at Azure.Storage.Blobs.Specialized.BlobBaseClient.DownloadToAsync(Stream destination, 
BlobRequestConditions conditions, StorageTransferOptions transferOptions, CancellationToken cancellationToken)at 
Azure.Storage.Blobs.Specialized.BlobBaseClient.DownloadToAsync(Stream destination, CancellationToken 
cancellationToken)at Azure.Storage.Blobs.Specialized.BlobBaseClient.DownloadToAsync(Stream destination)at 
BlobReEncryption.EncryptBlobDataFunction.DownloadAndEncryptBlob(BlobClient blobEncryptionClient, BlobClient 
blobDecryptionClient, Dictionary`2 metadata, ILogger log) in 
/home/vsts/work/1/s/src/BlobReEncryption/EncryptBlobDataFunction.cs:line 80at 
BlobReEncryption.EncryptBlobDataFunction.RunAsync(String myQueueItem, ILogger log) in 
/home/vsts/work/1/s/src/BlobReEncryption/EncryptBlobDataFunction.cs:line 61

code is:

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Azure.Identity;
using Azure.Security.KeyVault.Keys.Cryptography;
using Azure.Storage;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Specialized;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace BlobReEncryption
{
    public static class EncryptBlobDataFunction
    {
        [FunctionName("EncryptBlobData")]
        public static async Task RunAsync([QueueTrigger("blobs-queue", Connection = "StorageAccount")] string myQueueItem, ILogger log)
        {

            // this function gets all the blobs an pushes them on the queue
            var appSettings = CommonFunctionHelper.GetAppSettings(log);
            if (!CommonFunctionHelper.ValidateAppSettingsForNullValue(appSettings, log))
                return;
            try
            {
                var queueMessage = JsonConvert.DeserializeObject<QueueMessage>(myQueueItem);
                log.LogInformation($"running function for blob {queueMessage.BlobContainer} and {queueMessage.BlobName}");
                var cred = GetClientSecretCredentials(appSettings);


                BlobClientOptions encryptionOptions = GetBlobOptions(log, cred, appSettings.EncryptionKey);
                var blobServiceEncryptionClient = new BlobServiceClient(appSettings.StorageAccount, encryptionOptions);
                var blobContainerEncryptionClient = blobServiceEncryptionClient.GetBlobContainerClient(queueMessage.BlobContainer);
                var blobEncryptionClient = blobContainerEncryptionClient.GetBlobClient(queueMessage.BlobName);

                // get blob metadata first to check if it already has a key
                BlobServiceClient blobServiceDecryptionClient;
                var metadata = GetBlobMetadataAcross(blobEncryptionClient);
                if (metadata.ContainsKey("encryptiondata"))
                {
                    var encryption = JsonConvert.DeserializeObject<EncryptionMetadata>(metadata["encryptiondata"]);

                    // continue if the key is the same 
                    if (encryption.WrappedContentKey.KeyId == appSettings.EncryptionKey)
                    {
                        return;
                    }
                    BlobClientOptions decryptionOptions = GetBlobOptions(log, cred, encryption.WrappedContentKey.KeyId);
                    blobServiceDecryptionClient = new BlobServiceClient(appSettings.StorageAccount, decryptionOptions);                   
                }
                else
                {
                    blobServiceDecryptionClient = new BlobServiceClient(appSettings.StorageAccount);
                }

                var blobContainerDecryptionClient = blobServiceDecryptionClient.GetBlobContainerClient(queueMessage.BlobContainer);
                var blobDecryptionClient = blobContainerDecryptionClient.GetBlobClient(queueMessage.BlobName);

                await DownloadAndEncryptBlob(blobEncryptionClient, blobDecryptionClient, metadata, log);
                log.LogInformation($"Function finished");

                return;
            }
            catch (Exception ex)
            {
                log.LogError(ex.Message);
                log.LogError(ex.StackTrace);
                throw;
            }

        }

        private static async Task DownloadAndEncryptBlob(BlobClient blobEncryptionClient, BlobClient blobDecryptionClient, Dictionary<string, string> metadata, ILogger log)
        {

            using (var memoryStream = new MemoryStream())
            {
                await blobDecryptionClient.DownloadToAsync(memoryStream);

                // This is to log out the content of the blob
                //var text = Encoding.UTF8.GetString(memoryStream.ToArray());
                //log.LogInformation(text);


                memoryStream.Position = 0;
                await blobEncryptionClient.UploadAsync(memoryStream, overwrite: true);
                // Fix for bug. Please see https://stackoverflow.com/questions/67239116/how-do-you-decrypt-blobs-with-azure-keyvault-keys-in-azure-storage-v12
                if (blobEncryptionClient.GetProperties().Value.Metadata.ContainsKey("encryptiondata"))
                {
                    if (metadata.ContainsKey("encryptiondata"))
                        metadata["encryptiondata"] = blobEncryptionClient.GetProperties().Value.Metadata["encryptiondata"];
                    else
                        metadata.Add("encryptiondata", blobEncryptionClient.GetProperties().Value.Metadata["encryptiondata"]);
                }

                await blobEncryptionClient.SetMetadataAsync(metadata);
            }
          
        }

        private static Dictionary<string, string> GetBlobMetadataAcross(BlobClient blobClient)
        {
            var myMeta = new Dictionary<string, string>();
            foreach (var existingMeta in blobClient.GetProperties().Value.Metadata)
            {
                if (!myMeta.ContainsKey(existingMeta.Key))
                {
                    myMeta.Add(existingMeta.Key, existingMeta.Value);
                }
            }
            return myMeta;
        }

        private static BlobClientOptions GetBlobOptions(ILogger log, ClientSecretCredential clientSecretCredential, string keyVaultUrl)
        {
            CryptographyClient cryptoClient = new CryptographyClient(new Uri(keyVaultUrl), clientSecretCredential);
            KeyResolver keyResolver = new KeyResolver(clientSecretCredential);

            ClientSideEncryptionOptions encryptionOptions = new ClientSideEncryptionOptions(ClientSideEncryptionVersion.V1_0)
            {
                KeyEncryptionKey = cryptoClient,
                KeyResolver = keyResolver,
                KeyWrapAlgorithm = "RSA-OAEP",
                
            };

            BlobClientOptions options = new SpecializedBlobClientOptions() { ClientSideEncryption = encryptionOptions, };
            return options;
        }

        private static ClientSecretCredential GetClientSecretCredentials(AppSettings appSettings)
        {
            string clientID = appSettings.ServicePrincipalAppId;
            string clientSecret = appSettings.ServicePrincipalPassword;
            string tenant = appSettings.ServicePrincipalTenant;
            var cred = new ClientSecretCredential(tenant, clientID, clientSecret);
            return cred;
        }

      

       
    }
}

Environment:

Name and version of the Library package used:
Azure.Core 1.20.0
Azure.Identity 1.4.1
Azure.Security.KeyVault.Keys 4.2.0
Azure.Security.KeyVault.secrets 4.2.0
Azure.Storage.Blobs : 12.10.0
Azure.Storage.Queues 12.8.0
Microsoft.Azure.KeyVault.Core 3.0.5
Microsoft.Azure.WebJobs.Extensions.storage 4.0.5
Microsoft.net.sdk.functions 3.0.13

Hosting platform or OS and .NET runtime version (dotnet --info output for .NET Core projects):
Azure Function 64 bit - Windows - West US

IDE and version : [e.g. Visual Studio 16.3]
Visual Studio 2019 for mac and windows

@jaschrep-msft
Copy link
Member

@wonderphil thank you! I will look into this with your sample when I have the time. However, at a glance, it looks like you've provided me with code that only does the download, decrypt, reencrypt, and reupload. The initial upload isn't present. Depending on what root cause is, that part may be relevant. If you could convert (or wrap) this sample to cut the queue out of the way and just upload a new blob that will still produce this issue, I can look into this with my own creds and account.

If you can't manage a reproduction that way, or if you don't get a consistent reproduction, that's important! Let me know here. But since you actively have an instance of this issue and I have been unable to reproduce one, you're likely to have the code somewhere that can set this situation up. Otherwise, if this code succeeds in decryption with some blob I upload myself, I won't have an actual reproduction.

@wonderphil
Copy link

So out of my testing, I haven't been able to upload a new files and then get the error. I have only been able to reproduce on files that have been in our environment already. I am currently trying to tell if it happens to the same blob every time or different blobs each run, our environment has 300+k blobs so I am going to move into another environment with 10+ blobs for testing clarity

@jaschrep-msft
Copy link
Member

@wonderphil wondering if you've managed to narrow things down in your tests. In the meantime I've noticed something in your sample:

await blobEncryptionClient.UploadAsync(memoryStream, overwrite: true);
// Fix for bug. Please see https://stackoverflow.com/questions/67239116/how-do-you-decrypt-blobs-with-azure-keyvault-keys-in-azure-storage-v12
if (blobEncryptionClient.GetProperties().Value.Metadata.ContainsKey("encryptiondata"))
{
    if (metadata.ContainsKey("encryptiondata"))
        metadata["encryptiondata"] = blobEncryptionClient.GetProperties().Value.Metadata["encryptiondata"];
    else
        metadata.Add("encryptiondata", blobEncryptionClient.GetProperties().Value.Metadata["encryptiondata"]);
}

await blobEncryptionClient.SetMetadataAsync(metadata);

I've investigated this metadata bug (which no one seems to have filed in this repo). If I understand the linked stack overflow answer correctly, I can confirm there is a bug with client-side encryption and metadata, but it is not what is linked and don't think it's at play here. The stack overflow answer's claimed bug is the known and accepted result of metadata design (note the warning here).

What interests me about this sample, though, is that it introduces a race condition that wouldn't exist if you just put the metadata on the upload call, e.g. await blobEncryptionClient.UploadAsync(memoryStream, metadata: metadata). This line replaces the entire above block in functionality, resulting in easier maintenance, fewer REST calls, and no chance in between data upload and metadata upload for anyone else to mess with your blob.

It may be your end-to-end system is hitting this race condition. Because the encrypted data and the encryption metadata aren't being uploaded as one, something else could be getting in there and changing one of those two things in between steps. This would result in a mismatch between the encrypted data and its encryption metadata. This would also explain why you can't manage to replicate it with an isolated test.

@amishra-dev amishra-dev added bug This issue requires a change to an existing behavior in the product in order to be resolved. and removed question The issue doesn't require a change to the product in order to be resolved. Most issues start as that labels Nov 30, 2021
@amishra-dev
Copy link
Contributor

@jaschrep-msft any progress on this?

@jaschrep-msft
Copy link
Member

Closing this issue. Feel free to reopen if the problem persists after eliminating this race condition.

@github-actions github-actions bot locked and limited conversation to collaborators Mar 27, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug This issue requires a change to an existing behavior in the product in order to be resolved. Client This issue points to a problem in the data-plane of the library. customer-reported Issues that are reported by GitHub users external to the Azure organization. needs-team-attention Workflow: This issue needs attention from Azure service team or SDK team Service Attention Workflow: This issue is responsible by Azure service team. Storage Storage Service (Queues, Blobs, Files)
Projects
None yet
Development

No branches or pull requests

9 participants