Skip to content
Open
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
b1a4b40
implement encrypt size calculation
DeagleGross Jul 15, 2025
aecf589
implement geteencyrptedsize
DeagleGross Jul 16, 2025
198501e
try encrypt
DeagleGross Jul 16, 2025
a4e3ca4
simplify net10 impl
DeagleGross Jul 16, 2025
8d49973
simplify tests and cbc
DeagleGross Jul 16, 2025
ae6fb76
cnggcm
DeagleGross Jul 16, 2025
9caa72e
aes
DeagleGross Jul 16, 2025
b9b45b2
something
DeagleGross Jul 16, 2025
b3e5b42
key ring based part
DeagleGross Jul 16, 2025
4eb96e3
Merge branch 'main' into dmkorolev/dataprotector-spans
DeagleGross Jul 23, 2025
afd344c
refactor
DeagleGross Jul 24, 2025
fd7f929
finally passed!
DeagleGross Jul 24, 2025
afbad47
generate test for plain text
DeagleGross Jul 24, 2025
34d52e7
correct empty plain text scenario
DeagleGross Jul 24, 2025
18eec02
minor improvements
DeagleGross Jul 24, 2025
9e4a634
hide in internal + docs
DeagleGross Jul 24, 2025
8829566
to public api - its a nightmare to implement otherwise
DeagleGross Jul 24, 2025
5f240c2
fix build
DeagleGross Jul 24, 2025
8d275ac
wip
DeagleGross Jul 24, 2025
8f5b762
re-review
DeagleGross Jul 24, 2025
efd4f79
implement timelimitedDataProtector
DeagleGross Jul 24, 2025
6142309
introduce `IOptimizedDataProtector`
DeagleGross Jul 25, 2025
ae5bb82
introduce optimized IAuthenticatedEncryptor
DeagleGross Jul 25, 2025
0646d1a
fix dataprotector usage
DeagleGross Jul 25, 2025
3d37955
fix build?
DeagleGross Jul 25, 2025
bbfce53
move to a separate ISpanAuthenticatedEncryptor
DeagleGross Jul 25, 2025
b0fc525
refactor to ISpan interfaces
DeagleGross Jul 28, 2025
d4b1fc9
correct span allocation
DeagleGross Jul 28, 2025
146af98
use TryEncrypt from Encrypt()
DeagleGross Jul 28, 2025
630e451
fix
DeagleGross Jul 28, 2025
983b69f
Merge branch 'main' into dmkorolev/dataprotector-spans
DeagleGross Jul 31, 2025
948052c
init
DeagleGross Aug 1, 2025
37a3277
inheritance!
DeagleGross Aug 2, 2025
0e1dfd6
separate impl
DeagleGross Aug 2, 2025
35f7522
distinguish impl
DeagleGross Aug 2, 2025
05fdcc3
other impls
DeagleGross Aug 3, 2025
f223b45
tests & api
DeagleGross Aug 3, 2025
c029655
init decrypt
DeagleGross Aug 3, 2025
fe478d2
cnggcm
DeagleGross Aug 4, 2025
72aecba
init cbc
DeagleGross Aug 4, 2025
29e7622
cbc
DeagleGross Aug 4, 2025
516729c
mockable
DeagleGross Aug 4, 2025
21b7d87
AesGcm
DeagleGross Aug 4, 2025
5a1ea5c
impl managed
DeagleGross Aug 4, 2025
f561796
fix slices everywhere + rollback managedauth to a proper impl
DeagleGross Aug 4, 2025
c1b203f
ispanauth: decryption ready
DeagleGross Aug 4, 2025
614b569
intro ispandataprotector.unprotect \ fix warnings \ dont change timel…
DeagleGross Aug 5, 2025
9f24867
span data protector unprotect
DeagleGross Aug 6, 2025
27f7609
"final" review
DeagleGross Aug 6, 2025
e3726ec
avoid blank lines!
DeagleGross Aug 6, 2025
bc44688
push project for microbenchmarks
DeagleGross Aug 6, 2025
57e9f85
Merge branch 'main' into dmkorolev/dataprotector-spans
DeagleGross Sep 12, 2025
4eadb9b
PR review comments + check length upfront
DeagleGross Sep 12, 2025
e6d0d0a
fix warnings
DeagleGross Oct 9, 2025
41c2163
fix warnings in benchmarks
DeagleGross Oct 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/DataProtection/Abstractions/src/IDataProtector.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Diagnostics.CodeAnalysis;

