Skip to content

Commit 948052c

Browse files
committed
init
1 parent 983b69f commit 948052c

File tree

5 files changed

+510
-86
lines changed

5 files changed

+510
-86
lines changed

src/DataProtection/Abstractions/src/ISpanDataProtector.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,10 @@ public interface ISpanDataProtector : IDataProtector
1717
{
1818
/// <summary>
1919
/// Determines the size of the protected data in order to then use <see cref="TryProtect(ReadOnlySpan{byte}, Span{byte}, out int)"/>."/>.
20-
/// <br/> Returns the boolean representing if current implementation of data protector supports <see cref="ISpanDataProtector"/> or not.
21-
/// If it does not (returns false), then one needs to fallback to <see cref="IDataProtector"/> and use <see cref="IDataProtector.Protect(byte[])"/> and <see cref="IDataProtector.Unprotect(byte[])"/> methods instead.
2220
/// </summary>
2321
/// <param name="plainText">The plain text that will be encrypted later</param>
24-
/// <param name="cipherTextLength">The length of the expected cipher text.</param>
25-
/// <returns>true, if <see cref="ISpanDataProtector"/> is supported. False if a fallback to <see cref="IDataProtector"/> is required.</returns>
26-
bool TryGetProtectedSize(ReadOnlySpan<byte> plainText, out int cipherTextLength);
22+
/// <returns>The size of the protected data.</returns>
23+
int GetProtectedSize(ReadOnlySpan<byte> plainText);
2724

2825
/// <summary>
2926
/// Attempts to encrypt and tamper-proof a piece of data.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#nullable enable
22
Microsoft.AspNetCore.DataProtection.ISpanDataProtector
3-
Microsoft.AspNetCore.DataProtection.ISpanDataProtector.TryGetProtectedSize(System.ReadOnlySpan<byte> plainText, out int cipherTextLength) -> bool
3+
Microsoft.AspNetCore.DataProtection.ISpanDataProtector.GetProtectedSize(System.ReadOnlySpan<byte> plainText, out int cipherTextLength) -> int
44
Microsoft.AspNetCore.DataProtection.ISpanDataProtector.TryProtect(System.ReadOnlySpan<byte> plainText, System.Span<byte> destination, out int bytesWritten) -> bool

src/DataProtection/DataProtection/src/KeyManagement/KeyRingBasedDataProtector.cs

Lines changed: 1 addition & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
namespace Microsoft.AspNetCore.DataProtection.KeyManagement;
2323

24-
internal sealed unsafe class KeyRingBasedDataProtector : ISpanDataProtector, IPersistedDataProtector
24+
internal unsafe class KeyRingBasedDataProtector : IDataProtector, IPersistedDataProtector
2525
{
2626
// This magic header identifies a v0 protected data blob. It's the high 28 bits of the SHA1 hash of
2727
// "Microsoft.AspNet.DataProtection.KeyManagement.KeyRingBasedDataProtector" [US-ASCII], big-endian.
@@ -34,8 +34,6 @@ internal sealed unsafe class KeyRingBasedDataProtector : ISpanDataProtector, IPe
3434
private readonly IKeyRingProvider _keyRingProvider;
3535
private readonly ILogger? _logger;
3636

37-
private static readonly int _magicHeaderKeyIdSize = sizeof(uint) + sizeof(Guid);
38-
3937
public KeyRingBasedDataProtector(IKeyRingProvider keyRingProvider, ILogger? logger, string[]? originalPurposes, string newPurpose)
4038
{
4139
Debug.Assert(keyRingProvider != null);
@@ -92,82 +90,6 @@ public byte[] DangerousUnprotect(byte[] protectedData, bool ignoreRevocationErro
9290
return retVal;
9391
}
9492

95-
public bool TryGetProtectedSize(ReadOnlySpan<byte> plainText, out int cipherTextLength)
96-
{
97-
cipherTextLength = default;
98-
99-
// Get the current key ring to access the encryptor
100-
var currentKeyRing = _keyRingProvider.GetCurrentKeyRing();
101-
var defaultEncryptor = currentKeyRing.DefaultAuthenticatedEncryptor;
102-
if (defaultEncryptor is not ISpanAuthenticatedEncryptor optimizedAuthenticatedEncryptor)
103-
{
104-
return false;
105-
}
106-
CryptoUtil.Assert(optimizedAuthenticatedEncryptor != null, "optimizedAuthenticatedEncryptor != null");
107-
108-
// We allocate a 20-byte pre-buffer so that we can inject the magic header and key id into the return value.
109-
// See Protect() / TryProtect() for details
110-
cipherTextLength = _magicHeaderKeyIdSize + optimizedAuthenticatedEncryptor.GetEncryptedSize(plainText.Length);
111-
return true;
112-
}
113-
114-
public bool TryProtect(ReadOnlySpan<byte> plaintext, Span<byte> destination, out int bytesWritten)
115-
{
116-
try
117-
{
118-
// Perform the encryption operation using the current default encryptor.
119-
var currentKeyRing = _keyRingProvider.GetCurrentKeyRing();
120-
var defaultKeyId = currentKeyRing.DefaultKeyId;
121-
var defaultEncryptor = currentKeyRing.DefaultAuthenticatedEncryptor;
122-
if (defaultEncryptor is not ISpanAuthenticatedEncryptor spanEncryptor)
123-
{
124-
throw new NotSupportedException("The current default encryptor does not support optimized protection.");
125-
}
126-
CryptoUtil.Assert(spanEncryptor != null, "optimizedAuthenticatedEncryptor != null");
127-
128-
if (_logger.IsDebugLevelEnabled())
129-
{
130-
_logger.PerformingProtectOperationToKeyWithPurposes(defaultKeyId, JoinPurposesForLog(Purposes));
131-
}
132-
133-
// We'll need to apply the default key id to the template if it hasn't already been applied.
134-
// If the default key id has been updated since the last call to Protect, also write back the updated template.
135-
var aad = _aadTemplate.GetAadForKey(defaultKeyId, isProtecting: true);
136-
137-
var preBufferSize = _magicHeaderKeyIdSize;
138-
var postBufferSize = 0;
139-
var destinationBufferOffsets = destination.Slice(preBufferSize, destination.Length - (preBufferSize + postBufferSize));
140-
var success = spanEncryptor.TryEncrypt(plaintext, aad, destinationBufferOffsets, out bytesWritten);
141-
142-
// At this point: destination := { 000..000 || encryptorSpecificProtectedPayload },
143-
// where 000..000 is a placeholder for our magic header and key id.
144-
145-
// Write out the magic header and key id
146-
#if NET10_0_OR_GREATER
147-
BinaryPrimitives.WriteUInt32BigEndian(destination.Slice(0, sizeof(uint)), MAGIC_HEADER_V0);
148-
var writeKeyIdResult = defaultKeyId.TryWriteBytes(destination.Slice(sizeof(uint), sizeof(Guid)));
149-
Debug.Assert(writeKeyIdResult, "Failed to write Guid to destination.");
150-
#else
151-
fixed (byte* pbRetVal = destination)
152-
{
153-
WriteBigEndianInteger(pbRetVal, MAGIC_HEADER_V0);
154-
WriteGuid(&pbRetVal[sizeof(uint)], defaultKeyId);
155-
}
156-
#endif
157-
158-
bytesWritten += _magicHeaderKeyIdSize;
159-
160-
// At this point, destination := { magicHeader || keyId || encryptorSpecificProtectedPayload }
161-
// And we're done!
162-
return success;
163-
}
164-
catch (Exception ex) when (ex.RequiresHomogenization())
165-
{
166-
// homogenize all errors to CryptographicException
167-
throw Error.Common_EncryptionFailed(ex);
168-
}
169-
}
170-
17193
public byte[] Protect(byte[] plaintext)
17294
{
17395
ArgumentNullThrowHelper.ThrowIfNull(plaintext);

0 commit comments

Comments
 (0)