Skip to content

Commit 249b29c

Browse files
authored
feat: "Spanify" DataProtector with IBufferWriter<byte> (#64262)
1 parent c789895 commit 249b29c

File tree

50 files changed

+3690
-1030
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+3690
-1030
lines changed

AspNetCore.slnx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,9 @@
160160
<Project Path="src/DataProtection/Abstractions/src/Microsoft.AspNetCore.DataProtection.Abstractions.csproj" />
161161
<Project Path="src/DataProtection/Abstractions/test/Microsoft.AspNetCore.DataProtection.Abstractions.Tests.csproj" />
162162
</Folder>
163+
<Folder Name="/src/DataProtection/benchmarks/">
164+
<Project Path="src/DataProtection/benchmarks/Microsoft.AspNetCore.DataProtection.MicroBenchmarks/Microsoft.AspNetCore.DataProtection.MicroBenchmarks.csproj" />
165+
</Folder>
163166
<Folder Name="/src/DataProtection/Cryptography.Internal/">
164167
<Project Path="src/DataProtection/Cryptography.Internal/src/Microsoft.AspNetCore.Cryptography.Internal.csproj" />
165168
<Project Path="src/DataProtection/Cryptography.Internal/test/Microsoft.AspNetCore.Cryptography.Internal.Tests.csproj" />
@@ -1134,6 +1137,7 @@
11341137
<Project Path="src/SignalR/server/StackExchangeRedis/src/Microsoft.AspNetCore.SignalR.StackExchangeRedis.csproj" />
11351138
<Project Path="src/SignalR/server/StackExchangeRedis/test/Microsoft.AspNetCore.SignalR.StackExchangeRedis.Tests.csproj" />
11361139
</Folder>
1140+
<Folder Name="/src/SiteExtensions/" />
11371141
<Folder Name="/src/SiteExtensions/Microsoft.Web.Xdt.Extensions/">
11381142
<Project Path="src/SiteExtensions/Microsoft.Web.Xdt.Extensions/src/Microsoft.Web.Xdt.Extensions.csproj" />
11391143
<Project Path="src/SiteExtensions/Microsoft.Web.Xdt.Extensions/tests/Microsoft.Web.Xdt.Extensions.Tests.csproj" />
@@ -1181,8 +1185,8 @@
11811185
<Project Path="src/Validation/src/Microsoft.Extensions.Validation.csproj" />
11821186
</Folder>
11831187
<Folder Name="/src/Validation/test/">
1184-
<Project Path="src/Validation/test/Microsoft.Extensions.Validation.Tests/Microsoft.Extensions.Validation.Tests.csproj" />
11851188
<Project Path="src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/Microsoft.Extensions.Validation.GeneratorTests.csproj" />
1189+
<Project Path="src/Validation/test/Microsoft.Extensions.Validation.Tests/Microsoft.Extensions.Validation.Tests.csproj" />
11861190
</Folder>
11871191
<Folder Name="/src/WebEncoders/">
11881192
<Project Path="src/WebEncoders/src/Microsoft.Extensions.WebEncoders.csproj" />
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
#if NET
5+
6+
using System;
7+
using System.Buffers;
8+
using System.Collections.Generic;
9+
using System.Linq;
10+
using System.Text;
11+
using System.Threading.Tasks;
12+
13+
namespace Microsoft.AspNetCore.DataProtection;
14+
15+
/// <summary>
16+
/// An interface that can provide data protection services.
17+
/// Is an optimized version of <see cref="IDataProtector"/>.
18+
/// </summary>
19+
public interface ISpanDataProtector : IDataProtector
20+
{
21+
/// <summary>
22+
/// Cryptographically protects a piece of plaintext data and writes the result to a buffer writer.
23+
/// </summary>
24+
/// <typeparam name="TWriter">The type of buffer writer to write the protected data to.</typeparam>
25+
/// <param name="plaintext">The plaintext data to protect.</param>
26+
/// <param name="destination">The buffer writer to which the protected data will be written.</param>
27+
/// <remarks>
28+
/// This method provides an optimized, streaming alternative to <see cref="IDataProtector.Protect(byte[])"/>.
29+
/// Rather than allocating an intermediate buffer, the protected data is written directly to the provided
30+
/// buffer writer, which can improve performance and reduce memory allocation pressure.
31+
/// The buffer writer is advanced by the total number of bytes written to it.
32+
/// </remarks>
33+
void Protect<TWriter>(ReadOnlySpan<byte> plaintext, ref TWriter destination)
34+
where TWriter : IBufferWriter<byte>, allows ref struct;
35+
36+
/// <summary>
37+
/// Cryptographically unprotects a piece of protected data and writes the result to a buffer writer.
38+
/// </summary>
39+
/// <typeparam name="TWriter">The type of buffer writer to write the unprotected data to.</typeparam>
40+
/// <param name="protectedData">The protected data to unprotect.</param>
41+
/// <param name="destination">The buffer writer to which the unprotected plaintext will be written.</param>
42+
/// <remarks>
43+
/// This method provides an optimized, streaming alternative to <see cref="IDataProtector.Unprotect(byte[])"/>.
44+
/// Rather than allocating an intermediate buffer, the unprotected plaintext is written directly to the provided
45+
/// buffer writer, which can improve performance and reduce memory allocation pressure.
46+
/// The buffer writer is advanced by the total number of bytes written to it.
47+
/// </remarks>
48+
void Unprotect<TWriter>(ReadOnlySpan<byte> protectedData, ref TWriter destination)
49+
where TWriter : IBufferWriter<byte>, allows ref struct;
50+
}
51+
52+
#endif

src/DataProtection/Abstractions/src/Microsoft.AspNetCore.DataProtection.Abstractions.csproj

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@ Microsoft.AspNetCore.DataProtection.IDataProtector</Description>
2222
<Compile Include="$(SharedSourceRoot)CallerArgument\CallerArgumentExpressionAttribute.cs" LinkBase="Shared" />
2323
</ItemGroup>
2424

25+
<ItemGroup Condition="'$(TargetFramework)' != '$(DefaultNetCoreTargetFramework)'">
26+
<Reference Include="System.Memory" />
27+
</ItemGroup>
28+
29+
<ItemGroup>
30+
<AdditionalFiles Include="PublicAPI/$(TargetFramework)/PublicAPI.Shipped.txt" />
31+
<AdditionalFiles Include="PublicAPI/$(TargetFramework)/PublicAPI.Unshipped.txt" />
32+
</ItemGroup>
33+
2534
<ItemGroup>
2635
<InternalsVisibleTo Include="Microsoft.AspNetCore.DataProtection.Abstractions.Tests" />
2736
</ItemGroup>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#nullable enable
2+
Microsoft.AspNetCore.DataProtection.ISpanDataProtector
3+
Microsoft.AspNetCore.DataProtection.ISpanDataProtector.Protect<TWriter>(System.ReadOnlySpan<byte> plaintext, ref TWriter destination) -> void
4+
Microsoft.AspNetCore.DataProtection.ISpanDataProtector.Unprotect<TWriter>(System.ReadOnlySpan<byte> protectedData, ref TWriter destination) -> void
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#nullable enable
2+
Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions
3+
Microsoft.AspNetCore.DataProtection.IDataProtectionProvider
4+
Microsoft.AspNetCore.DataProtection.IDataProtectionProvider.CreateProtector(string! purpose) -> Microsoft.AspNetCore.DataProtection.IDataProtector!
5+
Microsoft.AspNetCore.DataProtection.IDataProtector
6+
Microsoft.AspNetCore.DataProtection.IDataProtector.Protect(byte[]! plaintext) -> byte[]!
7+
Microsoft.AspNetCore.DataProtection.IDataProtector.Unprotect(byte[]! protectedData) -> byte[]!
8+
Microsoft.AspNetCore.DataProtection.Infrastructure.IApplicationDiscriminator
9+
Microsoft.AspNetCore.DataProtection.Infrastructure.IApplicationDiscriminator.Discriminator.get -> string?
10+
static Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.CreateProtector(this Microsoft.AspNetCore.DataProtection.IDataProtectionProvider! provider, string! purpose, params string![]! subPurposes) -> Microsoft.AspNetCore.DataProtection.IDataProtector!
11+
static Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.CreateProtector(this Microsoft.AspNetCore.DataProtection.IDataProtectionProvider! provider, System.Collections.Generic.IEnumerable<string!>! purposes) -> Microsoft.AspNetCore.DataProtection.IDataProtector!
12+
static Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.GetDataProtectionProvider(this System.IServiceProvider! services) -> Microsoft.AspNetCore.DataProtection.IDataProtectionProvider!
13+
static Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.GetDataProtector(this System.IServiceProvider! services, string! purpose, params string![]! subPurposes) -> Microsoft.AspNetCore.DataProtection.IDataProtector!
14+
static Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.GetDataProtector(this System.IServiceProvider! services, System.Collections.Generic.IEnumerable<string!>! purposes) -> Microsoft.AspNetCore.DataProtection.IDataProtector!
15+
static Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.Protect(this Microsoft.AspNetCore.DataProtection.IDataProtector! protector, string! plaintext) -> string!
16+
static Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.Unprotect(this Microsoft.AspNetCore.DataProtection.IDataProtector! protector, string! protectedData) -> string!
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#nullable enable
2+
Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions
3+
Microsoft.AspNetCore.DataProtection.IDataProtectionProvider
4+
Microsoft.AspNetCore.DataProtection.IDataProtectionProvider.CreateProtector(string! purpose) -> Microsoft.AspNetCore.DataProtection.IDataProtector!
5+
Microsoft.AspNetCore.DataProtection.IDataProtector
6+
Microsoft.AspNetCore.DataProtection.IDataProtector.Protect(byte[]! plaintext) -> byte[]!
7+
Microsoft.AspNetCore.DataProtection.IDataProtector.Unprotect(byte[]! protectedData) -> byte[]!
8+
Microsoft.AspNetCore.DataProtection.Infrastructure.IApplicationDiscriminator
9+
Microsoft.AspNetCore.DataProtection.Infrastructure.IApplicationDiscriminator.Discriminator.get -> string?
10+
static Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.CreateProtector(this Microsoft.AspNetCore.DataProtection.IDataProtectionProvider! provider, string! purpose, params string![]! subPurposes) -> Microsoft.AspNetCore.DataProtection.IDataProtector!
11+
static Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.CreateProtector(this Microsoft.AspNetCore.DataProtection.IDataProtectionProvider! provider, System.Collections.Generic.IEnumerable<string!>! purposes) -> Microsoft.AspNetCore.DataProtection.IDataProtector!
12+
static Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.GetDataProtectionProvider(this System.IServiceProvider! services) -> Microsoft.AspNetCore.DataProtection.IDataProtectionProvider!
13+
static Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.GetDataProtector(this System.IServiceProvider! services, string! purpose, params string![]! subPurposes) -> Microsoft.AspNetCore.DataProtection.IDataProtector!
14+
static Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.GetDataProtector(this System.IServiceProvider! services, System.Collections.Generic.IEnumerable<string!>! purposes) -> Microsoft.AspNetCore.DataProtection.IDataProtector!
15+
static Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.Protect(this Microsoft.AspNetCore.DataProtection.IDataProtector! protector, string! plaintext) -> string!
16+
static Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.Unprotect(this Microsoft.AspNetCore.DataProtection.IDataProtector! protector, string! protectedData) -> string!

src/DataProtection/DataProtection.slnf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"src\\DataProtection\\Extensions\\test\\Microsoft.AspNetCore.DataProtection.Extensions.Tests.csproj",
1717
"src\\DataProtection\\StackExchangeRedis\\src\\Microsoft.AspNetCore.DataProtection.StackExchangeRedis.csproj",
1818
"src\\DataProtection\\StackExchangeRedis\\test\\Microsoft.AspNetCore.DataProtection.StackExchangeRedis.Tests.csproj",
19+
"src\\DataProtection\\benchmarks\\Microsoft.AspNetCore.DataProtection.MicroBenchmarks\\Microsoft.AspNetCore.DataProtection.MicroBenchmarks.csproj",
1920
"src\\DataProtection\\samples\\CustomEncryptorSample\\CustomEncryptorSample.csproj",
2021
"src\\DataProtection\\samples\\EntityFrameworkCoreSample\\EntityFrameworkCoreSample.csproj",
2122
"src\\DataProtection\\samples\\KeyManagementSample\\KeyManagementSample.csproj",

0 commit comments

Comments
 (0)