namespace Microsoft.AspNetCore.DataProtection;
Expand All @@ -26,4 +27,22 @@ public interface IDataProtector : IDataProtectionProvider
/// Thrown if the protected data is invalid or malformed.
/// </exception>
byte[] Unprotect(byte[] protectedData);

#if NET10_0_OR_GREATER
/// <summary>
/// Returns the size of the encrypted data for a given plaintext length.
/// </summary>
/// <param name="plainText">The plain text that will be encrypted later</param>
/// <returns>The length of the encrypted data</returns>
int GetProtectedSize(ReadOnlySpan<byte> plainText);

/// <summary>
/// Attempts to encrypt and tamper-proof a piece of data.
/// </summary>
/// <param name="plainText">The input to encrypt.</param>
/// <param name="destination">The ciphertext blob, including authentication tag.</param>
/// <param name="bytesWritten">When this method returns, the total number of bytes written into destination</param>
/// <returns>true if destination is long enough to receive the encrypted data; otherwise, false.</returns>
bool TryProtect(ReadOnlySpan<byte> plainText, Span<byte> destination, out int bytesWritten);
#endif
}
2 changes: 2 additions & 0 deletions src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
#nullable enable
Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: macOS arm64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: macOS arm64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux ARM)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux ARM)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux x64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux x64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux ARM64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux ARM64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux Musl ARM)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux Musl ARM)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux Musl ARM64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux Musl ARM64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: macOS x64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: macOS x64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-quarantined-pr (Tests: Ubuntu x64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-quarantined-pr (Tests: Ubuntu x64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Test: macOS)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Test: macOS)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux Musl x64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux Musl x64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Test: Ubuntu x64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Test: Ubuntu x64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-quarantined-pr

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 2 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L2

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(2,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText) -> int' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)
Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: macOS arm64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: macOS arm64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux ARM)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux ARM)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux x64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux x64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux ARM64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux ARM64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux Musl ARM)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux Musl ARM)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux Musl ARM64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux Musl ARM64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: macOS x64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: macOS x64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-quarantined-pr (Tests: Ubuntu x64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-quarantined-pr (Tests: Ubuntu x64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Test: macOS)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Test: macOS)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux Musl x64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Build: Linux Musl x64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Test: Ubuntu x64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci (Build Test: Ubuntu x64)

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-quarantined-pr

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check failure on line 3 in src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt

View check run for this annotation

Azure Pipelines / aspnetcore-ci

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt#L3

src/DataProtection/Abstractions/src/PublicAPI.Unshipped.txt(3,1): error RS0017: (NETCORE_ENGINEERING_TELEMETRY=Build) Symbol 'Microsoft.AspNetCore.DataProtection.IDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool' is part of the declared API, but is either not public or could not be found (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,27 @@ public interface IAuthenticatedEncryptor
/// <returns>The ciphertext blob, including authentication tag.</returns>
/// <remarks>All cryptography-related exceptions should be homogenized to CryptographicException.</remarks>
byte[] Encrypt(ArraySegment<byte> plaintext, ArraySegment<byte> additionalAuthenticatedData);

#if NET10_0_OR_GREATER
/// <summary>
/// Returns the size of the encrypted data for a given plaintext length.
/// </summary>
/// <param name="plainTextLength">Length of the plain text that will be encrypted later</param>
/// <returns>The length of the encrypted data</returns>
int GetEncryptedSize(int plainTextLength);

/// <summary>
/// Attempts to encrypt and tamper-proof a piece of data.
/// </summary>
/// <param name="plaintext">The input to encrypt.</param>
/// <param name="additionalAuthenticatedData">
/// A piece of data which will not be included in
/// the returned ciphertext but which will still be covered by the authentication tag.
/// This input may be zero bytes in length. The same AAD must be specified in the corresponding decryption call.
/// </param>
/// <param name="destination">The ciphertext blob, including authentication tag.</param>
/// <param name="bytesWritten">When this method returns, the total number of bytes written into destination</param>
/// <returns>true if destination is long enough to receive the encrypted data; otherwise, false.</returns>
bool TryEncrypt(ReadOnlySpan<byte> plaintext, ReadOnlySpan<byte> additionalAuthenticatedData, Span<byte> destination, out int bytesWritten);
#endif
}
145 changes: 143 additions & 2 deletions src/DataProtection/DataProtection/src/Cng/CbcAuthenticatedEncryptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Runtime.CompilerServices;
using Microsoft.AspNetCore.Cryptography;
using Microsoft.AspNetCore.Cryptography.Cng;
using Microsoft.AspNetCore.Cryptography.SafeHandles;
Expand Down Expand Up @@ -299,6 +300,113 @@ private void DoCbcEncrypt(BCryptKeyHandle symmetricKeyHandle, byte* pbIV, byte*
CryptoUtil.Assert(dwEncryptedBytes == cbOutput, "dwEncryptedBytes == cbOutput");
}

