-
Notifications
You must be signed in to change notification settings - Fork 10.5k
feat: "Spanify" DataProtector with GetSize/TryProtect pattern #62903
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
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds new non-allocating "Span-based" APIs to the DataProtection interfaces, specifically implementing the Protect/Encrypt functionality without requiring heap allocations. The new APIs allow callers to get the size of protected data upfront and then encrypt directly into a provided buffer.
Key changes:
- Added
GetProtectedSize()andTryProtect()methods toIDataProtectorinterface - Added
GetEncryptedSize()andTryEncrypt()methods toIAuthenticatedEncryptorinterface - Implemented these methods across all encryptor types (AES-GCM, CBC, CNG variants, Managed implementations)
Reviewed Changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/DataProtection/Abstractions/src/IDataProtector.cs | Added new span-based APIs to the main data protector interface |
| src/DataProtection/DataProtection/src/AuthenticatedEncryption/IAuthenticatedEncryptor.cs | Added new span-based APIs to the authenticated encryptor interface |
| src/DataProtection/DataProtection/src/KeyManagement/KeyRingBasedDataProtector.cs | Core implementation of new APIs with proper header management |
| src/DataProtection/DataProtection/src/Managed/ManagedAuthenticatedEncryptor.cs | Implementation for managed (non-CNG) encryption algorithms |
| src/DataProtection/DataProtection/src/Managed/AesGcmAuthenticatedEncryptor.cs | Implementation for AES-GCM encryption |
| src/DataProtection/DataProtection/src/Cng/CbcAuthenticatedEncryptor.cs | Implementation for CNG-based CBC encryption |
| src/DataProtection/DataProtection/src/Cng/CngGcmAuthenticatedEncryptor.cs | Implementation for CNG-based GCM encryption |
| src/DataProtection/Extensions/src/TimeLimitedDataProtector.cs | Updated time-limited protector to support new APIs |
| Multiple test files | Comprehensive test coverage for the new functionality |
src/DataProtection/DataProtection/src/Managed/ManagedAuthenticatedEncryptor.cs
Show resolved
Hide resolved
halter73
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should update our existing code that calls into IDataProtecter to use the new methods to get good test coverage of the new methods.
src/DataProtection/DataProtection/src/KeyManagement/KeyRingBasedSpanDataProtector.cs
Outdated
Show resolved
Hide resolved
src/DataProtection/DataProtection/src/KeyManagement/KeyRingBasedSpanDataProtector.cs
Outdated
Show resolved
Hide resolved
src/DataProtection/DataProtection/src/KeyManagement/KeyRingBasedSpanDataProtector.cs
Outdated
Show resolved
Hide resolved
src/DataProtection/DataProtection/src/KeyManagement/KeyRingBasedSpanDataProtector.cs
Outdated
Show resolved
Hide resolved
|
/azp run |
|
Azure Pipelines successfully started running 2 pipeline(s). |
|
Looks like this PR hasn't been active for some time and the codebase could have been changed in the meantime. |

Please, review with caution! This is cryptography and failures here can be pretty dramatic...
This PR introduces 2 new interfaces which allow usage of DataProtection via
Span<byte>:ISpanDataProtectorandIAuthenticatedEncryptor.Details
Current PR proposes extra interfaces
ISpanDataProtectorandISpanAuthenticatedEncryptor(Inspiration taken from ISpanFormattable : IFormattable). The APIs are:and
From the implementation standpoint, these APIs are basically doing what existing
Protect() / Unprotect()andEncrypt() / Decrypt()do, but without allocating a result array and instead filling in theSpan<byte> destination.For
IAuthenticatedEncryptors I tried to reuse theTryEncrypt/TryDecryptfromEncrypt/Decryptwhere possible to reduce code duplication.Registrations
IDataProtectoralso should implementIDataProtectionProviderwhich provides the protector instance:And in default DI (
AddDataProtection)IDataProtectoris created in such a manner:https://github.com/dotnet/aspnetcore/blob/b52c80fef2b8bf5239c7643d9c79d1029bb6c988/src/DataProtection/DataProtection/src/DataProtectionServiceCollectionExtensions.cs#L89C13-L95C14
I dont want to introduce more APIs and interfaces for providing
ISpanDataProtectorand instead when providing I am doing a lookup to determine whether it is possible to returnISpanDataProtectororIDataProtector. Users will then be able to differentiate based on their needs and registrations.Usage
Having
IDataProtector:and the same goes for
IAuthenticatedEncryptor, but I doubt majority of users implement their ownIAuthenticatedEncryptor.Testing
In order to verify correctness of the changes I've created
RoundtripEncryptionHelpers.AssertTryEncryptTryDecryptParitywhere I try to call Encrypt/Decrypt in different order forIDataProtectorandIAuthenticatedEncryptorto ensure any order of operations give a correct roundtrip result.I will also change any other place in aspnetcore to use this API to make sure new APIs behave correctly and in the same way as existing APIs
Fixes #44758