#if NET10_0_OR_GREATER
public override int GetEncryptedSize(int plainTextLength)
{
uint paddedCiphertextLength = GetCbcEncryptedOutputSizeWithPadding((uint)plainTextLength);
return checked((int)(KEY_MODIFIER_SIZE_IN_BYTES + _symmetricAlgorithmBlockSizeInBytes + paddedCiphertextLength + _hmacAlgorithmDigestLengthInBytes));
}

public override bool TryEncrypt(ReadOnlySpan<byte> plaintext, ReadOnlySpan<byte> additionalAuthenticatedData, Span<byte> destination, out int bytesWritten)
{
bytesWritten = 0;

try
{
// This buffer will be used to hold the symmetric encryption and HMAC subkeys
// used in the generation of this payload.
var cbTempSubkeys = checked(_symmetricAlgorithmSubkeyLengthInBytes + _hmacAlgorithmSubkeyLengthInBytes);
byte* pbTempSubkeys = stackalloc byte[checked((int)cbTempSubkeys)];

try
{
// Randomly generate the key modifier and IV.
var cbKeyModifierAndIV = checked(KEY_MODIFIER_SIZE_IN_BYTES + _symmetricAlgorithmBlockSizeInBytes);
byte* pbKeyModifierAndIV = stackalloc byte[checked((int)cbKeyModifierAndIV)];
_genRandom.GenRandom(pbKeyModifierAndIV, cbKeyModifierAndIV);

// Calculate offsets
byte* pbKeyModifier = pbKeyModifierAndIV;
byte* pbIV = &pbKeyModifierAndIV[KEY_MODIFIER_SIZE_IN_BYTES];

// Use the KDF to generate a new symmetric encryption and HMAC subkey
fixed (byte* pbAdditionalAuthenticatedData = additionalAuthenticatedData)
{
_sp800_108_ctr_hmac_provider.DeriveKeyWithContextHeader(
pbLabel: pbAdditionalAuthenticatedData,
cbLabel: (uint)additionalAuthenticatedData.Length,
contextHeader: _contextHeader,
pbContext: pbKeyModifier,
cbContext: KEY_MODIFIER_SIZE_IN_BYTES,
pbDerivedKey: pbTempSubkeys,
cbDerivedKey: cbTempSubkeys);
}

// Calculate offsets
byte* pbSymmetricEncryptionSubkey = pbTempSubkeys;
byte* pbHmacSubkey = &pbTempSubkeys[_symmetricAlgorithmSubkeyLengthInBytes];

using (var symmetricKeyHandle = _symmetricAlgorithmHandle.GenerateSymmetricKey(pbSymmetricEncryptionSubkey, _symmetricAlgorithmSubkeyLengthInBytes))
{
// Get the padded output size
byte dummy;
fixed (byte* pbPlaintextArray = plaintext)
{
var pbPlaintext = (pbPlaintextArray != null) ? pbPlaintextArray : &dummy;
var cbOutputCiphertext = GetCbcEncryptedOutputSizeWithPadding(symmetricKeyHandle, pbPlaintext, (uint)plaintext.Length);

fixed (byte* pbDestination = destination)
{
// Calculate offsets in destination
byte* pbOutputKeyModifier = pbDestination;
byte* pbOutputIV = &pbOutputKeyModifier[KEY_MODIFIER_SIZE_IN_BYTES];
byte* pbOutputCiphertext = &pbOutputIV[_symmetricAlgorithmBlockSizeInBytes];
byte* pbOutputHmac = &pbOutputCiphertext[cbOutputCiphertext];

// Copy key modifier and IV to destination
Unsafe.CopyBlock(pbOutputKeyModifier, pbKeyModifierAndIV, cbKeyModifierAndIV);
bytesWritten += checked((int)cbKeyModifierAndIV);

// Perform CBC encryption directly into destination
DoCbcEncrypt(
symmetricKeyHandle: symmetricKeyHandle,
pbIV: pbIV,
pbInput: pbPlaintext,
cbInput: (uint)plaintext.Length,
pbOutput: pbOutputCiphertext,
cbOutput: cbOutputCiphertext);
bytesWritten += checked((int)cbOutputCiphertext);

// Compute the HMAC over the IV and the ciphertext
using (var hashHandle = _hmacAlgorithmHandle.CreateHmac(pbHmacSubkey, _hmacAlgorithmSubkeyLengthInBytes))
{
hashHandle.HashData(
pbInput: pbOutputIV,
cbInput: checked(_symmetricAlgorithmBlockSizeInBytes + cbOutputCiphertext),
pbHashDigest: pbOutputHmac,
cbHashDigest: _hmacAlgorithmDigestLengthInBytes);
}
bytesWritten += checked((int)_hmacAlgorithmDigestLengthInBytes);

return true;
}
}
}
}
finally
{
// Buffer contains sensitive material; delete it.
UnsafeBufferUtil.SecureZeroMemory(pbTempSubkeys, cbTempSubkeys);
}
}
catch (Exception ex) when (ex.RequiresHomogenization())
{
// Homogenize all exceptions to CryptographicException.
throw Error.CryptCommon_GenericError(ex);
}
}
#endif

protected override byte[] EncryptImpl(byte* pbPlaintext, uint cbPlaintext, byte* pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData, uint cbPreBuffer, uint cbPostBuffer)
{
// This buffer will be used to hold the symmetric encryption and HMAC subkeys
Expand Down Expand Up @@ -387,14 +495,47 @@ protected override byte[] EncryptImpl(byte* pbPlaintext, uint cbPlaintext, byte*
}
}

/// <summary>
/// Should be used only for expected encrypt/decrypt size calculation,
/// use the other overload <see cref="GetCbcEncryptedOutputSizeWithPadding(BCryptKeyHandle, byte*, uint)"/>
/// for the actual encryption algorithm
/// </summary>
private uint GetCbcEncryptedOutputSizeWithPadding(uint cbInput)
{
// Create a temporary key with dummy data for size calculation only
// The actual key material doesn't matter for size calculation
byte* pbDummyKey = stackalloc byte[checked((int)_symmetricAlgorithmSubkeyLengthInBytes)];
// Leave pbDummyKey uninitialized (all zeros) - BCrypt doesn't care for size queries

using var tempKeyHandle = _symmetricAlgorithmHandle.GenerateSymmetricKey(pbDummyKey, _symmetricAlgorithmSubkeyLengthInBytes);

// Use uninitialized IV and input data - only the lengths matter
byte* pbDummyIV = stackalloc byte[checked((int)_symmetricAlgorithmBlockSizeInBytes)];
byte* pbDummyInput = stackalloc byte[checked((int)cbInput)];

var ntstatus = UnsafeNativeMethods.BCryptEncrypt(
hKey: tempKeyHandle,
pbInput: pbDummyInput,
cbInput: cbInput,
pPaddingInfo: null,
pbIV: pbDummyIV,
cbIV: _symmetricAlgorithmBlockSizeInBytes,
pbOutput: null, // NULL output = size query only
cbOutput: 0,
pcbResult: out var dwResult,
dwFlags: BCryptEncryptFlags.BCRYPT_BLOCK_PADDING);
UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus);

return dwResult;
}

private uint GetCbcEncryptedOutputSizeWithPadding(BCryptKeyHandle symmetricKeyHandle, byte* pbInput, uint cbInput)
{
// ok for this memory to remain uninitialized since nobody depends on it
byte* pbIV = stackalloc byte[checked((int)_symmetricAlgorithmBlockSizeInBytes)];

// Calling BCryptEncrypt with a null output pointer will cause it to return the total number
// of bytes required for the output buffer.
uint dwResult;
var ntstatus = UnsafeNativeMethods.BCryptEncrypt(
hKey: symmetricKeyHandle,
pbInput: pbInput,
Expand All @@ -404,7 +545,7 @@ private uint GetCbcEncryptedOutputSizeWithPadding(BCryptKeyHandle symmetricKeyHa
cbIV: _symmetricAlgorithmBlockSizeInBytes,
pbOutput: null,
cbOutput: 0,
pcbResult: out dwResult,
pcbResult: out var dwResult,
dwFlags: BCryptEncryptFlags.BCRYPT_BLOCK_PADDING);
UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using Microsoft.AspNetCore.Cryptography;
using Microsoft.AspNetCore.Cryptography.Cng;
using Microsoft.AspNetCore.Cryptography.SafeHandles;
Expand Down Expand Up @@ -230,6 +231,86 @@ private void DoGcmEncrypt(byte* pbKey, uint cbKey, byte* pbNonce, byte* pbPlaint
}
}

#if NET10_0_OR_GREATER
public override int GetEncryptedSize(int plainTextLength)
{
// A buffer to hold the key modifier, nonce, encrypted data, and tag.
// In GCM, the encrypted output will be the same length as the plaintext input.
return checked((int)(KEY_MODIFIER_SIZE_IN_BYTES + NONCE_SIZE_IN_BYTES + plainTextLength + TAG_SIZE_IN_BYTES));
}

public override bool TryEncrypt(ReadOnlySpan<byte> plaintext, ReadOnlySpan<byte> additionalAuthenticatedData, Span<byte> destination, out int bytesWritten)
{
bytesWritten = 0;

try
{
fixed (byte* pbDestination = destination)
{
// Calculate offsets
byte* pbKeyModifier = pbDestination;
byte* pbNonce = &pbKeyModifier[KEY_MODIFIER_SIZE_IN_BYTES];
byte* pbEncryptedData = &pbNonce[NONCE_SIZE_IN_BYTES];
byte* pbAuthTag = &pbEncryptedData[plaintext.Length];

// Randomly generate the key modifier and nonce
_genRandom.GenRandom(pbKeyModifier, KEY_MODIFIER_SIZE_IN_BYTES + NONCE_SIZE_IN_BYTES);
bytesWritten += checked((int)(KEY_MODIFIER_SIZE_IN_BYTES + NONCE_SIZE_IN_BYTES));

// At this point, retVal := { preBuffer | keyModifier | nonce | _____ | _____ | postBuffer }

// Use the KDF to generate a new symmetric block cipher key
// We'll need a temporary buffer to hold the symmetric encryption subkey
byte* pbSymmetricEncryptionSubkey = stackalloc byte[checked((int)_symmetricAlgorithmSubkeyLengthInBytes)];
try
{
fixed (byte* pbAdditionalAuthenticatedData = additionalAuthenticatedData)
{
_sp800_108_ctr_hmac_provider.DeriveKeyWithContextHeader(
pbLabel: pbAdditionalAuthenticatedData,
cbLabel: (uint)additionalAuthenticatedData.Length,
contextHeader: _contextHeader,
pbContext: pbKeyModifier,
cbContext: KEY_MODIFIER_SIZE_IN_BYTES,
pbDerivedKey: pbSymmetricEncryptionSubkey,
cbDerivedKey: _symmetricAlgorithmSubkeyLengthInBytes);
}

// Perform the encryption operation
byte dummy;
fixed (byte* pbPlaintextArray = plaintext)
{
var pbPlaintext = (pbPlaintextArray != null) ? pbPlaintextArray : &dummy;

DoGcmEncrypt(
pbKey: pbSymmetricEncryptionSubkey,
cbKey: _symmetricAlgorithmSubkeyLengthInBytes,
pbNonce: pbNonce,
pbPlaintextData: pbPlaintext,
cbPlaintextData: (uint)plaintext.Length,
pbEncryptedData: pbEncryptedData,
pbTag: pbAuthTag);
}

// At this point, retVal := { preBuffer | keyModifier | nonce | encryptedData | authenticationTag | postBuffer }
// And we're done!
bytesWritten += plaintext.Length + checked((int)TAG_SIZE_IN_BYTES);
return true;
}
finally
{
// The buffer contains key material, so delete it.
UnsafeBufferUtil.SecureZeroMemory(pbSymmetricEncryptionSubkey, _symmetricAlgorithmSubkeyLengthInBytes);
}
}
}
catch (Exception ex) when (ex.RequiresHomogenization())
{
throw Error.CryptCommon_GenericError(ex);
}
}
#endif

protected override byte[] EncryptImpl(byte* pbPlaintext, uint cbPlaintext, byte* pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData, uint cbPreBuffer, uint cbPostBuffer)
{
// Allocate a buffer to hold the key modifier, nonce, encrypted data, and tag.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,9 @@ public byte[] Encrypt(ArraySegment<byte> plaintext, ArraySegment<byte> additiona
}

protected abstract byte[] EncryptImpl(byte* pbPlaintext, uint cbPlaintext, byte* pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData, uint cbPreBuffer, uint cbPostBuffer);

#if NET10_0_OR_GREATER
public abstract int GetEncryptedSize(int plainTextLength);
public abstract bool TryEncrypt(ReadOnlySpan<byte> plainText, ReadOnlySpan<byte> additionalAuthenticatedData, Span<byte> destination, out int bytesWritten);
#endif
}
Loading
Loading