From 07666ab89519d50ece8a59b3a69cd3b2d9f224a0 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Fri, 2 Feb 2024 11:35:14 -0800 Subject: [PATCH 01/40] Add key deletion APIs to IKeyManager --- .../src/KeyManagement/IKeyManager.cs | 36 +++++++++++++++++++ .../src/PublicAPI.Unshipped.txt | 2 ++ 2 files changed, 38 insertions(+) diff --git a/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs index df7a1b09e1b6..a7d4dd265ac6 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs @@ -74,4 +74,40 @@ public interface IKeyManager /// all existing IKey instances should be discarded, and GetAllKeys should be called again. /// void RevokeAllKeys(DateTimeOffset revocationDate, string? reason = null); + +#if NETCOREAPP + /// + /// Indicates whether this key manager supports key deletion. + /// + /// + /// Deletion is stronger than revocation. A revoked key is retained and can even be (forcefully) applied. + /// A deleted key is indistinguishable from a key that never existed. + /// + bool CanDeleteKeys => false; + + /// + /// Deletes a specific key and its revocations. + /// + /// The id of the key to delete. + /// + /// Specifies how long ago a key must have expired to be eligible for deletion. + /// If no value is supplied, the default is double . + /// If a timespan of zero is supplied, the key will be deleted regardless of its expiration status. + /// + /// + /// Generally, keys should only be deleted to save space. If space is not a concern, keys + /// should be revoked or allowed to expire instead. + /// + /// This method will not mutate existing IKey instances. After calling this method, + /// all existing IKey instances should be discarded, and GetAllKeys should be called again. + /// + /// + /// If is false. + /// + /// + /// If the key is not found, if the key is expired but not for at least , + /// or if the key is active and is non-zero. + /// + void DeleteKey(Guid keyId, TimeSpan? expiredFor = null) => throw new NotSupportedException(); +#endif } diff --git a/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt index 7dc5c58110bf..8bf03d763ee3 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt @@ -1 +1,3 @@ #nullable enable +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.CanDeleteKeys.get -> bool +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.DeleteKey(System.Guid keyId, System.TimeSpan? expiredFor = null) -> void From 36d663cc47f2b9cb4cf555fec2e632c192b271eb Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Fri, 2 Feb 2024 12:13:38 -0800 Subject: [PATCH 02/40] Add element removal APIs to IXmlRepository --- .../src/PublicAPI.Unshipped.txt | 2 ++ .../src/Repositories/IXmlRepository.cs | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt index 8bf03d763ee3..7c0df0c86454 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt @@ -1,3 +1,5 @@ #nullable enable Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.CanDeleteKeys.get -> bool Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.DeleteKey(System.Guid keyId, System.TimeSpan? expiredFor = null) -> void +Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.CanRemoveElements.get -> bool +Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.RemoveElements(System.Func! shouldRemove) -> void diff --git a/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs index fffee8f07766..5ba5f593ded9 100644 --- a/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs @@ -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.Collections.Generic; using System.Xml.Linq; @@ -32,4 +33,23 @@ public interface IXmlRepository /// be the id of the key being stored. /// void StoreElement(XElement element, string friendlyName); + +#if NETCOREAPP + /// + /// Indicates whether this respository supports removal. + /// + bool CanRemoveElements => false; + + /// + /// Removes elements satisfying the given predicate. + /// + /// + /// A predicate applied to each element. + /// Returning true will cause the element to be removed from the repository. + /// + /// + /// If is false. + /// + void RemoveElements(Func shouldRemove) => throw new NotSupportedException(); +#endif } From 2dac469ef411629899735b1a8bf83ab31fb39352 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Fri, 2 Feb 2024 13:05:16 -0800 Subject: [PATCH 03/40] Implement IXmlRepository deletion for EF, FS, and registry --- .../src/PublicAPI.Unshipped.txt | 4 +++ .../Repositories/FileSystemXmlRepository.cs | 27 ++++++++++++++++++- .../src/Repositories/RegistryXmlRepository.cs | 18 +++++++++++++ .../src/EntityFrameworkCoreXmlRepository.cs | 23 ++++++++++++++++ .../src/PublicAPI.Unshipped.txt | 2 ++ 5 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt index 7c0df0c86454..ac2225c2ef5b 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt @@ -3,3 +3,7 @@ Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.CanDeleteKeys.get Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.DeleteKey(System.Guid keyId, System.TimeSpan? expiredFor = null) -> void Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.CanRemoveElements.get -> bool Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.RemoveElements(System.Func! shouldRemove) -> void +virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.CanRemoveElements.get -> bool +virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Func! shouldRemove) -> void +virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.CanRemoveElements.get -> bool +virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Func! shouldRemove) -> void diff --git a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs index d80ec7d44543..687cbf22623a 100644 --- a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs @@ -81,12 +81,17 @@ private IEnumerable GetAllElementsCore() // set of elements. If a file contains well-formed XML but its contents are meaningless, we // won't fail that operation here. The caller is responsible for failing as appropriate given // that scenario. - foreach (var fileSystemInfo in Directory.EnumerateFileSystemInfos("*.xml", SearchOption.TopDirectoryOnly)) + foreach (var fileSystemInfo in EnumerateFileSystemInfos()) { yield return ReadElementFromFile(fileSystemInfo.FullName); } } + private IEnumerable EnumerateFileSystemInfos() + { + return Directory.EnumerateFileSystemInfos("*.xml", SearchOption.TopDirectoryOnly); + } + private static bool IsSafeFilename(string filename) { // Must be non-empty and contain only a-zA-Z0-9, hyphen, and underscore. @@ -169,4 +174,24 @@ private void StoreElementCore(XElement element, string filename) File.Delete(tempFilename); // won't throw if the file doesn't exist } } + + /// + public virtual bool CanRemoveElements => true; + + /// + public virtual void RemoveElements(Func shouldRemove) + { + ArgumentNullThrowHelper.ThrowIfNull(shouldRemove); + + foreach (var fileSystemInfo in EnumerateFileSystemInfos().ToArray()) // ToArray() to avoid modifying the collection while enumerating + { + var fullPath = fileSystemInfo.FullName; + var element = ReadElementFromFile(fullPath); + if (shouldRemove(element)) + { + _logger.DeletingFile(fullPath); + File.Delete(fullPath); + } + } + } } diff --git a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs index c1fa11b7fbe4..7f2c0c732088 100644 --- a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs @@ -155,4 +155,22 @@ private void StoreElementCore(XElement element, string valueName) // but the window for that should be small enough that we shouldn't have to worry about it. RegistryKey.SetValue(valueName, element.ToString(), RegistryValueKind.String); } + + /// + public virtual bool CanRemoveElements => true; + + /// + public virtual void RemoveElements(Func shouldRemove) + { + ArgumentNullThrowHelper.ThrowIfNull(shouldRemove); + + foreach (string valueName in RegistryKey.GetValueNames()) + { + if (shouldRemove(ReadElementFromRegKey(RegistryKey, valueName)!)) + { + _logger.RemovingDataFromRegistryKeyValue(RegistryKey, valueName); + RegistryKey.DeleteValue(valueName); + } + } + } } diff --git a/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs b/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs index b1d206da0352..0212ea8522a2 100644 --- a/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs +++ b/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs @@ -79,4 +79,27 @@ public void StoreElement(XElement element, string friendlyName) context.SaveChanges(); } } + + /// + public virtual bool CanRemoveElements => true; + + /// + public virtual void RemoveElements(Func shouldRemove) + { + using (var scope = _services.CreateScope()) + { + var context = scope.ServiceProvider.GetRequiredService(); + var keys = context.DataProtectionKeys.AsNoTracking().ToList(); + foreach (var key in keys) + { + if (shouldRemove(XElement.Parse(key.Xml))) + { + context.DataProtectionKeys.Remove(key); + _logger.LogDeletingKeyFromDbContext(key.FriendlyName, typeof(TContext).Name); + } + } + + context.SaveChanges(); + } + } } diff --git a/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt b/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt index 7dc5c58110bf..6c644621a2f7 100644 --- a/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt +++ b/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt @@ -1 +1,3 @@ #nullable enable +virtual Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.EntityFrameworkCoreXmlRepository.CanRemoveElements.get -> bool +virtual Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.EntityFrameworkCoreXmlRepository.RemoveElements(System.Func! shouldRemove) -> void From a0cc3e1d8c06252fc8ee9b1ec13b1c58edff5716 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Fri, 2 Feb 2024 16:59:42 -0800 Subject: [PATCH 04/40] Make API manifest per-framework --- ...Microsoft.AspNetCore.DataProtection.csproj | 5 + .../net462}/PublicAPI.Shipped.txt | 0 .../PublicAPI/net462/PublicAPI.Unshipped.txt | 5 + .../PublicAPI/net9.0/PublicAPI.Shipped.txt | 276 ++++++++++++++++++ .../net9.0}/PublicAPI.Unshipped.txt | 0 .../netstandard2.0/PublicAPI.Shipped.txt | 276 ++++++++++++++++++ .../netstandard2.0/PublicAPI.Unshipped.txt | 5 + 7 files changed, 567 insertions(+) rename src/DataProtection/DataProtection/src/{ => PublicAPI/net462}/PublicAPI.Shipped.txt (100%) create mode 100644 src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt create mode 100644 src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Shipped.txt rename src/DataProtection/DataProtection/src/{ => PublicAPI/net9.0}/PublicAPI.Unshipped.txt (100%) create mode 100644 src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt create mode 100644 src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt diff --git a/src/DataProtection/DataProtection/src/Microsoft.AspNetCore.DataProtection.csproj b/src/DataProtection/DataProtection/src/Microsoft.AspNetCore.DataProtection.csproj index ddf556d6668c..3b6509e1d079 100644 --- a/src/DataProtection/DataProtection/src/Microsoft.AspNetCore.DataProtection.csproj +++ b/src/DataProtection/DataProtection/src/Microsoft.AspNetCore.DataProtection.csproj @@ -53,4 +53,9 @@ + + + + + diff --git a/src/DataProtection/DataProtection/src/PublicAPI.Shipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Shipped.txt similarity index 100% rename from src/DataProtection/DataProtection/src/PublicAPI.Shipped.txt rename to src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Shipped.txt diff --git a/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt new file mode 100644 index 000000000000..d486aca8f5c8 --- /dev/null +++ b/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt @@ -0,0 +1,5 @@ +#nullable enable +virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.CanRemoveElements.get -> bool +virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Func! shouldRemove) -> void +virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.CanRemoveElements.get -> bool +virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Func! shouldRemove) -> void diff --git a/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Shipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Shipped.txt new file mode 100644 index 000000000000..ce4946328fd2 --- /dev/null +++ b/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Shipped.txt @@ -0,0 +1,276 @@ +#nullable enable +abstract Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration.CreateNewDescriptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.AuthenticatedEncryptorFactory +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.AuthenticatedEncryptorFactory.AuthenticatedEncryptorFactory(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.AuthenticatedEncryptorFactory.CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! key) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngCbcAuthenticatedEncryptorFactory +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngCbcAuthenticatedEncryptorFactory.CngCbcAuthenticatedEncryptorFactory(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngCbcAuthenticatedEncryptorFactory.CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! key) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngGcmAuthenticatedEncryptorFactory +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngGcmAuthenticatedEncryptorFactory.CngGcmAuthenticatedEncryptorFactory(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngGcmAuthenticatedEncryptorFactory.CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! key) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration.AlgorithmConfiguration() -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.AuthenticatedEncryptorConfiguration() -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.EncryptionAlgorithm.get -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.EncryptionAlgorithm.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.ValidationAlgorithm.get -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.ValidationAlgorithm.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptor +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptor.AuthenticatedEncryptorDescriptor(Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration! configuration, Microsoft.AspNetCore.DataProtection.ISecret! masterKey) -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptor.ExportToXml() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer.AuthenticatedEncryptorDescriptorDeserializer() -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer.ImportFromXml(System.Xml.Linq.XElement! element) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.CngCbcAuthenticatedEncryptorConfiguration() -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithm.get -> string! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithm.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.get -> int +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithmProvider.get -> string? +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithmProvider.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.HashAlgorithm.get -> string! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.HashAlgorithm.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.HashAlgorithmProvider.get -> string? +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.HashAlgorithmProvider.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptor +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptor.CngCbcAuthenticatedEncryptorDescriptor(Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration! configuration, Microsoft.AspNetCore.DataProtection.ISecret! masterKey) -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptor.ExportToXml() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptorDeserializer +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptorDeserializer.CngCbcAuthenticatedEncryptorDescriptorDeserializer() -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptorDeserializer.ImportFromXml(System.Xml.Linq.XElement! element) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.CngGcmAuthenticatedEncryptorConfiguration() -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithm.get -> string! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithm.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.get -> int +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithmProvider.get -> string? +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithmProvider.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptor +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptor.CngGcmAuthenticatedEncryptorDescriptor(Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration! configuration, Microsoft.AspNetCore.DataProtection.ISecret! masterKey) -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptor.ExportToXml() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptorDeserializer +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptorDeserializer.CngGcmAuthenticatedEncryptorDescriptorDeserializer() -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptorDeserializer.ImportFromXml(System.Xml.Linq.XElement! element) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor.ExportToXml() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer.ImportFromXml(System.Xml.Linq.XElement! element) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.get -> int +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.EncryptionAlgorithmType.get -> System.Type! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.EncryptionAlgorithmType.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.ManagedAuthenticatedEncryptorConfiguration() -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.ValidationAlgorithmType.get -> System.Type! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.ValidationAlgorithmType.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptor +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptor.ExportToXml() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptor.ManagedAuthenticatedEncryptorDescriptor(Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration! configuration, Microsoft.AspNetCore.DataProtection.ISecret! masterKey) -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptorDeserializer +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptorDeserializer.ImportFromXml(System.Xml.Linq.XElement! element) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptorDeserializer.ManagedAuthenticatedEncryptorDescriptorDeserializer() -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlExtensions +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo.DeserializerType.get -> System.Type! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo.SerializedDescriptorElement.get -> System.Xml.Linq.XElement! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo.XmlSerializedDescriptorInfo(System.Xml.Linq.XElement! serializedDescriptorElement, System.Type! deserializerType) -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_128_CBC = 0 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_128_GCM = 3 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_192_CBC = 1 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_192_GCM = 4 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_256_CBC = 2 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_256_GCM = 5 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor.Decrypt(System.ArraySegment ciphertext, System.ArraySegment additionalAuthenticatedData) -> byte[]! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor.Encrypt(System.ArraySegment plaintext, System.ArraySegment additionalAuthenticatedData) -> byte[]! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory.CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! key) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory.CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! key) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory.ManagedAuthenticatedEncryptorFactory(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm.HMACSHA256 = 0 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm.HMACSHA512 = 1 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm +Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions +Microsoft.AspNetCore.DataProtection.DataProtectionOptions +Microsoft.AspNetCore.DataProtection.DataProtectionOptions.ApplicationDiscriminator.get -> string? +Microsoft.AspNetCore.DataProtection.DataProtectionOptions.ApplicationDiscriminator.set -> void +Microsoft.AspNetCore.DataProtection.DataProtectionOptions.DataProtectionOptions() -> void +Microsoft.AspNetCore.DataProtection.DataProtectionUtilityExtensions +Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider +Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider.CreateProtector(string! purpose) -> Microsoft.AspNetCore.DataProtection.IDataProtector! +Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider.EphemeralDataProtectionProvider() -> void +Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider.EphemeralDataProtectionProvider(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder +Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder.Services.get -> Microsoft.Extensions.DependencyInjection.IServiceCollection! +Microsoft.AspNetCore.DataProtection.Internal.IActivator +Microsoft.AspNetCore.DataProtection.Internal.IActivator.CreateInstance(System.Type! expectedBaseType, string! implementationTypeName) -> object! +Microsoft.AspNetCore.DataProtection.IPersistedDataProtector +Microsoft.AspNetCore.DataProtection.IPersistedDataProtector.DangerousUnprotect(byte[]! protectedData, bool ignoreRevocationErrors, out bool requiresMigration, out bool wasRevoked) -> byte[]! +Microsoft.AspNetCore.DataProtection.ISecret +Microsoft.AspNetCore.DataProtection.ISecret.Length.get -> int +Microsoft.AspNetCore.DataProtection.ISecret.WriteSecretIntoBuffer(System.ArraySegment buffer) -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.IKey +Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.ActivationDate.get -> System.DateTimeOffset +Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.CreateEncryptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? +Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.CreationDate.get -> System.DateTimeOffset +Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.Descriptor.get -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.ExpirationDate.get -> System.DateTimeOffset +Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.IsRevoked.get -> bool +Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.KeyId.get -> System.Guid +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyEscrowSink +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyEscrowSink.Store(System.Guid keyId, System.Xml.Linq.XElement! element) -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.CreateNewKey(System.DateTimeOffset activationDate, System.DateTimeOffset expirationDate) -> Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.GetAllKeys() -> System.Collections.Generic.IReadOnlyCollection! +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.GetCacheExpirationToken() -> System.Threading.CancellationToken +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.RevokeAllKeys(System.DateTimeOffset revocationDate, string? reason = null) -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.RevokeKey(System.Guid keyId, string? reason = null) -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.CacheableKeyRing +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution.DefaultKey -> Microsoft.AspNetCore.DataProtection.KeyManagement.IKey? +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution.DefaultKeyResolution() -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution.FallbackKey -> Microsoft.AspNetCore.DataProtection.KeyManagement.IKey? +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution.ShouldGenerateNewKey -> bool +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.ICacheableKeyRingProvider +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.ICacheableKeyRingProvider.GetCacheableKeyRing(System.DateTimeOffset now) -> Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.CacheableKeyRing! +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IDefaultKeyResolver +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IDefaultKeyResolver.ResolveDefaultKeyPolicy(System.DateTimeOffset now, System.Collections.Generic.IEnumerable! allKeys) -> Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager.CreateNewKey(System.Guid keyId, System.DateTimeOffset creationDate, System.DateTimeOffset activationDate, System.DateTimeOffset expirationDate) -> Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager.DeserializeDescriptorFromKeyElement(System.Xml.Linq.XElement! keyElement) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager.RevokeSingleKey(System.Guid keyId, System.DateTimeOffset revocationDate, string? reason) -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing.DefaultAuthenticatedEncryptor.get -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing.DefaultKeyId.get -> System.Guid +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing.GetAuthenticatedEncryptorByKeyId(System.Guid keyId, out bool isRevoked) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRingProvider +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRingProvider.GetCurrentKeyRing() -> Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing! +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.AuthenticatedEncryptorConfiguration.get -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration? +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.AuthenticatedEncryptorConfiguration.set -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.AuthenticatedEncryptorFactories.get -> System.Collections.Generic.IList! +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.AutoGenerateKeys.get -> bool +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.AutoGenerateKeys.set -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.KeyEscrowSinks.get -> System.Collections.Generic.IList! +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.KeyManagementOptions() -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.NewKeyLifetime.get -> System.TimeSpan +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.NewKeyLifetime.set -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.XmlEncryptor.get -> Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor? +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.XmlEncryptor.set -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.XmlRepository.get -> Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository? +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.XmlRepository.set -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager +Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.CreateNewKey(System.DateTimeOffset activationDate, System.DateTimeOffset expirationDate) -> Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! +Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.GetAllKeys() -> System.Collections.Generic.IReadOnlyCollection! +Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.GetCacheExpirationToken() -> System.Threading.CancellationToken +Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.RevokeAllKeys(System.DateTimeOffset revocationDate, string? reason = null) -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.RevokeKey(System.Guid keyId, string? reason = null) -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.XmlKeyManager(Microsoft.Extensions.Options.IOptions! keyManagementOptions, Microsoft.AspNetCore.DataProtection.Internal.IActivator! activator) -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.XmlKeyManager(Microsoft.Extensions.Options.IOptions! keyManagementOptions, Microsoft.AspNetCore.DataProtection.Internal.IActivator! activator, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository +Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.Directory.get -> System.IO.DirectoryInfo! +Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.FileSystemXmlRepository(System.IO.DirectoryInfo! directory, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository +Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.GetAllElements() -> System.Collections.Generic.IReadOnlyCollection! +Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.StoreElement(System.Xml.Linq.XElement! element, string! friendlyName) -> void +Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository +Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RegistryKey.get -> Microsoft.Win32.RegistryKey! +Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RegistryXmlRepository(Microsoft.Win32.RegistryKey! registryKey, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.Secret +Microsoft.AspNetCore.DataProtection.Secret.Dispose() -> void +Microsoft.AspNetCore.DataProtection.Secret.Length.get -> int +Microsoft.AspNetCore.DataProtection.Secret.Secret(byte* secret, int secretLength) -> void +Microsoft.AspNetCore.DataProtection.Secret.Secret(byte[]! value) -> void +Microsoft.AspNetCore.DataProtection.Secret.Secret(Microsoft.AspNetCore.DataProtection.ISecret! secret) -> void +Microsoft.AspNetCore.DataProtection.Secret.Secret(System.ArraySegment value) -> void +Microsoft.AspNetCore.DataProtection.Secret.WriteSecretIntoBuffer(byte* buffer, int bufferLength) -> void +Microsoft.AspNetCore.DataProtection.Secret.WriteSecretIntoBuffer(System.ArraySegment buffer) -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateResolver +Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateResolver.CertificateResolver() -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateXmlEncryptor +Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateXmlEncryptor.CertificateXmlEncryptor(string! thumbprint, Microsoft.AspNetCore.DataProtection.XmlEncryption.ICertificateResolver! certificateResolver, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateXmlEncryptor.CertificateXmlEncryptor(System.Security.Cryptography.X509Certificates.X509Certificate2! certificate, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateXmlEncryptor.Encrypt(System.Xml.Linq.XElement! plaintextElement) -> Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo! +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags.MachineKey = 32 -> Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags.NamedDescriptor = 1 -> Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags.None = 0 -> Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlDecryptor +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlDecryptor.Decrypt(System.Xml.Linq.XElement! encryptedElement) -> System.Xml.Linq.XElement! +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlDecryptor.DpapiNGXmlDecryptor() -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlDecryptor.DpapiNGXmlDecryptor(System.IServiceProvider? services) -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlEncryptor +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlEncryptor.DpapiNGXmlEncryptor(string! protectionDescriptorRule, Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags flags, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlEncryptor.Encrypt(System.Xml.Linq.XElement! plaintextElement) -> Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo! +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlDecryptor +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlDecryptor.Decrypt(System.Xml.Linq.XElement! encryptedElement) -> System.Xml.Linq.XElement! +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlDecryptor.DpapiXmlDecryptor() -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlDecryptor.DpapiXmlDecryptor(System.IServiceProvider? services) -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlEncryptor +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlEncryptor.DpapiXmlEncryptor(bool protectToLocalMachine, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlEncryptor.Encrypt(System.Xml.Linq.XElement! plaintextElement) -> Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo! +Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor +Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor.Decrypt(System.Xml.Linq.XElement! encryptedElement) -> System.Xml.Linq.XElement! +Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor.EncryptedXmlDecryptor() -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor.EncryptedXmlDecryptor(System.IServiceProvider? services) -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo +Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo.DecryptorType.get -> System.Type! +Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo.EncryptedElement.get -> System.Xml.Linq.XElement! +Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo.EncryptedXmlInfo(System.Xml.Linq.XElement! encryptedElement, System.Type! decryptorType) -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.ICertificateResolver +Microsoft.AspNetCore.DataProtection.XmlEncryption.ICertificateResolver.ResolveCertificate(string! thumbprint) -> System.Security.Cryptography.X509Certificates.X509Certificate2? +Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor +Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor.Decrypt(System.Xml.Linq.XElement! encryptedElement) -> System.Xml.Linq.XElement! +Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor +Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor.Encrypt(System.Xml.Linq.XElement! plaintextElement) -> Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo! +Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlDecryptor +Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlDecryptor.Decrypt(System.Xml.Linq.XElement! encryptedElement) -> System.Xml.Linq.XElement! +Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlDecryptor.NullXmlDecryptor() -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlEncryptor +Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlEncryptor.Encrypt(System.Xml.Linq.XElement! plaintextElement) -> Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo! +Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlEncryptor.NullXmlEncryptor() -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlEncryptor.NullXmlEncryptor(System.IServiceProvider? services) -> void +Microsoft.Extensions.DependencyInjection.DataProtectionServiceCollectionExtensions +override Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.CreateNewDescriptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +override Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.CreateNewDescriptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +override Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.CreateNewDescriptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +override Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.CreateNewDescriptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +static Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlExtensions.MarkAsRequiresEncryption(this System.Xml.Linq.XElement! element) -> void +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.AddKeyEscrowSink(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyEscrowSink! sink) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.AddKeyEscrowSink(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.Func! factory) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.AddKeyEscrowSink(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.AddKeyManagementOptions(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.Action! setupAction) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.DisableAutomaticKeyGeneration(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.PersistKeysToFileSystem(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.IO.DirectoryInfo! directory) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.PersistKeysToRegistry(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.Win32.RegistryKey! registryKey) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithCertificate(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, string! thumbprint) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithCertificate(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.Security.Cryptography.X509Certificates.X509Certificate2! certificate) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithDpapi(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithDpapi(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, bool protectToLocalMachine) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithDpapiNG(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithDpapiNG(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, string! protectionDescriptorRule, Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags flags) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.SetApplicationName(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, string! applicationName) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.SetDefaultKeyLifetime(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.TimeSpan lifetime) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UnprotectKeysWithAnyCertificate(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, params System.Security.Cryptography.X509Certificates.X509Certificate2![]! certificates) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UseCryptographicAlgorithms(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration! configuration) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UseCustomCryptographicAlgorithms(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration! configuration) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UseCustomCryptographicAlgorithms(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration! configuration) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UseCustomCryptographicAlgorithms(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration! configuration) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UseEphemeralDataProtectionProvider(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionUtilityExtensions.GetApplicationUniqueIdentifier(this System.IServiceProvider! services) -> string? +static Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.DefaultKeyStorageDirectory.get -> System.IO.DirectoryInfo? +static Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.DefaultRegistryKey.get -> Microsoft.Win32.RegistryKey? +static Microsoft.AspNetCore.DataProtection.Secret.Random(int numBytes) -> Microsoft.AspNetCore.DataProtection.Secret! +static Microsoft.Extensions.DependencyInjection.DataProtectionServiceCollectionExtensions.AddDataProtection(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.Extensions.DependencyInjection.DataProtectionServiceCollectionExtensions.AddDataProtection(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action! setupAction) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.GetAllElements() -> System.Collections.Generic.IReadOnlyCollection! +virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.StoreElement(System.Xml.Linq.XElement! element, string! friendlyName) -> void +virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.GetAllElements() -> System.Collections.Generic.IReadOnlyCollection! +virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.StoreElement(System.Xml.Linq.XElement! element, string! friendlyName) -> void +virtual Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateResolver.ResolveCertificate(string! thumbprint) -> System.Security.Cryptography.X509Certificates.X509Certificate2? diff --git a/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt similarity index 100% rename from src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt rename to src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt diff --git a/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt new file mode 100644 index 000000000000..ce4946328fd2 --- /dev/null +++ b/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt @@ -0,0 +1,276 @@ +#nullable enable +abstract Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration.CreateNewDescriptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.AuthenticatedEncryptorFactory +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.AuthenticatedEncryptorFactory.AuthenticatedEncryptorFactory(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.AuthenticatedEncryptorFactory.CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! key) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngCbcAuthenticatedEncryptorFactory +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngCbcAuthenticatedEncryptorFactory.CngCbcAuthenticatedEncryptorFactory(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngCbcAuthenticatedEncryptorFactory.CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! key) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngGcmAuthenticatedEncryptorFactory +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngGcmAuthenticatedEncryptorFactory.CngGcmAuthenticatedEncryptorFactory(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngGcmAuthenticatedEncryptorFactory.CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! key) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration.AlgorithmConfiguration() -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.AuthenticatedEncryptorConfiguration() -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.EncryptionAlgorithm.get -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.EncryptionAlgorithm.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.ValidationAlgorithm.get -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.ValidationAlgorithm.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptor +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptor.AuthenticatedEncryptorDescriptor(Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration! configuration, Microsoft.AspNetCore.DataProtection.ISecret! masterKey) -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptor.ExportToXml() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer.AuthenticatedEncryptorDescriptorDeserializer() -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer.ImportFromXml(System.Xml.Linq.XElement! element) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.CngCbcAuthenticatedEncryptorConfiguration() -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithm.get -> string! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithm.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.get -> int +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithmProvider.get -> string? +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithmProvider.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.HashAlgorithm.get -> string! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.HashAlgorithm.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.HashAlgorithmProvider.get -> string? +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.HashAlgorithmProvider.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptor +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptor.CngCbcAuthenticatedEncryptorDescriptor(Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration! configuration, Microsoft.AspNetCore.DataProtection.ISecret! masterKey) -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptor.ExportToXml() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptorDeserializer +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptorDeserializer.CngCbcAuthenticatedEncryptorDescriptorDeserializer() -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptorDeserializer.ImportFromXml(System.Xml.Linq.XElement! element) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.CngGcmAuthenticatedEncryptorConfiguration() -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithm.get -> string! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithm.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.get -> int +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithmProvider.get -> string? +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithmProvider.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptor +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptor.CngGcmAuthenticatedEncryptorDescriptor(Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration! configuration, Microsoft.AspNetCore.DataProtection.ISecret! masterKey) -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptor.ExportToXml() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptorDeserializer +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptorDeserializer.CngGcmAuthenticatedEncryptorDescriptorDeserializer() -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptorDeserializer.ImportFromXml(System.Xml.Linq.XElement! element) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor.ExportToXml() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer.ImportFromXml(System.Xml.Linq.XElement! element) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.get -> int +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.EncryptionAlgorithmType.get -> System.Type! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.EncryptionAlgorithmType.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.ManagedAuthenticatedEncryptorConfiguration() -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.ValidationAlgorithmType.get -> System.Type! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.ValidationAlgorithmType.set -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptor +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptor.ExportToXml() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptor.ManagedAuthenticatedEncryptorDescriptor(Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration! configuration, Microsoft.AspNetCore.DataProtection.ISecret! masterKey) -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptorDeserializer +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptorDeserializer.ImportFromXml(System.Xml.Linq.XElement! element) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptorDeserializer.ManagedAuthenticatedEncryptorDescriptorDeserializer() -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlExtensions +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo.DeserializerType.get -> System.Type! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo.SerializedDescriptorElement.get -> System.Xml.Linq.XElement! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo.XmlSerializedDescriptorInfo(System.Xml.Linq.XElement! serializedDescriptorElement, System.Type! deserializerType) -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_128_CBC = 0 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_128_GCM = 3 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_192_CBC = 1 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_192_GCM = 4 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_256_CBC = 2 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_256_GCM = 5 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor.Decrypt(System.ArraySegment ciphertext, System.ArraySegment additionalAuthenticatedData) -> byte[]! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor.Encrypt(System.ArraySegment plaintext, System.ArraySegment additionalAuthenticatedData) -> byte[]! +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory.CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! key) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory.CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! key) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory.ManagedAuthenticatedEncryptorFactory(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm.HMACSHA256 = 0 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm +Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm.HMACSHA512 = 1 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm +Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions +Microsoft.AspNetCore.DataProtection.DataProtectionOptions +Microsoft.AspNetCore.DataProtection.DataProtectionOptions.ApplicationDiscriminator.get -> string? +Microsoft.AspNetCore.DataProtection.DataProtectionOptions.ApplicationDiscriminator.set -> void +Microsoft.AspNetCore.DataProtection.DataProtectionOptions.DataProtectionOptions() -> void +Microsoft.AspNetCore.DataProtection.DataProtectionUtilityExtensions +Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider +Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider.CreateProtector(string! purpose) -> Microsoft.AspNetCore.DataProtection.IDataProtector! +Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider.EphemeralDataProtectionProvider() -> void +Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider.EphemeralDataProtectionProvider(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder +Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder.Services.get -> Microsoft.Extensions.DependencyInjection.IServiceCollection! +Microsoft.AspNetCore.DataProtection.Internal.IActivator +Microsoft.AspNetCore.DataProtection.Internal.IActivator.CreateInstance(System.Type! expectedBaseType, string! implementationTypeName) -> object! +Microsoft.AspNetCore.DataProtection.IPersistedDataProtector +Microsoft.AspNetCore.DataProtection.IPersistedDataProtector.DangerousUnprotect(byte[]! protectedData, bool ignoreRevocationErrors, out bool requiresMigration, out bool wasRevoked) -> byte[]! +Microsoft.AspNetCore.DataProtection.ISecret +Microsoft.AspNetCore.DataProtection.ISecret.Length.get -> int +Microsoft.AspNetCore.DataProtection.ISecret.WriteSecretIntoBuffer(System.ArraySegment buffer) -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.IKey +Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.ActivationDate.get -> System.DateTimeOffset +Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.CreateEncryptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? +Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.CreationDate.get -> System.DateTimeOffset +Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.Descriptor.get -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.ExpirationDate.get -> System.DateTimeOffset +Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.IsRevoked.get -> bool +Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.KeyId.get -> System.Guid +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyEscrowSink +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyEscrowSink.Store(System.Guid keyId, System.Xml.Linq.XElement! element) -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.CreateNewKey(System.DateTimeOffset activationDate, System.DateTimeOffset expirationDate) -> Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.GetAllKeys() -> System.Collections.Generic.IReadOnlyCollection! +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.GetCacheExpirationToken() -> System.Threading.CancellationToken +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.RevokeAllKeys(System.DateTimeOffset revocationDate, string? reason = null) -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.RevokeKey(System.Guid keyId, string? reason = null) -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.CacheableKeyRing +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution.DefaultKey -> Microsoft.AspNetCore.DataProtection.KeyManagement.IKey? +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution.DefaultKeyResolution() -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution.FallbackKey -> Microsoft.AspNetCore.DataProtection.KeyManagement.IKey? +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution.ShouldGenerateNewKey -> bool +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.ICacheableKeyRingProvider +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.ICacheableKeyRingProvider.GetCacheableKeyRing(System.DateTimeOffset now) -> Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.CacheableKeyRing! +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IDefaultKeyResolver +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IDefaultKeyResolver.ResolveDefaultKeyPolicy(System.DateTimeOffset now, System.Collections.Generic.IEnumerable! allKeys) -> Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager.CreateNewKey(System.Guid keyId, System.DateTimeOffset creationDate, System.DateTimeOffset activationDate, System.DateTimeOffset expirationDate) -> Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager.DeserializeDescriptorFromKeyElement(System.Xml.Linq.XElement! keyElement) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager.RevokeSingleKey(System.Guid keyId, System.DateTimeOffset revocationDate, string? reason) -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing.DefaultAuthenticatedEncryptor.get -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing.DefaultKeyId.get -> System.Guid +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing.GetAuthenticatedEncryptorByKeyId(System.Guid keyId, out bool isRevoked) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRingProvider +Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRingProvider.GetCurrentKeyRing() -> Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing! +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.AuthenticatedEncryptorConfiguration.get -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration? +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.AuthenticatedEncryptorConfiguration.set -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.AuthenticatedEncryptorFactories.get -> System.Collections.Generic.IList! +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.AutoGenerateKeys.get -> bool +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.AutoGenerateKeys.set -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.KeyEscrowSinks.get -> System.Collections.Generic.IList! +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.KeyManagementOptions() -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.NewKeyLifetime.get -> System.TimeSpan +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.NewKeyLifetime.set -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.XmlEncryptor.get -> Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor? +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.XmlEncryptor.set -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.XmlRepository.get -> Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository? +Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.XmlRepository.set -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager +Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.CreateNewKey(System.DateTimeOffset activationDate, System.DateTimeOffset expirationDate) -> Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! +Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.GetAllKeys() -> System.Collections.Generic.IReadOnlyCollection! +Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.GetCacheExpirationToken() -> System.Threading.CancellationToken +Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.RevokeAllKeys(System.DateTimeOffset revocationDate, string? reason = null) -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.RevokeKey(System.Guid keyId, string? reason = null) -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.XmlKeyManager(Microsoft.Extensions.Options.IOptions! keyManagementOptions, Microsoft.AspNetCore.DataProtection.Internal.IActivator! activator) -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.XmlKeyManager(Microsoft.Extensions.Options.IOptions! keyManagementOptions, Microsoft.AspNetCore.DataProtection.Internal.IActivator! activator, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository +Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.Directory.get -> System.IO.DirectoryInfo! +Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.FileSystemXmlRepository(System.IO.DirectoryInfo! directory, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository +Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.GetAllElements() -> System.Collections.Generic.IReadOnlyCollection! +Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.StoreElement(System.Xml.Linq.XElement! element, string! friendlyName) -> void +Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository +Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RegistryKey.get -> Microsoft.Win32.RegistryKey! +Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RegistryXmlRepository(Microsoft.Win32.RegistryKey! registryKey, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.Secret +Microsoft.AspNetCore.DataProtection.Secret.Dispose() -> void +Microsoft.AspNetCore.DataProtection.Secret.Length.get -> int +Microsoft.AspNetCore.DataProtection.Secret.Secret(byte* secret, int secretLength) -> void +Microsoft.AspNetCore.DataProtection.Secret.Secret(byte[]! value) -> void +Microsoft.AspNetCore.DataProtection.Secret.Secret(Microsoft.AspNetCore.DataProtection.ISecret! secret) -> void +Microsoft.AspNetCore.DataProtection.Secret.Secret(System.ArraySegment value) -> void +Microsoft.AspNetCore.DataProtection.Secret.WriteSecretIntoBuffer(byte* buffer, int bufferLength) -> void +Microsoft.AspNetCore.DataProtection.Secret.WriteSecretIntoBuffer(System.ArraySegment buffer) -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateResolver +Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateResolver.CertificateResolver() -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateXmlEncryptor +Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateXmlEncryptor.CertificateXmlEncryptor(string! thumbprint, Microsoft.AspNetCore.DataProtection.XmlEncryption.ICertificateResolver! certificateResolver, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateXmlEncryptor.CertificateXmlEncryptor(System.Security.Cryptography.X509Certificates.X509Certificate2! certificate, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateXmlEncryptor.Encrypt(System.Xml.Linq.XElement! plaintextElement) -> Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo! +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags.MachineKey = 32 -> Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags.NamedDescriptor = 1 -> Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags.None = 0 -> Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlDecryptor +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlDecryptor.Decrypt(System.Xml.Linq.XElement! encryptedElement) -> System.Xml.Linq.XElement! +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlDecryptor.DpapiNGXmlDecryptor() -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlDecryptor.DpapiNGXmlDecryptor(System.IServiceProvider? services) -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlEncryptor +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlEncryptor.DpapiNGXmlEncryptor(string! protectionDescriptorRule, Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags flags, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlEncryptor.Encrypt(System.Xml.Linq.XElement! plaintextElement) -> Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo! +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlDecryptor +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlDecryptor.Decrypt(System.Xml.Linq.XElement! encryptedElement) -> System.Xml.Linq.XElement! +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlDecryptor.DpapiXmlDecryptor() -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlDecryptor.DpapiXmlDecryptor(System.IServiceProvider? services) -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlEncryptor +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlEncryptor.DpapiXmlEncryptor(bool protectToLocalMachine, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlEncryptor.Encrypt(System.Xml.Linq.XElement! plaintextElement) -> Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo! +Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor +Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor.Decrypt(System.Xml.Linq.XElement! encryptedElement) -> System.Xml.Linq.XElement! +Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor.EncryptedXmlDecryptor() -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor.EncryptedXmlDecryptor(System.IServiceProvider? services) -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo +Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo.DecryptorType.get -> System.Type! +Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo.EncryptedElement.get -> System.Xml.Linq.XElement! +Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo.EncryptedXmlInfo(System.Xml.Linq.XElement! encryptedElement, System.Type! decryptorType) -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.ICertificateResolver +Microsoft.AspNetCore.DataProtection.XmlEncryption.ICertificateResolver.ResolveCertificate(string! thumbprint) -> System.Security.Cryptography.X509Certificates.X509Certificate2? +Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor +Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor.Decrypt(System.Xml.Linq.XElement! encryptedElement) -> System.Xml.Linq.XElement! +Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor +Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor.Encrypt(System.Xml.Linq.XElement! plaintextElement) -> Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo! +Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlDecryptor +Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlDecryptor.Decrypt(System.Xml.Linq.XElement! encryptedElement) -> System.Xml.Linq.XElement! +Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlDecryptor.NullXmlDecryptor() -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlEncryptor +Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlEncryptor.Encrypt(System.Xml.Linq.XElement! plaintextElement) -> Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo! +Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlEncryptor.NullXmlEncryptor() -> void +Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlEncryptor.NullXmlEncryptor(System.IServiceProvider? services) -> void +Microsoft.Extensions.DependencyInjection.DataProtectionServiceCollectionExtensions +override Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.CreateNewDescriptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +override Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.CreateNewDescriptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +override Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.CreateNewDescriptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +override Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.CreateNewDescriptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! +static Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlExtensions.MarkAsRequiresEncryption(this System.Xml.Linq.XElement! element) -> void +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.AddKeyEscrowSink(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyEscrowSink! sink) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.AddKeyEscrowSink(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.Func! factory) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.AddKeyEscrowSink(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.AddKeyManagementOptions(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.Action! setupAction) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.DisableAutomaticKeyGeneration(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.PersistKeysToFileSystem(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.IO.DirectoryInfo! directory) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.PersistKeysToRegistry(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.Win32.RegistryKey! registryKey) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithCertificate(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, string! thumbprint) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithCertificate(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.Security.Cryptography.X509Certificates.X509Certificate2! certificate) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithDpapi(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithDpapi(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, bool protectToLocalMachine) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithDpapiNG(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithDpapiNG(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, string! protectionDescriptorRule, Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags flags) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.SetApplicationName(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, string! applicationName) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.SetDefaultKeyLifetime(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.TimeSpan lifetime) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UnprotectKeysWithAnyCertificate(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, params System.Security.Cryptography.X509Certificates.X509Certificate2![]! certificates) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UseCryptographicAlgorithms(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration! configuration) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UseCustomCryptographicAlgorithms(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration! configuration) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UseCustomCryptographicAlgorithms(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration! configuration) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UseCustomCryptographicAlgorithms(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration! configuration) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UseEphemeralDataProtectionProvider(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.DataProtectionUtilityExtensions.GetApplicationUniqueIdentifier(this System.IServiceProvider! services) -> string? +static Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.DefaultKeyStorageDirectory.get -> System.IO.DirectoryInfo? +static Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.DefaultRegistryKey.get -> Microsoft.Win32.RegistryKey? +static Microsoft.AspNetCore.DataProtection.Secret.Random(int numBytes) -> Microsoft.AspNetCore.DataProtection.Secret! +static Microsoft.Extensions.DependencyInjection.DataProtectionServiceCollectionExtensions.AddDataProtection(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.Extensions.DependencyInjection.DataProtectionServiceCollectionExtensions.AddDataProtection(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action! setupAction) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.GetAllElements() -> System.Collections.Generic.IReadOnlyCollection! +virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.StoreElement(System.Xml.Linq.XElement! element, string! friendlyName) -> void +virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.GetAllElements() -> System.Collections.Generic.IReadOnlyCollection! +virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.StoreElement(System.Xml.Linq.XElement! element, string! friendlyName) -> void +virtual Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateResolver.ResolveCertificate(string! thumbprint) -> System.Security.Cryptography.X509Certificates.X509Certificate2? diff --git a/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt new file mode 100644 index 000000000000..d486aca8f5c8 --- /dev/null +++ b/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -0,0 +1,5 @@ +#nullable enable +virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.CanRemoveElements.get -> bool +virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Func! shouldRemove) -> void +virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.CanRemoveElements.get -> bool +virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Func! shouldRemove) -> void From 9ce136a49485f5b7c671c5b9ac575b1084d6549e Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Fri, 2 Feb 2024 17:12:56 -0800 Subject: [PATCH 05/40] Implement missing logging methods --- src/DataProtection/DataProtection/src/LoggingExtensions.cs | 6 ++++++ .../src/EntityFrameworkCoreXmlRepository.cs | 4 ++-- .../EntityFrameworkCore/src/LoggingExtensions.cs | 3 +++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/DataProtection/DataProtection/src/LoggingExtensions.cs b/src/DataProtection/DataProtection/src/LoggingExtensions.cs index 553a4f5e1f60..4a089320ed26 100644 --- a/src/DataProtection/DataProtection/src/LoggingExtensions.cs +++ b/src/DataProtection/DataProtection/src/LoggingExtensions.cs @@ -255,4 +255,10 @@ private static bool IsLogLevelEnabledCore([NotNullWhen(true)] ILogger? logger, L [LoggerMessage(73, LogLevel.Debug, "Key {KeyId:B} method {MethodName} failed. Retrying.", EventName = "RetryingMethodOfKeyAfterFailure")] public static partial void RetryingMethodOfKeyAfterFailure(this ILogger logger, Guid keyId, string methodName, Exception exception); + + [LoggerMessage(74, LogLevel.Information, "Deleting file '{FileName}'.", EventName = "DeletingFile")] + public static partial void DeletingFile(this ILogger logger, string fileName); + + [LoggerMessage(75, LogLevel.Debug, "Deleting registry key '{RegistryKeyName}', value '{Value}'.", EventName = "RemovingDataFromRegistryKeyValue")] + public static partial void RemovingDataFromRegistryKeyValue(this ILogger logger, RegistryKey registryKeyName, string value); } diff --git a/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs b/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs index 0212ea8522a2..79f7daa38be5 100644 --- a/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs +++ b/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs @@ -92,10 +92,10 @@ public virtual void RemoveElements(Func shouldRemove) var keys = context.DataProtectionKeys.AsNoTracking().ToList(); foreach (var key in keys) { - if (shouldRemove(XElement.Parse(key.Xml))) + if (!string.IsNullOrEmpty(key.Xml) && shouldRemove(XElement.Parse(key.Xml))) { context.DataProtectionKeys.Remove(key); - _logger.LogDeletingKeyFromDbContext(key.FriendlyName, typeof(TContext).Name); + _logger.DeletingKeyFromDbContext(key.FriendlyName, typeof(TContext).Name); } } diff --git a/src/DataProtection/EntityFrameworkCore/src/LoggingExtensions.cs b/src/DataProtection/EntityFrameworkCore/src/LoggingExtensions.cs index 5491abcbeebc..3c8e047f73a9 100644 --- a/src/DataProtection/EntityFrameworkCore/src/LoggingExtensions.cs +++ b/src/DataProtection/EntityFrameworkCore/src/LoggingExtensions.cs @@ -10,4 +10,7 @@ internal static partial class LoggingExtensions [LoggerMessage(2, LogLevel.Debug, "Saving key '{FriendlyName}' to '{DbContext}'.", EventName = "SavingKeyToDbContext")] public static partial void LogSavingKeyToDbContext(this ILogger logger, string friendlyName, string dbContext); + + [LoggerMessage(3, LogLevel.Debug, "Deleting key '{FriendlyName}' from '{DbContext}'.", EventName = "DeletingKeyFromDbContext")] + public static partial void DeletingKeyFromDbContext(this ILogger logger, string? friendlyName, string dbContext); } From 2f086d696e2829a730b5e7d7f2953df64e5deaf3 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Fri, 2 Feb 2024 17:22:25 -0800 Subject: [PATCH 06/40] Update IKeyManager API to parallel IXmlRepository --- .../src/KeyManagement/IKeyManager.cs | 18 ++++++++---------- .../PublicAPI/net9.0/PublicAPI.Unshipped.txt | 2 +- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs index a7d4dd265ac6..2b3a226d15db 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs @@ -88,11 +88,13 @@ public interface IKeyManager /// /// Deletes a specific key and its revocations. /// - /// The id of the key to delete. - /// - /// Specifies how long ago a key must have expired to be eligible for deletion. - /// If no value is supplied, the default is double . - /// If a timespan of zero is supplied, the key will be deleted regardless of its expiration status. + /// + /// A predicate applied to each expired key (and active key if is true). + /// Returning true will cause the key to be deleted. + /// + /// + /// True indicates that active keys should also be passed to . + /// Use with caution as deleting active keys will normally cause data loss. /// /// /// Generally, keys should only be deleted to save space. If space is not a concern, keys @@ -104,10 +106,6 @@ public interface IKeyManager /// /// If is false. /// - /// - /// If the key is not found, if the key is expired but not for at least , - /// or if the key is active and is non-zero. - /// - void DeleteKey(Guid keyId, TimeSpan? expiredFor = null) => throw new NotSupportedException(); + void DeleteKeys(Func shouldDelete, bool unsafeIncludeActive = false) => throw new NotSupportedException(); #endif } diff --git a/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt index ac2225c2ef5b..00bbc4bf8520 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt @@ -1,6 +1,6 @@ #nullable enable Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.CanDeleteKeys.get -> bool -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.DeleteKey(System.Guid keyId, System.TimeSpan? expiredFor = null) -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.DeleteKeys(System.Func! shouldDelete, bool unsafeIncludeActive = false) -> void Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.CanRemoveElements.get -> bool Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.RemoveElements(System.Func! shouldRemove) -> void virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.CanRemoveElements.get -> bool From 161f5bfb948ebf98e1a45a7bb22bf015178a4e40 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Mon, 5 Feb 2024 16:09:52 -0800 Subject: [PATCH 07/40] Pass entire list of XElements to RemoveElements callback --- .../src/KeyManagement/IKeyManager.cs | 11 +++---- .../DataProtection/src/LoggingExtensions.cs | 8 ++++- .../PublicAPI/net462/PublicAPI.Unshipped.txt | 4 +-- .../PublicAPI/net9.0/PublicAPI.Unshipped.txt | 8 ++--- .../netstandard2.0/PublicAPI.Unshipped.txt | 4 +-- .../Repositories/FileSystemXmlRepository.cs | 29 +++++++++++++++---- .../src/Repositories/IXmlRepository.cs | 3 +- .../src/Repositories/RegistryXmlRepository.cs | 29 ++++++++++++++++--- .../src/EntityFrameworkCoreXmlRepository.cs | 29 +++++++++++++++---- .../src/LoggingExtensions.cs | 3 ++ .../src/PublicAPI.Unshipped.txt | 2 +- 11 files changed, 100 insertions(+), 30 deletions(-) diff --git a/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs index 2b3a226d15db..9786539ead9d 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs @@ -86,14 +86,15 @@ public interface IKeyManager bool CanDeleteKeys => false; /// - /// Deletes a specific key and its revocations. + /// Deletes keys matching a predicate. /// /// - /// A predicate applied to each expired key (and active key if is true). + /// A predicate applied to each expired key (and unexpired key if is true). /// Returning true will cause the key to be deleted. /// - /// - /// True indicates that active keys should also be passed to . + /// + /// True indicates that unexpired keys (which may be presently or yet to be activated) should also be + /// passed to . /// Use with caution as deleting active keys will normally cause data loss. /// /// @@ -106,6 +107,6 @@ public interface IKeyManager /// /// If is false. /// - void DeleteKeys(Func shouldDelete, bool unsafeIncludeActive = false) => throw new NotSupportedException(); + void DeleteKeys(Func shouldDelete, bool unsafeIncludeUnexpired = false) => throw new NotSupportedException(); #endif } diff --git a/src/DataProtection/DataProtection/src/LoggingExtensions.cs b/src/DataProtection/DataProtection/src/LoggingExtensions.cs index 4a089320ed26..0b008cff0551 100644 --- a/src/DataProtection/DataProtection/src/LoggingExtensions.cs +++ b/src/DataProtection/DataProtection/src/LoggingExtensions.cs @@ -259,6 +259,12 @@ private static bool IsLogLevelEnabledCore([NotNullWhen(true)] ILogger? logger, L [LoggerMessage(74, LogLevel.Information, "Deleting file '{FileName}'.", EventName = "DeletingFile")] public static partial void DeletingFile(this ILogger logger, string fileName); - [LoggerMessage(75, LogLevel.Debug, "Deleting registry key '{RegistryKeyName}', value '{Value}'.", EventName = "RemovingDataFromRegistryKeyValue")] + [LoggerMessage(75, LogLevel.Information, "Failed to delete file '{FileName}'.", EventName = "FailedToDeleteFile")] + public static partial void FailedToDeleteFile(this ILogger logger, string fileName, Exception exception); + + [LoggerMessage(76, LogLevel.Debug, "Deleting registry key '{RegistryKeyName}', value '{Value}'.", EventName = "RemovingDataFromRegistryKeyValue")] public static partial void RemovingDataFromRegistryKeyValue(this ILogger logger, RegistryKey registryKeyName, string value); + + [LoggerMessage(77, LogLevel.Error, "Failed to delete registry key '{RegistryKeyName}', value '{ValueName}'.", EventName = "FailedToRemoveDataFromRegistryKeyValue")] + public static partial void FailedToRemoveDataFromRegistryKeyValue(this ILogger logger, RegistryKey registryKeyName, string valueName, Exception exception); } diff --git a/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt index d486aca8f5c8..493e2922870e 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt @@ -1,5 +1,5 @@ #nullable enable virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Func! shouldRemove) -> void +virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> void virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Func! shouldRemove) -> void +virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> void diff --git a/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt index 00bbc4bf8520..2c94a8b38636 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt @@ -1,9 +1,9 @@ #nullable enable Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.CanDeleteKeys.get -> bool -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.DeleteKeys(System.Func! shouldDelete, bool unsafeIncludeActive = false) -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.DeleteKeys(System.Func! shouldDelete, bool unsafeIncludeUnexpired = false) -> void Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.CanRemoveElements.get -> bool -Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.RemoveElements(System.Func! shouldRemove) -> void +Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> void virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Func! shouldRemove) -> void +virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> void virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Func! shouldRemove) -> void +virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> void diff --git a/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index d486aca8f5c8..493e2922870e 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,5 +1,5 @@ #nullable enable virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Func! shouldRemove) -> void +virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> void virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Func! shouldRemove) -> void +virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> void diff --git a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs index 687cbf22623a..d018c21eaedc 100644 --- a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; @@ -179,18 +180,36 @@ private void StoreElementCore(XElement element, string filename) public virtual bool CanRemoveElements => true; /// - public virtual void RemoveElements(Func shouldRemove) + public virtual void RemoveElements(Func, bool> shouldRemove) { ArgumentNullThrowHelper.ThrowIfNull(shouldRemove); - foreach (var fileSystemInfo in EnumerateFileSystemInfos().ToArray()) // ToArray() to avoid modifying the collection while enumerating + var fileSystemInfos = new List(); + var elements = new List(); + + foreach (var fileSystemInfo in EnumerateFileSystemInfos()) { var fullPath = fileSystemInfo.FullName; var element = ReadElementFromFile(fullPath); - if (shouldRemove(element)) + fileSystemInfos.Add(fileSystemInfo); + elements.Add(element); + } + + for (var i = 0; i < fileSystemInfos.Count; i++) + { + if (shouldRemove(elements[i], elements)) { - _logger.DeletingFile(fullPath); - File.Delete(fullPath); + var fileSystemInfo = fileSystemInfos[i]; + _logger.DeletingFile(fileSystemInfo.FullName); + try + { + fileSystemInfo.Delete(); + } + catch (Exception ex) + { + Debug.Assert(fileSystemInfo.Exists, "Having previously been deleted should not have caused an exception"); + _logger.FailedToDeleteFile(fileSystemInfo.FullName, ex); + } } } } diff --git a/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs index 5ba5f593ded9..2122de5ad3d8 100644 --- a/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs @@ -45,11 +45,12 @@ public interface IXmlRepository /// /// /// A predicate applied to each element. + /// The second argument gives the contents of the collection before any removals. /// Returning true will cause the element to be removed from the repository. /// /// /// If is false. /// - void RemoveElements(Func shouldRemove) => throw new NotSupportedException(); + void RemoveElements(Func, bool> shouldRemove) => throw new NotSupportedException(); #endif } diff --git a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs index 7f2c0c732088..1665d35c5523 100644 --- a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs @@ -160,16 +160,37 @@ private void StoreElementCore(XElement element, string valueName) public virtual bool CanRemoveElements => true; /// - public virtual void RemoveElements(Func shouldRemove) + public virtual void RemoveElements(Func, bool> shouldRemove) { ArgumentNullThrowHelper.ThrowIfNull(shouldRemove); - foreach (string valueName in RegistryKey.GetValueNames()) + var valueNames = new List(); + var elements = new List(); + + foreach (var valueName in RegistryKey.GetValueNames()) + { + var element = ReadElementFromRegKey(RegistryKey, valueName); + if (element is not null) + { + valueNames.Add(valueName); + elements.Add(element); + } + } + + for (var i = 0; i < valueNames.Count; i++) { - if (shouldRemove(ReadElementFromRegKey(RegistryKey, valueName)!)) + if (shouldRemove(elements[i], elements)) { + var valueName = valueNames[i]; _logger.RemovingDataFromRegistryKeyValue(RegistryKey, valueName); - RegistryKey.DeleteValue(valueName); + try + { + RegistryKey.DeleteValue(valueName); + } + catch (Exception ex) + { + _logger.FailedToRemoveDataFromRegistryKeyValue(RegistryKey, valueName, ex); + } } } } diff --git a/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs b/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs index 79f7daa38be5..792fa6ef6aa2 100644 --- a/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs +++ b/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs @@ -84,18 +84,37 @@ public void StoreElement(XElement element, string friendlyName) public virtual bool CanRemoveElements => true; /// - public virtual void RemoveElements(Func shouldRemove) + public virtual void RemoveElements(Func, bool> shouldRemove) { using (var scope = _services.CreateScope()) { var context = scope.ServiceProvider.GetRequiredService(); - var keys = context.DataProtectionKeys.AsNoTracking().ToList(); - foreach (var key in keys) + var keys = new List(); + var elements = new List(); + + foreach (var key in context.DataProtectionKeys.AsNoTracking()) + { + if (!string.IsNullOrEmpty(key.Xml)) + { + keys.Add(key); + elements.Add(XElement.Parse(key.Xml)); + } + } + + for (var i = 0; i < keys.Count; i++) { - if (!string.IsNullOrEmpty(key.Xml) && shouldRemove(XElement.Parse(key.Xml))) + if (shouldRemove(elements[i], elements)) { - context.DataProtectionKeys.Remove(key); + var key = keys[i]; _logger.DeletingKeyFromDbContext(key.FriendlyName, typeof(TContext).Name); + try + { + context.DataProtectionKeys.Remove(key); + } + catch (Exception ex) + { + _logger.FailedToDeleteKeyFromDbContext(key.FriendlyName, typeof(TContext).Name, ex); + } } } diff --git a/src/DataProtection/EntityFrameworkCore/src/LoggingExtensions.cs b/src/DataProtection/EntityFrameworkCore/src/LoggingExtensions.cs index 3c8e047f73a9..e71f584a3cb2 100644 --- a/src/DataProtection/EntityFrameworkCore/src/LoggingExtensions.cs +++ b/src/DataProtection/EntityFrameworkCore/src/LoggingExtensions.cs @@ -13,4 +13,7 @@ internal static partial class LoggingExtensions [LoggerMessage(3, LogLevel.Debug, "Deleting key '{FriendlyName}' from '{DbContext}'.", EventName = "DeletingKeyFromDbContext")] public static partial void DeletingKeyFromDbContext(this ILogger logger, string? friendlyName, string dbContext); + + [LoggerMessage(4, LogLevel.Error, "Failed to delete key '{FriendlyName}' from '{DbContext}'.", EventName = "FailedToDeleteKeyFromDbContext")] + public static partial void FailedToDeleteKeyFromDbContext(this ILogger logger, string? friendlyName, string dbContext, Exception exception); } diff --git a/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt b/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt index 6c644621a2f7..b349a7c47e30 100644 --- a/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt +++ b/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt @@ -1,3 +1,3 @@ #nullable enable virtual Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.EntityFrameworkCoreXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.EntityFrameworkCoreXmlRepository.RemoveElements(System.Func! shouldRemove) -> void +virtual Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.EntityFrameworkCoreXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> void From be09a956be3d7ecc465cbc9f835e2f76a3e95408 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Tue, 6 Feb 2024 11:07:07 -0800 Subject: [PATCH 08/40] Started implementing key manager deletion and hit roadblock --- .../DataProtection/src/Error.cs | 6 + .../src/KeyManagement/IKeyManager.cs | 5 +- .../src/KeyManagement/XmlKeyManager.cs | 115 +++++++++++++++--- .../PublicAPI/net9.0/PublicAPI.Unshipped.txt | 4 +- .../DataProtection/src/Resources.resx | 3 + 5 files changed, 116 insertions(+), 17 deletions(-) diff --git a/src/DataProtection/DataProtection/src/Error.cs b/src/DataProtection/DataProtection/src/Error.cs index 00c1d3b59ce3..f3b874659bb5 100644 --- a/src/DataProtection/DataProtection/src/Error.cs +++ b/src/DataProtection/DataProtection/src/Error.cs @@ -102,4 +102,10 @@ public static InvalidOperationException KeyRingProvider_RefreshFailedOnOtherThre { return new InvalidOperationException(Resources.KeyRingProvider_RefreshFailedOnOtherThread, inner); } + + public static NotSupportedException XmlKeyManager_DoesNotSupportKeyDeletion() + { + var message = string.Format(CultureInfo.CurrentCulture, Resources.XmlKeyManager_DoesNotSupportKeyDeletion); + return new NotSupportedException(message); + } } diff --git a/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs index 9786539ead9d..80d0c39a4c15 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs @@ -97,6 +97,9 @@ public interface IKeyManager /// passed to . /// Use with caution as deleting active keys will normally cause data loss. /// + /// + /// True if all attempted deletions succeeded. + /// /// /// Generally, keys should only be deleted to save space. If space is not a concern, keys /// should be revoked or allowed to expire instead. @@ -107,6 +110,6 @@ public interface IKeyManager /// /// If is false. /// - void DeleteKeys(Func shouldDelete, bool unsafeIncludeUnexpired = false) => throw new NotSupportedException(); + bool DeleteKeys(Func shouldDelete, bool unsafeIncludeUnexpired = false) => throw new NotSupportedException(); #endif } diff --git a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs index aa4438b82c64..fef519a16006 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs @@ -164,11 +164,28 @@ private static string DateTimeOffsetToFilenameSafeString(DateTimeOffset dateTime public IReadOnlyCollection GetAllKeys() { var allElements = KeyRepository.GetAllElements(); + var keyIdToKeyMap = GetKeysWorker(allElements, collectElements: false, out _, out _, out _, out _, out _); - // We aggregate all the information we read into three buckets - Dictionary keyIdToKeyMap = new Dictionary(); - HashSet? revokedKeyIds = null; - DateTimeOffset? mostRecentMassRevocationDate = null; + // And we're finished! + return keyIdToKeyMap.Values.ToList().AsReadOnly(); + } + + private Dictionary GetKeysWorker( + IReadOnlyCollection allElements, + bool collectElements, + out Dictionary? keyElementToKeyIdMap, + out Dictionary? revocationIdToElementMap, + out DateTimeOffset? mostRecentMassRevocationDate, + out XElement? mostRecentMassRevocationElement, + out List? redundantRevocationElements) + { + Dictionary keyIdToKeyMap = []; + + keyElementToKeyIdMap = null; // Depends on collectElements + revocationIdToElementMap = null; + mostRecentMassRevocationDate = null; + mostRecentMassRevocationElement = null; // Depends on collectElements + redundantRevocationElements = null; // Depends on collectElements foreach (var element in allElements) { @@ -184,26 +201,55 @@ public IReadOnlyCollection GetAllKeys() throw Error.XmlKeyManager_DuplicateKey(key.KeyId); } keyIdToKeyMap[key.KeyId] = key; + + if (collectElements) + { + keyElementToKeyIdMap ??= new Dictionary(ReferenceEqualityComparer.Instance); + keyElementToKeyIdMap[element] = key.KeyId; + } } } else if (element.Name == RevocationElementName) { var revocationInfo = ProcessRevocationElement(element); - if (revocationInfo is Guid) + if (revocationInfo is Guid revocationGuid) { // a single key was revoked - if (revokedKeyIds == null) + revocationIdToElementMap ??= []; + if (revocationIdToElementMap.ContainsKey(revocationGuid)) + { + // TODO (acasey): log duplicate revocation + + if (collectElements) + { + redundantRevocationElements ??= []; + redundantRevocationElements.Add(element); + } + } + else { - revokedKeyIds = new HashSet(); + revocationIdToElementMap[revocationGuid] = element; } - revokedKeyIds.Add((Guid)revocationInfo); } else { // all keys as of a certain date were revoked - DateTimeOffset thisMassRevocationDate = (DateTimeOffset)revocationInfo; + var thisMassRevocationDate = (DateTimeOffset)revocationInfo; if (!mostRecentMassRevocationDate.HasValue || mostRecentMassRevocationDate < thisMassRevocationDate) { + if (collectElements) + { + if (mostRecentMassRevocationElement is not null) + { + // TODO (acasey): log redundant mass revocation + + redundantRevocationElements ??= []; + redundantRevocationElements.Add(mostRecentMassRevocationElement!); + } + + mostRecentMassRevocationElement = element; + } + mostRecentMassRevocationDate = thisMassRevocationDate; } } @@ -216,12 +262,11 @@ public IReadOnlyCollection GetAllKeys() } // Apply individual revocations - if (revokedKeyIds != null) + if (revocationIdToElementMap is not null) { - foreach (Guid revokedKeyId in revokedKeyIds) + foreach (Guid revokedKeyId in revocationIdToElementMap.Keys) { - keyIdToKeyMap.TryGetValue(revokedKeyId, out var key); - if (key != null) + if (keyIdToKeyMap.TryGetValue(revokedKeyId, out var key)) { key.SetRevoked(); _logger.MarkedKeyAsRevokedInTheKeyring(revokedKeyId); @@ -251,8 +296,7 @@ public IReadOnlyCollection GetAllKeys() } } - // And we're finished! - return keyIdToKeyMap.Values.ToList().AsReadOnly(); + return keyIdToKeyMap; } /// @@ -385,6 +429,47 @@ public void RevokeKey(Guid keyId, string? reason = null) reason: reason); } + /// + public bool CanDeleteKeys => KeyRepository.CanRemoveElements; + + /// + public bool DeleteKeys(Func shouldDelete, bool unsafeIncludeUnexpired = false) + { + if (!CanDeleteKeys) + { + throw Error.XmlKeyManager_DoesNotSupportKeyDeletion(); + } + + Dictionary? keyIdToKeyMap = null; + Dictionary? keyElementToKeyIdMap = null; + Dictionary? revocationIdToElementMap = null; + DateTimeOffset? mostRecentMassRevocationDate = null; + XElement? mostRecentMassRevocationElement = null; + List? redundantRevocationElements = null; + + KeyRepository.RemoveElements((element, allElements) => + { + keyIdToKeyMap ??= GetKeysWorker( + allElements, + collectElements: true, + out keyElementToKeyIdMap, + out revocationIdToElementMap, + out mostRecentMassRevocationDate, + out mostRecentMassRevocationElement, + out redundantRevocationElements); + + var keyId = keyElementToKeyIdMap![element]!; + var key = keyIdToKeyMap[keyId]; + if (shouldDelete(key)) + { + return true; + } + return false; + }); + + return true; + } + private void TriggerAndResetCacheExpirationToken([CallerMemberName] string? opName = null, bool suppressLogging = false) { if (!suppressLogging) diff --git a/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt index 2c94a8b38636..3f8a4473a1fe 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt @@ -1,6 +1,8 @@ #nullable enable Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.CanDeleteKeys.get -> bool -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.DeleteKeys(System.Func! shouldDelete, bool unsafeIncludeUnexpired = false) -> void +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.DeleteKeys(System.Func! shouldDelete, bool unsafeIncludeUnexpired = false) -> bool +Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.CanDeleteKeys.get -> bool +Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.DeleteKeys(System.Func! shouldDelete, bool unsafeIncludeUnexpired = false) -> bool Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.CanRemoveElements.get -> bool Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> void virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.CanRemoveElements.get -> bool diff --git a/src/DataProtection/DataProtection/src/Resources.resx b/src/DataProtection/DataProtection/src/Resources.resx index bb00dfe220bc..c9f64f385329 100644 --- a/src/DataProtection/DataProtection/src/Resources.resx +++ b/src/DataProtection/DataProtection/src/Resources.resx @@ -159,6 +159,9 @@ The key {0:B} already exists in the keyring. For more information go to https://aka.ms/aspnet/dataprotectionwarning + + This key manager does not support key deletion. + Argument cannot be null or empty. From f7cd631737fcaa784ff13cea16502867720acf39 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Tue, 6 Feb 2024 13:26:34 -0800 Subject: [PATCH 09/40] Return success from IXmlRepository.RemoveElements --- .../PublicAPI/net462/PublicAPI.Unshipped.txt | 4 ++-- .../PublicAPI/net9.0/PublicAPI.Unshipped.txt | 6 +++--- .../netstandard2.0/PublicAPI.Unshipped.txt | 4 ++-- .../src/Repositories/FileSystemXmlRepository.cs | 7 ++++++- .../src/Repositories/IXmlRepository.cs | 5 ++++- .../src/Repositories/RegistryXmlRepository.cs | 7 ++++++- .../src/EntityFrameworkCoreXmlRepository.cs | 17 +++++++++++++++-- .../src/LoggingExtensions.cs | 3 +++ 8 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt index 493e2922870e..f270439257cd 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt @@ -1,5 +1,5 @@ #nullable enable virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> void +virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> bool virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> void +virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> bool diff --git a/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt index 3f8a4473a1fe..05cbabab6634 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt @@ -4,8 +4,8 @@ Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.DeleteKeys(System. Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.CanDeleteKeys.get -> bool Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.DeleteKeys(System.Func! shouldDelete, bool unsafeIncludeUnexpired = false) -> bool Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.CanRemoveElements.get -> bool -Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> void +Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> bool virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> void +virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> bool virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> void +virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> bool diff --git a/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index 493e2922870e..f270439257cd 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,5 +1,5 @@ #nullable enable virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> void +virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> bool virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> void +virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> bool diff --git a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs index d018c21eaedc..46cc03bc0c7e 100644 --- a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs @@ -180,7 +180,7 @@ private void StoreElementCore(XElement element, string filename) public virtual bool CanRemoveElements => true; /// - public virtual void RemoveElements(Func, bool> shouldRemove) + public virtual bool RemoveElements(Func, bool> shouldRemove) { ArgumentNullThrowHelper.ThrowIfNull(shouldRemove); @@ -195,6 +195,8 @@ public virtual void RemoveElements(Func, elements.Add(element); } + var allSucceeded = true; + for (var i = 0; i < fileSystemInfos.Count; i++) { if (shouldRemove(elements[i], elements)) @@ -209,8 +211,11 @@ public virtual void RemoveElements(Func, { Debug.Assert(fileSystemInfo.Exists, "Having previously been deleted should not have caused an exception"); _logger.FailedToDeleteFile(fileSystemInfo.FullName, ex); + allSucceeded = false; } } } + + return allSucceeded; } } diff --git a/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs index 2122de5ad3d8..2dbc08e5f19c 100644 --- a/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs @@ -48,9 +48,12 @@ public interface IXmlRepository /// The second argument gives the contents of the collection before any removals. /// Returning true will cause the element to be removed from the repository. /// + /// + /// True if all deletions succeeded. + /// /// /// If is false. /// - void RemoveElements(Func, bool> shouldRemove) => throw new NotSupportedException(); + bool RemoveElements(Func, bool> shouldRemove) => throw new NotSupportedException(); #endif } diff --git a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs index 1665d35c5523..ef4a0d95b750 100644 --- a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs @@ -160,7 +160,7 @@ private void StoreElementCore(XElement element, string valueName) public virtual bool CanRemoveElements => true; /// - public virtual void RemoveElements(Func, bool> shouldRemove) + public virtual bool RemoveElements(Func, bool> shouldRemove) { ArgumentNullThrowHelper.ThrowIfNull(shouldRemove); @@ -177,6 +177,8 @@ public virtual void RemoveElements(Func, } } + var allSucceeded = true; + for (var i = 0; i < valueNames.Count; i++) { if (shouldRemove(elements[i], elements)) @@ -190,8 +192,11 @@ public virtual void RemoveElements(Func, catch (Exception ex) { _logger.FailedToRemoveDataFromRegistryKeyValue(RegistryKey, valueName, ex); + allSucceeded = false; } } } + + return allSucceeded; } } diff --git a/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs b/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs index 792fa6ef6aa2..7a6e2e9ef69b 100644 --- a/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs +++ b/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs @@ -84,7 +84,7 @@ public void StoreElement(XElement element, string friendlyName) public virtual bool CanRemoveElements => true; /// - public virtual void RemoveElements(Func, bool> shouldRemove) + public virtual bool RemoveElements(Func, bool> shouldRemove) { using (var scope = _services.CreateScope()) { @@ -101,6 +101,8 @@ public virtual void RemoveElements(Func, } } + var allSucceeded = true; + for (var i = 0; i < keys.Count; i++) { if (shouldRemove(elements[i], elements)) @@ -114,11 +116,22 @@ public virtual void RemoveElements(Func, catch (Exception ex) { _logger.FailedToDeleteKeyFromDbContext(key.FriendlyName, typeof(TContext).Name, ex); + allSucceeded = false; } } } - context.SaveChanges(); + try + { + context.SaveChanges(); + } + catch (Exception ex) + { + _logger.FailedToSaveKeyDeletionsToDbContext(typeof(TContext).Name, ex); + allSucceeded = false; + } + + return allSucceeded; } } } diff --git a/src/DataProtection/EntityFrameworkCore/src/LoggingExtensions.cs b/src/DataProtection/EntityFrameworkCore/src/LoggingExtensions.cs index e71f584a3cb2..db6e63bdda32 100644 --- a/src/DataProtection/EntityFrameworkCore/src/LoggingExtensions.cs +++ b/src/DataProtection/EntityFrameworkCore/src/LoggingExtensions.cs @@ -16,4 +16,7 @@ internal static partial class LoggingExtensions [LoggerMessage(4, LogLevel.Error, "Failed to delete key '{FriendlyName}' from '{DbContext}'.", EventName = "FailedToDeleteKeyFromDbContext")] public static partial void FailedToDeleteKeyFromDbContext(this ILogger logger, string? friendlyName, string dbContext, Exception exception); + + [LoggerMessage(5, LogLevel.Error, "Failed to save key deletions to '{DbContext}'.", EventName = "FailedToSaveKeyDeletionsToDbContext")] + public static partial void FailedToSaveKeyDeletionsToDbContext(this ILogger logger, string dbContext, Exception exception); } From c611fca49ee814666f3e93659ed0271fc5a2463a Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Tue, 6 Feb 2024 13:56:06 -0800 Subject: [PATCH 10/40] Finish implementing key manager deletion --- .../src/KeyManagement/XmlKeyManager.cs | 79 +++++++++++-------- .../src/PublicAPI.Unshipped.txt | 2 +- 2 files changed, 49 insertions(+), 32 deletions(-) diff --git a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs index fef519a16006..1499731faa0c 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs @@ -164,7 +164,7 @@ private static string DateTimeOffsetToFilenameSafeString(DateTimeOffset dateTime public IReadOnlyCollection GetAllKeys() { var allElements = KeyRepository.GetAllElements(); - var keyIdToKeyMap = GetKeysWorker(allElements, collectElements: false, out _, out _, out _, out _, out _); + var keyIdToKeyMap = GetKeysWorker(allElements, collectElements: false, out _, out _, out _); // And we're finished! return keyIdToKeyMap.Values.ToList().AsReadOnly(); @@ -173,19 +173,19 @@ public IReadOnlyCollection GetAllKeys() private Dictionary GetKeysWorker( IReadOnlyCollection allElements, bool collectElements, - out Dictionary? keyElementToKeyIdMap, + out Dictionary? keyIdToKeyElementMap, out Dictionary? revocationIdToElementMap, - out DateTimeOffset? mostRecentMassRevocationDate, - out XElement? mostRecentMassRevocationElement, out List? redundantRevocationElements) { Dictionary keyIdToKeyMap = []; - keyElementToKeyIdMap = null; // Depends on collectElements + keyIdToKeyElementMap = null; // Stays null unless collectElements revocationIdToElementMap = null; - mostRecentMassRevocationDate = null; - mostRecentMassRevocationElement = null; // Depends on collectElements - redundantRevocationElements = null; // Depends on collectElements + + redundantRevocationElements = null; // Stays null unless collectElements + + DateTimeOffset? mostRecentMassRevocationDate = null; + XElement? mostRecentMassRevocationElement = null; // Stays null unless collectElements foreach (var element in allElements) { @@ -204,8 +204,8 @@ private Dictionary GetKeysWorker( if (collectElements) { - keyElementToKeyIdMap ??= new Dictionary(ReferenceEqualityComparer.Instance); - keyElementToKeyIdMap[element] = key.KeyId; + keyIdToKeyElementMap ??= []; + keyIdToKeyElementMap[key.KeyId] = element; } } } @@ -429,6 +429,7 @@ public void RevokeKey(Guid keyId, string? reason = null) reason: reason); } +#if NETCOREAPP /// public bool CanDeleteKeys => KeyRepository.CanRemoveElements; @@ -440,35 +441,51 @@ public bool DeleteKeys(Func shouldDelete, bool unsafeIncludeUnexpire throw Error.XmlKeyManager_DoesNotSupportKeyDeletion(); } - Dictionary? keyIdToKeyMap = null; - Dictionary? keyElementToKeyIdMap = null; - Dictionary? revocationIdToElementMap = null; - DateTimeOffset? mostRecentMassRevocationDate = null; - XElement? mostRecentMassRevocationElement = null; - List? redundantRevocationElements = null; + HashSet? elementsToRemove = null; + + return KeyRepository.RemoveElements((element, allElements) => + { + // All the actual work happens on the first iteration - subsequent iterations just check set membership + elementsToRemove ??= GetElementsToRemove(allElements); + return elementsToRemove.Contains(element); + }); - KeyRepository.RemoveElements((element, allElements) => + HashSet GetElementsToRemove(IReadOnlyCollection allElements) { - keyIdToKeyMap ??= GetKeysWorker( + var keyIdToKeyMap = GetKeysWorker( allElements, collectElements: true, - out keyElementToKeyIdMap, - out revocationIdToElementMap, - out mostRecentMassRevocationDate, - out mostRecentMassRevocationElement, - out redundantRevocationElements); - - var keyId = keyElementToKeyIdMap![element]!; - var key = keyIdToKeyMap[keyId]; - if (shouldDelete(key)) + out var keyIdToKeyElementMap, + out var revocationIdToElementMap, + out var redundantRevocationElements); + + var elementsToRemove = new HashSet(ReferenceEqualityComparer.Instance); + + foreach (var pair in keyIdToKeyMap) { - return true; + var key = pair.Value; + var keyId = pair.Key; + if (shouldDelete(key)) + { + var keyElement = keyIdToKeyElementMap![keyId]; + elementsToRemove.Add(keyElement); + + if (revocationIdToElementMap is not null && revocationIdToElementMap.TryGetValue(keyId, out var revocationElement)) + { + elementsToRemove.Add(revocationElement); + } + } } - return false; - }); - return true; + if (redundantRevocationElements is not null) + { + elementsToRemove.UnionWith(redundantRevocationElements); + } + + return elementsToRemove; + } } +#endif private void TriggerAndResetCacheExpirationToken([CallerMemberName] string? opName = null, bool suppressLogging = false) { diff --git a/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt b/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt index b349a7c47e30..1483b2473641 100644 --- a/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt +++ b/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt @@ -1,3 +1,3 @@ #nullable enable virtual Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.EntityFrameworkCoreXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.EntityFrameworkCoreXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> void +virtual Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.EntityFrameworkCoreXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> bool From 8a7d9ed2bcb2e7cdd7aefb3bc77c35f569b94e7f Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Tue, 6 Feb 2024 16:29:50 -0800 Subject: [PATCH 11/40] Add more logging --- .../DataProtection/src/KeyManagement/XmlKeyManager.cs | 7 +++++-- .../DataProtection/src/LoggingExtensions.cs | 9 +++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs index 1499731faa0c..680e1cb0c012 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs @@ -218,7 +218,7 @@ private Dictionary GetKeysWorker( revocationIdToElementMap ??= []; if (revocationIdToElementMap.ContainsKey(revocationGuid)) { - // TODO (acasey): log duplicate revocation + _logger.KeyRevokedMultipleTimes(revocationGuid); if (collectElements) { @@ -241,7 +241,8 @@ private Dictionary GetKeysWorker( { if (mostRecentMassRevocationElement is not null) { - // TODO (acasey): log redundant mass revocation + // Ideally, this would report the most recent revocation date, but it's not worth an extra iteration + _logger.DateBasedRevocationSuperseded(mostRecentMassRevocationDate!.Value, thisMassRevocationDate); redundantRevocationElements ??= []; redundantRevocationElements.Add(mostRecentMassRevocationElement!); @@ -467,6 +468,8 @@ HashSet GetElementsToRemove(IReadOnlyCollection allElements) var keyId = pair.Key; if (shouldDelete(key)) { + _logger.DeletingKey(keyId); + var keyElement = keyIdToKeyElementMap![keyId]; elementsToRemove.Add(keyElement); diff --git a/src/DataProtection/DataProtection/src/LoggingExtensions.cs b/src/DataProtection/DataProtection/src/LoggingExtensions.cs index 0b008cff0551..88499e8c524e 100644 --- a/src/DataProtection/DataProtection/src/LoggingExtensions.cs +++ b/src/DataProtection/DataProtection/src/LoggingExtensions.cs @@ -267,4 +267,13 @@ private static bool IsLogLevelEnabledCore([NotNullWhen(true)] ILogger? logger, L [LoggerMessage(77, LogLevel.Error, "Failed to delete registry key '{RegistryKeyName}', value '{ValueName}'.", EventName = "FailedToRemoveDataFromRegistryKeyValue")] public static partial void FailedToRemoveDataFromRegistryKeyValue(this ILogger logger, RegistryKey registryKeyName, string valueName, Exception exception); + + [LoggerMessage(75, LogLevel.Trace, "Found multiple revocation entries for key {KeyId:B}.", EventName = "KeyRevokedMultipleTimes")] + public static partial void KeyRevokedMultipleTimes(this ILogger logger, Guid keyId); + + [LoggerMessage(76, LogLevel.Trace, "Ignoring revocation of keys created before {OlderDate:u} in favor of revocation of keys created before {NewerDate:u}.", EventName = "DateBasedRevocationSuperseded")] + public static partial void DateBasedRevocationSuperseded(this ILogger logger, DateTimeOffset olderDate, DateTimeOffset newerDate); + + [LoggerMessage(77, LogLevel.Debug, "Deleting key {KeyId:B}.", EventName = "DeletingKey")] + public static partial void DeletingKey(this ILogger logger, Guid keyId); } From 22a30ba7bc9b092eb519f6811210c15ed44a7596 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Tue, 6 Feb 2024 16:57:08 -0800 Subject: [PATCH 12/40] Consume unsafeIncludeUnexpired --- .../DataProtection/src/KeyManagement/XmlKeyManager.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs index 680e1cb0c012..d5a95bc87a09 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs @@ -461,12 +461,14 @@ HashSet GetElementsToRemove(IReadOnlyCollection allElements) out var redundantRevocationElements); var elementsToRemove = new HashSet(ReferenceEqualityComparer.Instance); + var now = DateTimeOffset.Now; foreach (var pair in keyIdToKeyMap) { var key = pair.Value; var keyId = pair.Key; - if (shouldDelete(key)) + + if ((unsafeIncludeUnexpired || key.ExpirationDate < now) && shouldDelete(key)) { _logger.DeletingKey(keyId); From 98a408e38cee118089cce278aa568d3bbce81cf7 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Wed, 7 Feb 2024 13:55:54 -0800 Subject: [PATCH 13/40] Change IXmlRepository.RemoveElements to use a mutating Action --- .../src/KeyManagement/XmlKeyManager.cs | 146 ++++++++---------- .../PublicAPI/net462/PublicAPI.Unshipped.txt | 8 +- .../PublicAPI/net9.0/PublicAPI.Unshipped.txt | 10 +- .../netstandard2.0/PublicAPI.Unshipped.txt | 8 +- .../Repositories/FileSystemXmlRepository.cs | 33 ++-- .../src/Repositories/IDeletableElement.cs | 17 ++ .../src/Repositories/IXmlRepository.cs | 9 +- .../src/Repositories/RegistryXmlRepository.cs | 34 ++-- .../src/EntityFrameworkCoreXmlRepository.cs | 31 +++- .../src/PublicAPI.Unshipped.txt | 2 +- 10 files changed, 175 insertions(+), 123 deletions(-) create mode 100644 src/DataProtection/DataProtection/src/Repositories/IDeletableElement.cs diff --git a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs index d5a95bc87a09..a336e4b0864b 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs @@ -164,36 +164,38 @@ private static string DateTimeOffsetToFilenameSafeString(DateTimeOffset dateTime public IReadOnlyCollection GetAllKeys() { var allElements = KeyRepository.GetAllElements(); - var keyIdToKeyMap = GetKeysWorker(allElements, collectElements: false, out _, out _, out _); - - // And we're finished! - return keyIdToKeyMap.Values.ToList().AsReadOnly(); + var processed = ProcessAllElements(allElements, out _); + return processed.OfType().ToList().AsReadOnly(); } - private Dictionary GetKeysWorker( - IReadOnlyCollection allElements, - bool collectElements, - out Dictionary? keyIdToKeyElementMap, - out Dictionary? revocationIdToElementMap, - out List? redundantRevocationElements) + /// + /// Returns an array paralleling but: + /// 1. Key elements become IKeys (with revocation data) + /// 2. KeyId-based revocations become Guids + /// 3. Date-based revocations become DateTimeOffsets + /// 4. Unknown elements become null + /// + private object?[] ProcessAllElements(IReadOnlyCollection allElements, out DateTimeOffset? mostRecentMassRevocationDate) { - Dictionary keyIdToKeyMap = []; + var elementCount = allElements.Count; - keyIdToKeyElementMap = null; // Stays null unless collectElements - revocationIdToElementMap = null; + var results = new object?[elementCount]; - redundantRevocationElements = null; // Stays null unless collectElements + Dictionary keyIdToKeyMap = []; + HashSet? revokedIds = null; - DateTimeOffset? mostRecentMassRevocationDate = null; - XElement? mostRecentMassRevocationElement = null; // Stays null unless collectElements + mostRecentMassRevocationDate = null; + var pos = 0; foreach (var element in allElements) { + object? result; if (element.Name == KeyElementName) { // ProcessKeyElement can return null in the case of failure, and if this happens we'll move on. // Still need to throw if we see duplicate keys with the same id. var key = ProcessKeyElement(element); + result = key; if (key != null) { if (keyIdToKeyMap.ContainsKey(key.KeyId)) @@ -201,34 +203,19 @@ private Dictionary GetKeysWorker( throw Error.XmlKeyManager_DuplicateKey(key.KeyId); } keyIdToKeyMap[key.KeyId] = key; - - if (collectElements) - { - keyIdToKeyElementMap ??= []; - keyIdToKeyElementMap[key.KeyId] = element; - } } } else if (element.Name == RevocationElementName) { var revocationInfo = ProcessRevocationElement(element); + result = revocationInfo; if (revocationInfo is Guid revocationGuid) { // a single key was revoked - revocationIdToElementMap ??= []; - if (revocationIdToElementMap.ContainsKey(revocationGuid)) + revokedIds ??= []; + if (!revokedIds.Add(revocationGuid)) { _logger.KeyRevokedMultipleTimes(revocationGuid); - - if (collectElements) - { - redundantRevocationElements ??= []; - redundantRevocationElements.Add(element); - } - } - else - { - revocationIdToElementMap[revocationGuid] = element; } } else @@ -237,20 +224,6 @@ private Dictionary GetKeysWorker( var thisMassRevocationDate = (DateTimeOffset)revocationInfo; if (!mostRecentMassRevocationDate.HasValue || mostRecentMassRevocationDate < thisMassRevocationDate) { - if (collectElements) - { - if (mostRecentMassRevocationElement is not null) - { - // Ideally, this would report the most recent revocation date, but it's not worth an extra iteration - _logger.DateBasedRevocationSuperseded(mostRecentMassRevocationDate!.Value, thisMassRevocationDate); - - redundantRevocationElements ??= []; - redundantRevocationElements.Add(mostRecentMassRevocationElement!); - } - - mostRecentMassRevocationElement = element; - } - mostRecentMassRevocationDate = thisMassRevocationDate; } } @@ -259,13 +232,16 @@ private Dictionary GetKeysWorker( { // Skip unknown elements. _logger.UnknownElementWithNameFoundInKeyringSkipping(element.Name); + result = null; } + + results[pos++] = result; } // Apply individual revocations - if (revocationIdToElementMap is not null) + if (revokedIds is not null) { - foreach (Guid revokedKeyId in revocationIdToElementMap.Keys) + foreach (Guid revokedKeyId in revokedIds) { if (keyIdToKeyMap.TryGetValue(revokedKeyId, out var key)) { @@ -297,7 +273,7 @@ private Dictionary GetKeysWorker( } } - return keyIdToKeyMap; + return results; } /// @@ -442,53 +418,55 @@ public bool DeleteKeys(Func shouldDelete, bool unsafeIncludeUnexpire throw Error.XmlKeyManager_DoesNotSupportKeyDeletion(); } - HashSet? elementsToRemove = null; - - return KeyRepository.RemoveElements((element, allElements) => + return KeyRepository.RemoveElements((deletableElements) => { - // All the actual work happens on the first iteration - subsequent iterations just check set membership - elementsToRemove ??= GetElementsToRemove(allElements); - return elementsToRemove.Contains(element); - }); + var deletableElementsArray = deletableElements.ToArray(); + + var allElements = deletableElements.Select(d => d.Element).ToArray(); + var processed = ProcessAllElements(allElements, out var mostRecentMassRevocationDate); + + var allKeyIds = new HashSet(); + var deletedKeyIds = new HashSet(); - HashSet GetElementsToRemove(IReadOnlyCollection allElements) - { - var keyIdToKeyMap = GetKeysWorker( - allElements, - collectElements: true, - out var keyIdToKeyElementMap, - out var revocationIdToElementMap, - out var redundantRevocationElements); - - var elementsToRemove = new HashSet(ReferenceEqualityComparer.Instance); var now = DateTimeOffset.Now; - foreach (var pair in keyIdToKeyMap) + for (var i = 0; i < deletableElementsArray.Length; i++) { - var key = pair.Value; - var keyId = pair.Key; - - if ((unsafeIncludeUnexpired || key.ExpirationDate < now) && shouldDelete(key)) + var obj = processed[i]; + if (obj is IKey key) { - _logger.DeletingKey(keyId); + var keyId = key.KeyId; + allKeyIds.Add(keyId); - var keyElement = keyIdToKeyElementMap![keyId]; - elementsToRemove.Add(keyElement); - - if (revocationIdToElementMap is not null && revocationIdToElementMap.TryGetValue(keyId, out var revocationElement)) + if ((unsafeIncludeUnexpired || key.ExpirationDate < now) && shouldDelete(key)) + { + _logger.DeletingKey(keyId); + deletedKeyIds.Add(keyId); + deletableElementsArray[i].ShouldDelete = true; + } + } + else if (obj is DateTimeOffset massRevocationDate) + { + if (massRevocationDate < mostRecentMassRevocationDate) { - elementsToRemove.Add(revocationElement); + // Delete superceded mass revocation elements + deletableElementsArray[i].ShouldDelete = true; } } } - if (redundantRevocationElements is not null) + for (var i = 0; i < deletableElementsArray.Length; i++) { - elementsToRemove.UnionWith(redundantRevocationElements); + if (processed[i] is Guid revocationId) + { + // Delete individual revocations of keys that don't (still) exist + if (deletedKeyIds.Contains(revocationId) || !allKeyIds.Contains(revocationId)) + { + deletableElementsArray[i].ShouldDelete = true; + } + } } - - return elementsToRemove; - } + }); } #endif diff --git a/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt index f270439257cd..ac81ae6721dc 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt @@ -1,5 +1,9 @@ #nullable enable +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.Element.get -> System.Xml.Linq.XElement! +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.ShouldDelete.get -> bool +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.ShouldDelete.set -> void virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> bool +virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> bool +virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool diff --git a/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt index 05cbabab6634..a2105e0e9fc5 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt @@ -3,9 +3,13 @@ Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.CanDeleteKeys.get Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.DeleteKeys(System.Func! shouldDelete, bool unsafeIncludeUnexpired = false) -> bool Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.CanDeleteKeys.get -> bool Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.DeleteKeys(System.Func! shouldDelete, bool unsafeIncludeUnexpired = false) -> bool +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.Element.get -> System.Xml.Linq.XElement! +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.ShouldDelete.get -> bool +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.ShouldDelete.set -> void Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.CanRemoveElements.get -> bool -Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> bool +Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> bool +virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> bool +virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool diff --git a/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index f270439257cd..ac81ae6721dc 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,5 +1,9 @@ #nullable enable +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.Element.get -> System.Xml.Linq.XElement! +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.ShouldDelete.get -> bool +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.ShouldDelete.set -> void virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> bool +virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> bool +virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool diff --git a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs index 46cc03bc0c7e..0d701df5da9b 100644 --- a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs @@ -180,28 +180,28 @@ private void StoreElementCore(XElement element, string filename) public virtual bool CanRemoveElements => true; /// - public virtual bool RemoveElements(Func, bool> shouldRemove) + public virtual bool RemoveElements(Action> chooseElements) { - ArgumentNullThrowHelper.ThrowIfNull(shouldRemove); + ArgumentNullThrowHelper.ThrowIfNull(chooseElements); - var fileSystemInfos = new List(); - var elements = new List(); + var deletableElements = new List(); foreach (var fileSystemInfo in EnumerateFileSystemInfos()) { var fullPath = fileSystemInfo.FullName; var element = ReadElementFromFile(fullPath); - fileSystemInfos.Add(fileSystemInfo); - elements.Add(element); + deletableElements.Add(new DeletableElement(fileSystemInfo, element)); } + chooseElements(deletableElements); + var allSucceeded = true; - for (var i = 0; i < fileSystemInfos.Count; i++) + foreach (var deletableElement in deletableElements) { - if (shouldRemove(elements[i], elements)) + if (deletableElement.ShouldDelete) { - var fileSystemInfo = fileSystemInfos[i]; + var fileSystemInfo = deletableElement.FileSystemInfo; _logger.DeletingFile(fileSystemInfo.FullName); try { @@ -218,4 +218,19 @@ public virtual bool RemoveElements(Func, return allSucceeded; } + + private sealed class DeletableElement : IDeletableElement + { + public DeletableElement(FileSystemInfo fileSystemInfo, XElement element) + { + FileSystemInfo = fileSystemInfo; + Element = element; + } + + public XElement Element { get; } + + public FileSystemInfo FileSystemInfo { get; } + + public bool ShouldDelete { get; set; } + } } diff --git a/src/DataProtection/DataProtection/src/Repositories/IDeletableElement.cs b/src/DataProtection/DataProtection/src/Repositories/IDeletableElement.cs new file mode 100644 index 000000000000..b61b2b4b523a --- /dev/null +++ b/src/DataProtection/DataProtection/src/Repositories/IDeletableElement.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection.Repositories; + +/// +/// Represents an XML element in an that can be deleted. +/// +public interface IDeletableElement +{ + /// The XML element. + public XElement Element { get; } + /// Set to true if the element should be deleted. + public bool ShouldDelete { get; set; } +} diff --git a/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs index 2dbc08e5f19c..d746cbee8f16 100644 --- a/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs @@ -43,10 +43,9 @@ public interface IXmlRepository /// /// Removes elements satisfying the given predicate. /// - /// - /// A predicate applied to each element. - /// The second argument gives the contents of the collection before any removals. - /// Returning true will cause the element to be removed from the repository. + /// + /// A snapshot of the elements in this repository. + /// For each, set to true if it should be deleted. /// /// /// True if all deletions succeeded. @@ -54,6 +53,6 @@ public interface IXmlRepository /// /// If is false. /// - bool RemoveElements(Func, bool> shouldRemove) => throw new NotSupportedException(); + bool RemoveElements(Action> chooseElements) => throw new NotSupportedException(); #endif } diff --git a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs index ef4a0d95b750..630a4892cf99 100644 --- a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Linq; using System.Runtime.Versioning; using System.Security.Principal; @@ -160,30 +161,30 @@ private void StoreElementCore(XElement element, string valueName) public virtual bool CanRemoveElements => true; /// - public virtual bool RemoveElements(Func, bool> shouldRemove) + public virtual bool RemoveElements(Action> chooseElements) { - ArgumentNullThrowHelper.ThrowIfNull(shouldRemove); + ArgumentNullThrowHelper.ThrowIfNull(chooseElements); - var valueNames = new List(); - var elements = new List(); + var deletableElements = new List(); foreach (var valueName in RegistryKey.GetValueNames()) { var element = ReadElementFromRegKey(RegistryKey, valueName); if (element is not null) { - valueNames.Add(valueName); - elements.Add(element); + deletableElements.Add(new DeletableElement(valueName, element)); } } + chooseElements(deletableElements); + var allSucceeded = true; - for (var i = 0; i < valueNames.Count; i++) + foreach (var deletableElement in deletableElements) { - if (shouldRemove(elements[i], elements)) + if (deletableElement.ShouldDelete) { - var valueName = valueNames[i]; + var valueName = deletableElement.ValueName; _logger.RemovingDataFromRegistryKeyValue(RegistryKey, valueName); try { @@ -199,4 +200,19 @@ public virtual bool RemoveElements(Func, return allSucceeded; } + + private sealed class DeletableElement : IDeletableElement + { + public DeletableElement(string valueName, XElement element) + { + ValueName = valueName; + Element = element; + } + + public XElement Element { get; } + + public string ValueName { get; } + + public bool ShouldDelete { get; set; } + } } diff --git a/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs b/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs index 7a6e2e9ef69b..18935a9630d1 100644 --- a/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs +++ b/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs @@ -84,30 +84,30 @@ public void StoreElement(XElement element, string friendlyName) public virtual bool CanRemoveElements => true; /// - public virtual bool RemoveElements(Func, bool> shouldRemove) + public virtual bool RemoveElements(Action> chooseElements) { using (var scope = _services.CreateScope()) { var context = scope.ServiceProvider.GetRequiredService(); - var keys = new List(); - var elements = new List(); + var deletableElements = new List(); foreach (var key in context.DataProtectionKeys.AsNoTracking()) { if (!string.IsNullOrEmpty(key.Xml)) { - keys.Add(key); - elements.Add(XElement.Parse(key.Xml)); + deletableElements.Add(new DeletableElement(key, XElement.Parse(key.Xml))); } } + chooseElements(deletableElements); + var allSucceeded = true; - for (var i = 0; i < keys.Count; i++) + foreach (var deletableElement in deletableElements) { - if (shouldRemove(elements[i], elements)) + if (deletableElement.ShouldDelete) { - var key = keys[i]; + var key = deletableElement.Key; _logger.DeletingKeyFromDbContext(key.FriendlyName, typeof(TContext).Name); try { @@ -134,4 +134,19 @@ public virtual bool RemoveElements(Func, return allSucceeded; } } + + private sealed class DeletableElement : IDeletableElement + { + public DeletableElement(DataProtectionKey key, XElement element) + { + Key = key; + Element = element; + } + + public XElement Element { get; } + + public DataProtectionKey Key { get; } + + public bool ShouldDelete { get; set; } + } } diff --git a/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt b/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt index 1483b2473641..ffe18c85f65b 100644 --- a/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt +++ b/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt @@ -1,3 +1,3 @@ #nullable enable virtual Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.EntityFrameworkCoreXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.EntityFrameworkCoreXmlRepository.RemoveElements(System.Func!, bool>! shouldRemove) -> bool +virtual Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.EntityFrameworkCoreXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool From 2fb6656ab9d9e5f78c2b1c55f94d6c618fa578d8 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Wed, 7 Feb 2024 14:17:28 -0800 Subject: [PATCH 14/40] Tidy up diff --- .../DataProtection/src/KeyManagement/XmlKeyManager.cs | 11 ++++++----- .../src/Repositories/RegistryXmlRepository.cs | 1 - 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs index a336e4b0864b..5d4f777c6963 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs @@ -182,7 +182,7 @@ public IReadOnlyCollection GetAllKeys() var results = new object?[elementCount]; Dictionary keyIdToKeyMap = []; - HashSet? revokedIds = null; + HashSet? revokedKeyIds = null; mostRecentMassRevocationDate = null; @@ -212,8 +212,8 @@ public IReadOnlyCollection GetAllKeys() if (revocationInfo is Guid revocationGuid) { // a single key was revoked - revokedIds ??= []; - if (!revokedIds.Add(revocationGuid)) + revokedKeyIds ??= []; + if (!revokedKeyIds.Add(revocationGuid)) { _logger.KeyRevokedMultipleTimes(revocationGuid); } @@ -239,9 +239,9 @@ public IReadOnlyCollection GetAllKeys() } // Apply individual revocations - if (revokedIds is not null) + if (revokedKeyIds is not null) { - foreach (Guid revokedKeyId in revokedIds) + foreach (var revokedKeyId in revokedKeyIds) { if (keyIdToKeyMap.TryGetValue(revokedKeyId, out var key)) { @@ -273,6 +273,7 @@ public IReadOnlyCollection GetAllKeys() } } + // And we're finished! return results; } diff --git a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs index 630a4892cf99..ee2c3f960216 100644 --- a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.IO; using System.Linq; using System.Runtime.Versioning; using System.Security.Principal; From a5b35cbd83efd77107b28a296c878e523ce93b80 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 2 May 2024 12:27:56 -0700 Subject: [PATCH 15/40] Fix merge --- src/DataProtection/DataProtection/src/LoggingExtensions.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/DataProtection/DataProtection/src/LoggingExtensions.cs b/src/DataProtection/DataProtection/src/LoggingExtensions.cs index 88499e8c524e..3e545d38a2a7 100644 --- a/src/DataProtection/DataProtection/src/LoggingExtensions.cs +++ b/src/DataProtection/DataProtection/src/LoggingExtensions.cs @@ -268,12 +268,12 @@ private static bool IsLogLevelEnabledCore([NotNullWhen(true)] ILogger? logger, L [LoggerMessage(77, LogLevel.Error, "Failed to delete registry key '{RegistryKeyName}', value '{ValueName}'.", EventName = "FailedToRemoveDataFromRegistryKeyValue")] public static partial void FailedToRemoveDataFromRegistryKeyValue(this ILogger logger, RegistryKey registryKeyName, string valueName, Exception exception); - [LoggerMessage(75, LogLevel.Trace, "Found multiple revocation entries for key {KeyId:B}.", EventName = "KeyRevokedMultipleTimes")] + [LoggerMessage(78, LogLevel.Trace, "Found multiple revocation entries for key {KeyId:B}.", EventName = "KeyRevokedMultipleTimes")] public static partial void KeyRevokedMultipleTimes(this ILogger logger, Guid keyId); - [LoggerMessage(76, LogLevel.Trace, "Ignoring revocation of keys created before {OlderDate:u} in favor of revocation of keys created before {NewerDate:u}.", EventName = "DateBasedRevocationSuperseded")] + [LoggerMessage(79, LogLevel.Trace, "Ignoring revocation of keys created before {OlderDate:u} in favor of revocation of keys created before {NewerDate:u}.", EventName = "DateBasedRevocationSuperseded")] public static partial void DateBasedRevocationSuperseded(this ILogger logger, DateTimeOffset olderDate, DateTimeOffset newerDate); - [LoggerMessage(77, LogLevel.Debug, "Deleting key {KeyId:B}.", EventName = "DeletingKey")] + [LoggerMessage(80, LogLevel.Debug, "Deleting key {KeyId:B}.", EventName = "DeletingKey")] public static partial void DeletingKey(this ILogger logger, Guid keyId); } From aa0abf59e3aa82500538af43ddb7c36e89137f4b Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Fri, 3 May 2024 15:45:51 -0700 Subject: [PATCH 16/40] Remove unsafeIncludeUnexpired --- .../DataProtection/src/KeyManagement/IKeyManager.cs | 11 ++++------- .../DataProtection/src/KeyManagement/XmlKeyManager.cs | 4 ++-- .../src/PublicAPI/net9.0/PublicAPI.Unshipped.txt | 4 ++-- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs index 80d0c39a4c15..2b365ff31d31 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs @@ -87,16 +87,13 @@ public interface IKeyManager /// /// Deletes keys matching a predicate. + /// + /// Use with caution as deleting active keys will normally cause data loss. /// /// - /// A predicate applied to each expired key (and unexpired key if is true). + /// A predicate applied to each key. /// Returning true will cause the key to be deleted. /// - /// - /// True indicates that unexpired keys (which may be presently or yet to be activated) should also be - /// passed to . - /// Use with caution as deleting active keys will normally cause data loss. - /// /// /// True if all attempted deletions succeeded. /// @@ -110,6 +107,6 @@ public interface IKeyManager /// /// If is false. /// - bool DeleteKeys(Func shouldDelete, bool unsafeIncludeUnexpired = false) => throw new NotSupportedException(); + bool DeleteKeys(Func shouldDelete) => throw new NotSupportedException(); #endif } diff --git a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs index 5d4f777c6963..c46bf3fc3985 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs @@ -412,7 +412,7 @@ public void RevokeKey(Guid keyId, string? reason = null) public bool CanDeleteKeys => KeyRepository.CanRemoveElements; /// - public bool DeleteKeys(Func shouldDelete, bool unsafeIncludeUnexpired = false) + public bool DeleteKeys(Func shouldDelete) { if (!CanDeleteKeys) { @@ -439,7 +439,7 @@ public bool DeleteKeys(Func shouldDelete, bool unsafeIncludeUnexpire var keyId = key.KeyId; allKeyIds.Add(keyId); - if ((unsafeIncludeUnexpired || key.ExpirationDate < now) && shouldDelete(key)) + if (shouldDelete(key)) { _logger.DeletingKey(keyId); deletedKeyIds.Add(keyId); diff --git a/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt index a2105e0e9fc5..8c3ae72870d1 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt @@ -1,8 +1,8 @@ #nullable enable Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.CanDeleteKeys.get -> bool -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.DeleteKeys(System.Func! shouldDelete, bool unsafeIncludeUnexpired = false) -> bool +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.DeleteKeys(System.Func! shouldDelete) -> bool Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.CanDeleteKeys.get -> bool -Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.DeleteKeys(System.Func! shouldDelete, bool unsafeIncludeUnexpired = false) -> bool +Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.DeleteKeys(System.Func! shouldDelete) -> bool Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.Element.get -> System.Xml.Linq.XElement! Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.ShouldDelete.get -> bool From 96524e4e1cb320a4c18f677abf967dc76c551d59 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Fri, 3 May 2024 16:10:17 -0700 Subject: [PATCH 17/40] Switch from ShouldDelete to DeletionOrder --- .../src/KeyManagement/XmlKeyManager.cs | 15 ++++++-- .../PublicAPI/net462/PublicAPI.Unshipped.txt | 4 +-- .../PublicAPI/net9.0/PublicAPI.Unshipped.txt | 4 +-- .../netstandard2.0/PublicAPI.Unshipped.txt | 4 +-- .../Repositories/FileSystemXmlRepository.cs | 34 +++++++++++-------- .../src/Repositories/IDeletableElement.cs | 4 +-- .../src/Repositories/IXmlRepository.cs | 3 +- .../src/Repositories/RegistryXmlRepository.cs | 33 ++++++++++-------- .../src/EntityFrameworkCoreXmlRepository.cs | 32 +++++++++-------- 9 files changed, 78 insertions(+), 55 deletions(-) diff --git a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs index c46bf3fc3985..5f893ab09e93 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs @@ -421,6 +421,15 @@ public bool DeleteKeys(Func shouldDelete) return KeyRepository.RemoveElements((deletableElements) => { + // It is important to delete key elements before the corresponding revocation elements, + // in case the deletion fails part way - we don't want to accidentally unrevoke a key + // and then not delete it. + // Don't start at zero just to make it a little clearer in the debugger that it was set + // explicitly. + const int deletionOrderKey = 1; + const int deletionOrderRevocation = 2; + const int deletionOrderMassRevocation = 3; + var deletableElementsArray = deletableElements.ToArray(); var allElements = deletableElements.Select(d => d.Element).ToArray(); @@ -443,7 +452,7 @@ public bool DeleteKeys(Func shouldDelete) { _logger.DeletingKey(keyId); deletedKeyIds.Add(keyId); - deletableElementsArray[i].ShouldDelete = true; + deletableElementsArray[i].DeletionOrder = deletionOrderKey; } } else if (obj is DateTimeOffset massRevocationDate) @@ -451,7 +460,7 @@ public bool DeleteKeys(Func shouldDelete) if (massRevocationDate < mostRecentMassRevocationDate) { // Delete superceded mass revocation elements - deletableElementsArray[i].ShouldDelete = true; + deletableElementsArray[i].DeletionOrder = deletionOrderMassRevocation; } } } @@ -463,7 +472,7 @@ public bool DeleteKeys(Func shouldDelete) // Delete individual revocations of keys that don't (still) exist if (deletedKeyIds.Contains(revocationId) || !allKeyIds.Contains(revocationId)) { - deletableElementsArray[i].ShouldDelete = true; + deletableElementsArray[i].DeletionOrder = deletionOrderRevocation; } } } diff --git a/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt index ac81ae6721dc..3e28c1172bcf 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt @@ -1,8 +1,8 @@ #nullable enable Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.DeletionOrder.get -> int? +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.DeletionOrder.set -> void Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.Element.get -> System.Xml.Linq.XElement! -Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.ShouldDelete.get -> bool -Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.ShouldDelete.set -> void virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.CanRemoveElements.get -> bool virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.CanRemoveElements.get -> bool diff --git a/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt index 8c3ae72870d1..1d9f38788331 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt @@ -4,9 +4,9 @@ Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.DeleteKeys(System. Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.CanDeleteKeys.get -> bool Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.DeleteKeys(System.Func! shouldDelete) -> bool Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.DeletionOrder.get -> int? +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.DeletionOrder.set -> void Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.Element.get -> System.Xml.Linq.XElement! -Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.ShouldDelete.get -> bool -Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.ShouldDelete.set -> void Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.CanRemoveElements.get -> bool Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.CanRemoveElements.get -> bool diff --git a/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index ac81ae6721dc..3e28c1172bcf 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,8 +1,8 @@ #nullable enable Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.DeletionOrder.get -> int? +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.DeletionOrder.set -> void Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.Element.get -> System.Xml.Linq.XElement! -Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.ShouldDelete.get -> bool -Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.ShouldDelete.set -> void virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.CanRemoveElements.get -> bool virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.CanRemoveElements.get -> bool diff --git a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs index 0d701df5da9b..8782833a9983 100644 --- a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs @@ -197,22 +197,23 @@ public virtual bool RemoveElements(Action var allSucceeded = true; - foreach (var deletableElement in deletableElements) + var elementsToDelete = deletableElements + .Where(e => e.DeletionOrder.HasValue) + .OrderBy(e => e.DeletionOrder.GetValueOrDefault()); + + foreach (var deletableElement in elementsToDelete) { - if (deletableElement.ShouldDelete) + var fileSystemInfo = deletableElement.FileSystemInfo; + _logger.DeletingFile(fileSystemInfo.FullName); + try + { + fileSystemInfo.Delete(); + } + catch (Exception ex) { - var fileSystemInfo = deletableElement.FileSystemInfo; - _logger.DeletingFile(fileSystemInfo.FullName); - try - { - fileSystemInfo.Delete(); - } - catch (Exception ex) - { - Debug.Assert(fileSystemInfo.Exists, "Having previously been deleted should not have caused an exception"); - _logger.FailedToDeleteFile(fileSystemInfo.FullName, ex); - allSucceeded = false; - } + Debug.Assert(fileSystemInfo.Exists, "Having previously been deleted should not have caused an exception"); + _logger.FailedToDeleteFile(fileSystemInfo.FullName, ex); + allSucceeded = false; } } @@ -227,10 +228,13 @@ public DeletableElement(FileSystemInfo fileSystemInfo, XElement element) Element = element; } + /// public XElement Element { get; } + /// The FileSystemInfo from which was read. public FileSystemInfo FileSystemInfo { get; } - public bool ShouldDelete { get; set; } + /// + public int? DeletionOrder { get; set; } } } diff --git a/src/DataProtection/DataProtection/src/Repositories/IDeletableElement.cs b/src/DataProtection/DataProtection/src/Repositories/IDeletableElement.cs index b61b2b4b523a..567aba2a189f 100644 --- a/src/DataProtection/DataProtection/src/Repositories/IDeletableElement.cs +++ b/src/DataProtection/DataProtection/src/Repositories/IDeletableElement.cs @@ -12,6 +12,6 @@ public interface IDeletableElement { /// The XML element. public XElement Element { get; } - /// Set to true if the element should be deleted. - public bool ShouldDelete { get; set; } + /// Elements are deleted in increasing DeletionOrder. null means "don't delete". + public int? DeletionOrder { get; set; } } diff --git a/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs index d746cbee8f16..bd28fff84486 100644 --- a/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs @@ -45,7 +45,8 @@ public interface IXmlRepository /// /// /// A snapshot of the elements in this repository. - /// For each, set to true if it should be deleted. + /// For each, set to a non-null value if it should be deleted. + /// Elements are deleted in increasing order. /// /// /// True if all deletions succeeded. diff --git a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs index ee2c3f960216..bec5c7f8ea15 100644 --- a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Linq; using System.Runtime.Versioning; using System.Security.Principal; @@ -179,21 +180,22 @@ public virtual bool RemoveElements(Action var allSucceeded = true; - foreach (var deletableElement in deletableElements) + var elementsToDelete = deletableElements + .Where(e => e.DeletionOrder.HasValue) + .OrderBy(e => e.DeletionOrder.GetValueOrDefault()); + + foreach (var deletableElement in elementsToDelete) { - if (deletableElement.ShouldDelete) + var valueName = deletableElement.ValueName; + _logger.RemovingDataFromRegistryKeyValue(RegistryKey, valueName); + try { - var valueName = deletableElement.ValueName; - _logger.RemovingDataFromRegistryKeyValue(RegistryKey, valueName); - try - { - RegistryKey.DeleteValue(valueName); - } - catch (Exception ex) - { - _logger.FailedToRemoveDataFromRegistryKeyValue(RegistryKey, valueName, ex); - allSucceeded = false; - } + RegistryKey.DeleteValue(valueName); + } + catch (Exception ex) + { + _logger.FailedToRemoveDataFromRegistryKeyValue(RegistryKey, valueName, ex); + allSucceeded = false; } } @@ -208,10 +210,13 @@ public DeletableElement(string valueName, XElement element) Element = element; } + /// public XElement Element { get; } + /// The name of the registry value from which was read. public string ValueName { get; } - public bool ShouldDelete { get; set; } + /// + public int? DeletionOrder { get; set; } } } diff --git a/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs b/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs index 18935a9630d1..5d409a05c40b 100644 --- a/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs +++ b/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs @@ -103,21 +103,22 @@ public virtual bool RemoveElements(Action var allSucceeded = true; - foreach (var deletableElement in deletableElements) + var elementsToDelete = deletableElements + .Where(e => e.DeletionOrder.HasValue) + .OrderBy(e => e.DeletionOrder.GetValueOrDefault()); + + foreach (var deletableElement in elementsToDelete) { - if (deletableElement.ShouldDelete) + var key = deletableElement.Key; + _logger.DeletingKeyFromDbContext(key.FriendlyName, typeof(TContext).Name); + try { - var key = deletableElement.Key; - _logger.DeletingKeyFromDbContext(key.FriendlyName, typeof(TContext).Name); - try - { - context.DataProtectionKeys.Remove(key); - } - catch (Exception ex) - { - _logger.FailedToDeleteKeyFromDbContext(key.FriendlyName, typeof(TContext).Name, ex); - allSucceeded = false; - } + context.DataProtectionKeys.Remove(key); + } + catch (Exception ex) + { + _logger.FailedToDeleteKeyFromDbContext(key.FriendlyName, typeof(TContext).Name, ex); + allSucceeded = false; } } @@ -143,10 +144,13 @@ public DeletableElement(DataProtectionKey key, XElement element) Element = element; } + /// public XElement Element { get; } + /// The from which was read. public DataProtectionKey Key { get; } - public bool ShouldDelete { get; set; } + /// + public int? DeletionOrder { get; set; } } } From 642d16ff22142e989fb8a044c93d99d37e830947 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 11 Jul 2024 13:44:30 -0700 Subject: [PATCH 18/40] Improve comments --- .../DataProtection/src/KeyManagement/XmlKeyManager.cs | 7 +++---- .../DataProtection/src/Repositories/IXmlRepository.cs | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs index 5f893ab09e93..0c193902e65a 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs @@ -424,8 +424,8 @@ public bool DeleteKeys(Func shouldDelete) // It is important to delete key elements before the corresponding revocation elements, // in case the deletion fails part way - we don't want to accidentally unrevoke a key // and then not delete it. - // Don't start at zero just to make it a little clearer in the debugger that it was set - // explicitly. + // Start at a non-zero value just to make it a little clearer in the debugger that it + // was set explicitly. const int deletionOrderKey = 1; const int deletionOrderRevocation = 2; const int deletionOrderMassRevocation = 3; @@ -438,8 +438,6 @@ public bool DeleteKeys(Func shouldDelete) var allKeyIds = new HashSet(); var deletedKeyIds = new HashSet(); - var now = DateTimeOffset.Now; - for (var i = 0; i < deletableElementsArray.Length; i++) { var obj = processed[i]; @@ -465,6 +463,7 @@ public bool DeleteKeys(Func shouldDelete) } } + // Separate loop since deletedKeyIds and allKeyIds need to have been populated. for (var i = 0; i < deletableElementsArray.Length; i++) { if (processed[i] is Guid revocationId) diff --git a/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs index bd28fff84486..31f5a2b27d08 100644 --- a/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs @@ -41,7 +41,7 @@ public interface IXmlRepository bool CanRemoveElements => false; /// - /// Removes elements satisfying the given predicate. + /// Removes selected elements from the repository. /// /// /// A snapshot of the elements in this repository. From 2d9456a8d0e551dc76f382f33e2675687f2d4bab Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 11 Jul 2024 14:22:46 -0700 Subject: [PATCH 19/40] Implement deletion in EphemeralXmlRepository --- .../Repositories/EphemeralXmlRepository.cs | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs index 9d0d0eb65075..23b4d9c64d8e 100644 --- a/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs @@ -54,4 +54,64 @@ public void StoreElement(XElement element, string friendlyName) _storedElements.Add(cloned); } } + +#if NETCOREAPP + /// + public bool CanRemoveElements => true; + + /// + public bool RemoveElements(Action> chooseElements) + { + ArgumentNullThrowHelper.ThrowIfNull(chooseElements); + + var deletableElements = new List(); + + foreach (var storedElement in _storedElements) + { + // Make a deep copy so caller doesn't inadvertently modify it. + deletableElements.Add(new DeletableElement(storedElement, new XElement(storedElement))); + } + + chooseElements(deletableElements); + + var elementsToDelete = deletableElements + .Where(e => e.DeletionOrder.HasValue) + .OrderBy(e => e.DeletionOrder.GetValueOrDefault()); + + lock (_storedElements) + { + foreach (var deletableElement in elementsToDelete) + { + var storedElement = deletableElement.StoredElement; + var index = _storedElements.FindIndex(e => ReferenceEquals(e, storedElement)); + if (index >= 0) // Might not find it if the collection has changed since we started. + { + // It would be more efficient to remove the larger indices first, but deletion order + // is important for correctness. + _storedElements.RemoveAt(index); + } + } + } + + return true; + } + + private sealed class DeletableElement : IDeletableElement + { + public DeletableElement(XElement storedElement, XElement element) + { + StoredElement = storedElement; + Element = element; + } + + /// + public XElement Element { get; } + + /// The from which was cloned. + public XElement StoredElement { get; } + + /// + public int? DeletionOrder { get; set; } + } +#endif } From e1e0d63db269c0ffb5363f8797b4fcdd5d506e23 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 11 Jul 2024 14:35:11 -0700 Subject: [PATCH 20/40] Add comment requested by API Review --- .../DataProtection/src/Repositories/IXmlRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs index 31f5a2b27d08..8060c24725aa 100644 --- a/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs @@ -46,7 +46,7 @@ public interface IXmlRepository /// /// A snapshot of the elements in this repository. /// For each, set to a non-null value if it should be deleted. - /// Elements are deleted in increasing order. + /// Elements are deleted in increasing order. If any deletion fails, the remaining deletions *MUST* be skipped. /// /// /// True if all deletions succeeded. From e02e85f5f18aaf6c1ed986e60ae03d5b4c1d4e17 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 11 Jul 2024 14:37:50 -0700 Subject: [PATCH 21/40] Stub out RedisXmlRepository implementation for API Review --- .../StackExchangeRedis/src/PublicAPI.Unshipped.txt | 2 ++ .../StackExchangeRedis/src/RedisXmlRepository.cs | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/src/DataProtection/StackExchangeRedis/src/PublicAPI.Unshipped.txt b/src/DataProtection/StackExchangeRedis/src/PublicAPI.Unshipped.txt index 7dc5c58110bf..adf6b1606024 100644 --- a/src/DataProtection/StackExchangeRedis/src/PublicAPI.Unshipped.txt +++ b/src/DataProtection/StackExchangeRedis/src/PublicAPI.Unshipped.txt @@ -1 +1,3 @@ #nullable enable +virtual Microsoft.AspNetCore.DataProtection.StackExchangeRedis.RedisXmlRepository.CanRemoveElements.get -> bool +virtual Microsoft.AspNetCore.DataProtection.StackExchangeRedis.RedisXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool diff --git a/src/DataProtection/StackExchangeRedis/src/RedisXmlRepository.cs b/src/DataProtection/StackExchangeRedis/src/RedisXmlRepository.cs index 9ef8bcc5d9a3..a156453d7e10 100644 --- a/src/DataProtection/StackExchangeRedis/src/RedisXmlRepository.cs +++ b/src/DataProtection/StackExchangeRedis/src/RedisXmlRepository.cs @@ -55,4 +55,13 @@ public void StoreElement(XElement element, string friendlyName) var database = _databaseFactory(); database.ListRightPush(_key, element.ToString(SaveOptions.DisableFormatting)); } + + /// + public virtual bool CanRemoveElements => true; + + /// + public virtual bool RemoveElements(Action> chooseElements) + { + throw new NotImplementedException(); // TODO (acasey): ask Marc + } } From 3aeafcac6ecf43938012993ccb4da056bccee1d6 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 11 Jul 2024 17:33:30 -0700 Subject: [PATCH 22/40] Split out new interfaces so we don't need ifdefs --- .../src/KeyManagement/IKeyManager.cs | 35 --- .../KeyManagement/IKeyManagerWithDeletion.cs | 51 ++++ .../src/KeyManagement/XmlKeyManager.cs | 8 +- ...Microsoft.AspNetCore.DataProtection.csproj | 5 - .../net462 => }/PublicAPI.Shipped.txt | 0 .../net9.0 => }/PublicAPI.Unshipped.txt | 11 +- .../PublicAPI/net462/PublicAPI.Unshipped.txt | 9 - .../PublicAPI/net9.0/PublicAPI.Shipped.txt | 276 ------------------ .../netstandard2.0/PublicAPI.Shipped.txt | 276 ------------------ .../netstandard2.0/PublicAPI.Unshipped.txt | 9 - .../Repositories/EphemeralXmlRepository.cs | 9 +- .../Repositories/FileSystemXmlRepository.cs | 5 +- .../src/Repositories/IXmlRepository.cs | 24 -- .../IXmlRepositoryWithDeletion.cs | 27 ++ .../src/Repositories/RegistryXmlRepository.cs | 6 +- .../src/EntityFrameworkCoreXmlRepository.cs | 5 +- .../src/PublicAPI.Unshipped.txt | 1 - .../src/PublicAPI.Unshipped.txt | 1 - .../src/RedisXmlRepository.cs | 5 +- 19 files changed, 92 insertions(+), 671 deletions(-) create mode 100644 src/DataProtection/DataProtection/src/KeyManagement/IKeyManagerWithDeletion.cs rename src/DataProtection/DataProtection/src/{PublicAPI/net462 => }/PublicAPI.Shipped.txt (100%) rename src/DataProtection/DataProtection/src/{PublicAPI/net9.0 => }/PublicAPI.Unshipped.txt (58%) delete mode 100644 src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt delete mode 100644 src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Shipped.txt delete mode 100644 src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt delete mode 100644 src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt create mode 100644 src/DataProtection/DataProtection/src/Repositories/IXmlRepositoryWithDeletion.cs diff --git a/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs index 2b365ff31d31..df7a1b09e1b6 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs @@ -74,39 +74,4 @@ public interface IKeyManager /// all existing IKey instances should be discarded, and GetAllKeys should be called again. /// void RevokeAllKeys(DateTimeOffset revocationDate, string? reason = null); - -#if NETCOREAPP - /// - /// Indicates whether this key manager supports key deletion. - /// - /// - /// Deletion is stronger than revocation. A revoked key is retained and can even be (forcefully) applied. - /// A deleted key is indistinguishable from a key that never existed. - /// - bool CanDeleteKeys => false; - - /// - /// Deletes keys matching a predicate. - /// - /// Use with caution as deleting active keys will normally cause data loss. - /// - /// - /// A predicate applied to each key. - /// Returning true will cause the key to be deleted. - /// - /// - /// True if all attempted deletions succeeded. - /// - /// - /// Generally, keys should only be deleted to save space. If space is not a concern, keys - /// should be revoked or allowed to expire instead. - /// - /// This method will not mutate existing IKey instances. After calling this method, - /// all existing IKey instances should be discarded, and GetAllKeys should be called again. - /// - /// - /// If is false. - /// - bool DeleteKeys(Func shouldDelete) => throw new NotSupportedException(); -#endif } diff --git a/src/DataProtection/DataProtection/src/KeyManagement/IKeyManagerWithDeletion.cs b/src/DataProtection/DataProtection/src/KeyManagement/IKeyManagerWithDeletion.cs new file mode 100644 index 000000000000..3f3177d6a877 --- /dev/null +++ b/src/DataProtection/DataProtection/src/KeyManagement/IKeyManagerWithDeletion.cs @@ -0,0 +1,51 @@ +// 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.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Threading; + +namespace Microsoft.AspNetCore.DataProtection.KeyManagement; + +/// +/// The basic interface for performing key management operations. +/// +/// +/// Instantiations of this interface are expected to be thread-safe. +/// +public interface IKeyManagerWithDeletion : IKeyManager +{ + /// + /// Indicates whether this key manager supports key deletion. + /// + /// + /// Deletion is stronger than revocation. A revoked key is retained and can even be (forcefully) applied. + /// A deleted key is indistinguishable from a key that never existed. + /// + bool CanDeleteKeys { get; } + + /// + /// Deletes keys matching a predicate. + /// + /// Use with caution as deleting active keys will normally cause data loss. + /// + /// + /// A predicate applied to each key. + /// Returning true will cause the key to be deleted. + /// + /// + /// True if all attempted deletions succeeded. + /// + /// + /// Generally, keys should only be deleted to save space. If space is not a concern, keys + /// should be revoked or allowed to expire instead. + /// + /// This method will not mutate existing IKey instances. After calling this method, + /// all existing IKey instances should be discarded, and GetAllKeys should be called again. + /// + /// + /// If is false. + /// + bool DeleteKeys(Func shouldDelete); +} diff --git a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs index 0c193902e65a..f6ee9ff9f123 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs @@ -407,19 +407,18 @@ public void RevokeKey(Guid keyId, string? reason = null) reason: reason); } -#if NETCOREAPP /// - public bool CanDeleteKeys => KeyRepository.CanRemoveElements; + public bool CanDeleteKeys => KeyRepository is IXmlRepositoryWithDeletion; /// public bool DeleteKeys(Func shouldDelete) { - if (!CanDeleteKeys) + if (KeyRepository is not IXmlRepositoryWithDeletion xmlRepositoryWithDeletion) { throw Error.XmlKeyManager_DoesNotSupportKeyDeletion(); } - return KeyRepository.RemoveElements((deletableElements) => + return xmlRepositoryWithDeletion.RemoveElements((deletableElements) => { // It is important to delete key elements before the corresponding revocation elements, // in case the deletion fails part way - we don't want to accidentally unrevoke a key @@ -477,7 +476,6 @@ public bool DeleteKeys(Func shouldDelete) } }); } -#endif private void TriggerAndResetCacheExpirationToken([CallerMemberName] string? opName = null, bool suppressLogging = false) { diff --git a/src/DataProtection/DataProtection/src/Microsoft.AspNetCore.DataProtection.csproj b/src/DataProtection/DataProtection/src/Microsoft.AspNetCore.DataProtection.csproj index 3b6509e1d079..ddf556d6668c 100644 --- a/src/DataProtection/DataProtection/src/Microsoft.AspNetCore.DataProtection.csproj +++ b/src/DataProtection/DataProtection/src/Microsoft.AspNetCore.DataProtection.csproj @@ -53,9 +53,4 @@ - - - - - diff --git a/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Shipped.txt b/src/DataProtection/DataProtection/src/PublicAPI.Shipped.txt similarity index 100% rename from src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Shipped.txt rename to src/DataProtection/DataProtection/src/PublicAPI.Shipped.txt diff --git a/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt similarity index 58% rename from src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt rename to src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt index 1d9f38788331..c260fd6e9be8 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt @@ -1,15 +1,14 @@ #nullable enable -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.CanDeleteKeys.get -> bool -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.DeleteKeys(System.Func! shouldDelete) -> bool +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManagerWithDeletion +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManagerWithDeletion.CanDeleteKeys.get -> bool +Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManagerWithDeletion.DeleteKeys(System.Func! shouldDelete) -> bool Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.CanDeleteKeys.get -> bool Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.DeleteKeys(System.Func! shouldDelete) -> bool Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.DeletionOrder.get -> int? Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.DeletionOrder.set -> void Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.Element.get -> System.Xml.Linq.XElement! -Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.CanRemoveElements.get -> bool -Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.CanRemoveElements.get -> bool +Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepositoryWithDeletion +Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepositoryWithDeletion.RemoveElements(System.Action!>! chooseElements) -> bool virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.CanRemoveElements.get -> bool virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool diff --git a/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt deleted file mode 100644 index 3e28c1172bcf..000000000000 --- a/src/DataProtection/DataProtection/src/PublicAPI/net462/PublicAPI.Unshipped.txt +++ /dev/null @@ -1,9 +0,0 @@ -#nullable enable -Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement -Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.DeletionOrder.get -> int? -Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.DeletionOrder.set -> void -Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.Element.get -> System.Xml.Linq.XElement! -virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool diff --git a/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Shipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Shipped.txt deleted file mode 100644 index ce4946328fd2..000000000000 --- a/src/DataProtection/DataProtection/src/PublicAPI/net9.0/PublicAPI.Shipped.txt +++ /dev/null @@ -1,276 +0,0 @@ -#nullable enable -abstract Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration.CreateNewDescriptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.AuthenticatedEncryptorFactory -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.AuthenticatedEncryptorFactory.AuthenticatedEncryptorFactory(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.AuthenticatedEncryptorFactory.CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! key) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngCbcAuthenticatedEncryptorFactory -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngCbcAuthenticatedEncryptorFactory.CngCbcAuthenticatedEncryptorFactory(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngCbcAuthenticatedEncryptorFactory.CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! key) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngGcmAuthenticatedEncryptorFactory -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngGcmAuthenticatedEncryptorFactory.CngGcmAuthenticatedEncryptorFactory(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngGcmAuthenticatedEncryptorFactory.CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! key) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration.AlgorithmConfiguration() -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.AuthenticatedEncryptorConfiguration() -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.EncryptionAlgorithm.get -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.EncryptionAlgorithm.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.ValidationAlgorithm.get -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.ValidationAlgorithm.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptor -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptor.AuthenticatedEncryptorDescriptor(Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration! configuration, Microsoft.AspNetCore.DataProtection.ISecret! masterKey) -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptor.ExportToXml() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer.AuthenticatedEncryptorDescriptorDeserializer() -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer.ImportFromXml(System.Xml.Linq.XElement! element) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.CngCbcAuthenticatedEncryptorConfiguration() -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithm.get -> string! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithm.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.get -> int -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithmProvider.get -> string? -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithmProvider.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.HashAlgorithm.get -> string! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.HashAlgorithm.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.HashAlgorithmProvider.get -> string? -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.HashAlgorithmProvider.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptor -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptor.CngCbcAuthenticatedEncryptorDescriptor(Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration! configuration, Microsoft.AspNetCore.DataProtection.ISecret! masterKey) -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptor.ExportToXml() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptorDeserializer -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptorDeserializer.CngCbcAuthenticatedEncryptorDescriptorDeserializer() -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptorDeserializer.ImportFromXml(System.Xml.Linq.XElement! element) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.CngGcmAuthenticatedEncryptorConfiguration() -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithm.get -> string! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithm.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.get -> int -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithmProvider.get -> string? -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithmProvider.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptor -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptor.CngGcmAuthenticatedEncryptorDescriptor(Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration! configuration, Microsoft.AspNetCore.DataProtection.ISecret! masterKey) -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptor.ExportToXml() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptorDeserializer -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptorDeserializer.CngGcmAuthenticatedEncryptorDescriptorDeserializer() -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptorDeserializer.ImportFromXml(System.Xml.Linq.XElement! element) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor.ExportToXml() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer.ImportFromXml(System.Xml.Linq.XElement! element) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.get -> int -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.EncryptionAlgorithmType.get -> System.Type! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.EncryptionAlgorithmType.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.ManagedAuthenticatedEncryptorConfiguration() -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.ValidationAlgorithmType.get -> System.Type! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.ValidationAlgorithmType.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptor -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptor.ExportToXml() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptor.ManagedAuthenticatedEncryptorDescriptor(Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration! configuration, Microsoft.AspNetCore.DataProtection.ISecret! masterKey) -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptorDeserializer -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptorDeserializer.ImportFromXml(System.Xml.Linq.XElement! element) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptorDeserializer.ManagedAuthenticatedEncryptorDescriptorDeserializer() -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlExtensions -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo.DeserializerType.get -> System.Type! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo.SerializedDescriptorElement.get -> System.Xml.Linq.XElement! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo.XmlSerializedDescriptorInfo(System.Xml.Linq.XElement! serializedDescriptorElement, System.Type! deserializerType) -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_128_CBC = 0 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_128_GCM = 3 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_192_CBC = 1 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_192_GCM = 4 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_256_CBC = 2 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_256_GCM = 5 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor.Decrypt(System.ArraySegment ciphertext, System.ArraySegment additionalAuthenticatedData) -> byte[]! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor.Encrypt(System.ArraySegment plaintext, System.ArraySegment additionalAuthenticatedData) -> byte[]! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory.CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! key) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory.CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! key) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory.ManagedAuthenticatedEncryptorFactory(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm.HMACSHA256 = 0 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm.HMACSHA512 = 1 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm -Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions -Microsoft.AspNetCore.DataProtection.DataProtectionOptions -Microsoft.AspNetCore.DataProtection.DataProtectionOptions.ApplicationDiscriminator.get -> string? -Microsoft.AspNetCore.DataProtection.DataProtectionOptions.ApplicationDiscriminator.set -> void -Microsoft.AspNetCore.DataProtection.DataProtectionOptions.DataProtectionOptions() -> void -Microsoft.AspNetCore.DataProtection.DataProtectionUtilityExtensions -Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider -Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider.CreateProtector(string! purpose) -> Microsoft.AspNetCore.DataProtection.IDataProtector! -Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider.EphemeralDataProtectionProvider() -> void -Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider.EphemeralDataProtectionProvider(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder -Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder.Services.get -> Microsoft.Extensions.DependencyInjection.IServiceCollection! -Microsoft.AspNetCore.DataProtection.Internal.IActivator -Microsoft.AspNetCore.DataProtection.Internal.IActivator.CreateInstance(System.Type! expectedBaseType, string! implementationTypeName) -> object! -Microsoft.AspNetCore.DataProtection.IPersistedDataProtector -Microsoft.AspNetCore.DataProtection.IPersistedDataProtector.DangerousUnprotect(byte[]! protectedData, bool ignoreRevocationErrors, out bool requiresMigration, out bool wasRevoked) -> byte[]! -Microsoft.AspNetCore.DataProtection.ISecret -Microsoft.AspNetCore.DataProtection.ISecret.Length.get -> int -Microsoft.AspNetCore.DataProtection.ISecret.WriteSecretIntoBuffer(System.ArraySegment buffer) -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.IKey -Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.ActivationDate.get -> System.DateTimeOffset -Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.CreateEncryptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? -Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.CreationDate.get -> System.DateTimeOffset -Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.Descriptor.get -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.ExpirationDate.get -> System.DateTimeOffset -Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.IsRevoked.get -> bool -Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.KeyId.get -> System.Guid -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyEscrowSink -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyEscrowSink.Store(System.Guid keyId, System.Xml.Linq.XElement! element) -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.CreateNewKey(System.DateTimeOffset activationDate, System.DateTimeOffset expirationDate) -> Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.GetAllKeys() -> System.Collections.Generic.IReadOnlyCollection! -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.GetCacheExpirationToken() -> System.Threading.CancellationToken -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.RevokeAllKeys(System.DateTimeOffset revocationDate, string? reason = null) -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.RevokeKey(System.Guid keyId, string? reason = null) -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.CacheableKeyRing -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution.DefaultKey -> Microsoft.AspNetCore.DataProtection.KeyManagement.IKey? -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution.DefaultKeyResolution() -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution.FallbackKey -> Microsoft.AspNetCore.DataProtection.KeyManagement.IKey? -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution.ShouldGenerateNewKey -> bool -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.ICacheableKeyRingProvider -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.ICacheableKeyRingProvider.GetCacheableKeyRing(System.DateTimeOffset now) -> Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.CacheableKeyRing! -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IDefaultKeyResolver -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IDefaultKeyResolver.ResolveDefaultKeyPolicy(System.DateTimeOffset now, System.Collections.Generic.IEnumerable! allKeys) -> Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager.CreateNewKey(System.Guid keyId, System.DateTimeOffset creationDate, System.DateTimeOffset activationDate, System.DateTimeOffset expirationDate) -> Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager.DeserializeDescriptorFromKeyElement(System.Xml.Linq.XElement! keyElement) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager.RevokeSingleKey(System.Guid keyId, System.DateTimeOffset revocationDate, string? reason) -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing.DefaultAuthenticatedEncryptor.get -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing.DefaultKeyId.get -> System.Guid -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing.GetAuthenticatedEncryptorByKeyId(System.Guid keyId, out bool isRevoked) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRingProvider -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRingProvider.GetCurrentKeyRing() -> Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing! -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.AuthenticatedEncryptorConfiguration.get -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration? -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.AuthenticatedEncryptorConfiguration.set -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.AuthenticatedEncryptorFactories.get -> System.Collections.Generic.IList! -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.AutoGenerateKeys.get -> bool -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.AutoGenerateKeys.set -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.KeyEscrowSinks.get -> System.Collections.Generic.IList! -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.KeyManagementOptions() -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.NewKeyLifetime.get -> System.TimeSpan -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.NewKeyLifetime.set -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.XmlEncryptor.get -> Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor? -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.XmlEncryptor.set -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.XmlRepository.get -> Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository? -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.XmlRepository.set -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager -Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.CreateNewKey(System.DateTimeOffset activationDate, System.DateTimeOffset expirationDate) -> Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! -Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.GetAllKeys() -> System.Collections.Generic.IReadOnlyCollection! -Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.GetCacheExpirationToken() -> System.Threading.CancellationToken -Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.RevokeAllKeys(System.DateTimeOffset revocationDate, string? reason = null) -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.RevokeKey(System.Guid keyId, string? reason = null) -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.XmlKeyManager(Microsoft.Extensions.Options.IOptions! keyManagementOptions, Microsoft.AspNetCore.DataProtection.Internal.IActivator! activator) -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.XmlKeyManager(Microsoft.Extensions.Options.IOptions! keyManagementOptions, Microsoft.AspNetCore.DataProtection.Internal.IActivator! activator, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository -Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.Directory.get -> System.IO.DirectoryInfo! -Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.FileSystemXmlRepository(System.IO.DirectoryInfo! directory, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository -Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.GetAllElements() -> System.Collections.Generic.IReadOnlyCollection! -Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.StoreElement(System.Xml.Linq.XElement! element, string! friendlyName) -> void -Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository -Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RegistryKey.get -> Microsoft.Win32.RegistryKey! -Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RegistryXmlRepository(Microsoft.Win32.RegistryKey! registryKey, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.Secret -Microsoft.AspNetCore.DataProtection.Secret.Dispose() -> void -Microsoft.AspNetCore.DataProtection.Secret.Length.get -> int -Microsoft.AspNetCore.DataProtection.Secret.Secret(byte* secret, int secretLength) -> void -Microsoft.AspNetCore.DataProtection.Secret.Secret(byte[]! value) -> void -Microsoft.AspNetCore.DataProtection.Secret.Secret(Microsoft.AspNetCore.DataProtection.ISecret! secret) -> void -Microsoft.AspNetCore.DataProtection.Secret.Secret(System.ArraySegment value) -> void -Microsoft.AspNetCore.DataProtection.Secret.WriteSecretIntoBuffer(byte* buffer, int bufferLength) -> void -Microsoft.AspNetCore.DataProtection.Secret.WriteSecretIntoBuffer(System.ArraySegment buffer) -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateResolver -Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateResolver.CertificateResolver() -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateXmlEncryptor -Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateXmlEncryptor.CertificateXmlEncryptor(string! thumbprint, Microsoft.AspNetCore.DataProtection.XmlEncryption.ICertificateResolver! certificateResolver, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateXmlEncryptor.CertificateXmlEncryptor(System.Security.Cryptography.X509Certificates.X509Certificate2! certificate, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateXmlEncryptor.Encrypt(System.Xml.Linq.XElement! plaintextElement) -> Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo! -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags.MachineKey = 32 -> Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags.NamedDescriptor = 1 -> Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags.None = 0 -> Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlDecryptor -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlDecryptor.Decrypt(System.Xml.Linq.XElement! encryptedElement) -> System.Xml.Linq.XElement! -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlDecryptor.DpapiNGXmlDecryptor() -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlDecryptor.DpapiNGXmlDecryptor(System.IServiceProvider? services) -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlEncryptor -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlEncryptor.DpapiNGXmlEncryptor(string! protectionDescriptorRule, Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags flags, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlEncryptor.Encrypt(System.Xml.Linq.XElement! plaintextElement) -> Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo! -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlDecryptor -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlDecryptor.Decrypt(System.Xml.Linq.XElement! encryptedElement) -> System.Xml.Linq.XElement! -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlDecryptor.DpapiXmlDecryptor() -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlDecryptor.DpapiXmlDecryptor(System.IServiceProvider? services) -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlEncryptor -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlEncryptor.DpapiXmlEncryptor(bool protectToLocalMachine, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlEncryptor.Encrypt(System.Xml.Linq.XElement! plaintextElement) -> Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo! -Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor -Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor.Decrypt(System.Xml.Linq.XElement! encryptedElement) -> System.Xml.Linq.XElement! -Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor.EncryptedXmlDecryptor() -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor.EncryptedXmlDecryptor(System.IServiceProvider? services) -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo -Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo.DecryptorType.get -> System.Type! -Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo.EncryptedElement.get -> System.Xml.Linq.XElement! -Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo.EncryptedXmlInfo(System.Xml.Linq.XElement! encryptedElement, System.Type! decryptorType) -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.ICertificateResolver -Microsoft.AspNetCore.DataProtection.XmlEncryption.ICertificateResolver.ResolveCertificate(string! thumbprint) -> System.Security.Cryptography.X509Certificates.X509Certificate2? -Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor -Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor.Decrypt(System.Xml.Linq.XElement! encryptedElement) -> System.Xml.Linq.XElement! -Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor -Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor.Encrypt(System.Xml.Linq.XElement! plaintextElement) -> Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo! -Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlDecryptor -Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlDecryptor.Decrypt(System.Xml.Linq.XElement! encryptedElement) -> System.Xml.Linq.XElement! -Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlDecryptor.NullXmlDecryptor() -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlEncryptor -Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlEncryptor.Encrypt(System.Xml.Linq.XElement! plaintextElement) -> Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo! -Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlEncryptor.NullXmlEncryptor() -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlEncryptor.NullXmlEncryptor(System.IServiceProvider? services) -> void -Microsoft.Extensions.DependencyInjection.DataProtectionServiceCollectionExtensions -override Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.CreateNewDescriptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -override Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.CreateNewDescriptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -override Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.CreateNewDescriptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -override Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.CreateNewDescriptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -static Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlExtensions.MarkAsRequiresEncryption(this System.Xml.Linq.XElement! element) -> void -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.AddKeyEscrowSink(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyEscrowSink! sink) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.AddKeyEscrowSink(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.Func! factory) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.AddKeyEscrowSink(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.AddKeyManagementOptions(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.Action! setupAction) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.DisableAutomaticKeyGeneration(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.PersistKeysToFileSystem(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.IO.DirectoryInfo! directory) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.PersistKeysToRegistry(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.Win32.RegistryKey! registryKey) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithCertificate(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, string! thumbprint) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithCertificate(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.Security.Cryptography.X509Certificates.X509Certificate2! certificate) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithDpapi(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithDpapi(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, bool protectToLocalMachine) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithDpapiNG(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithDpapiNG(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, string! protectionDescriptorRule, Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags flags) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.SetApplicationName(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, string! applicationName) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.SetDefaultKeyLifetime(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.TimeSpan lifetime) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UnprotectKeysWithAnyCertificate(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, params System.Security.Cryptography.X509Certificates.X509Certificate2![]! certificates) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UseCryptographicAlgorithms(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration! configuration) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UseCustomCryptographicAlgorithms(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration! configuration) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UseCustomCryptographicAlgorithms(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration! configuration) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UseCustomCryptographicAlgorithms(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration! configuration) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UseEphemeralDataProtectionProvider(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionUtilityExtensions.GetApplicationUniqueIdentifier(this System.IServiceProvider! services) -> string? -static Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.DefaultKeyStorageDirectory.get -> System.IO.DirectoryInfo? -static Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.DefaultRegistryKey.get -> Microsoft.Win32.RegistryKey? -static Microsoft.AspNetCore.DataProtection.Secret.Random(int numBytes) -> Microsoft.AspNetCore.DataProtection.Secret! -static Microsoft.Extensions.DependencyInjection.DataProtectionServiceCollectionExtensions.AddDataProtection(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.Extensions.DependencyInjection.DataProtectionServiceCollectionExtensions.AddDataProtection(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action! setupAction) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.GetAllElements() -> System.Collections.Generic.IReadOnlyCollection! -virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.StoreElement(System.Xml.Linq.XElement! element, string! friendlyName) -> void -virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.GetAllElements() -> System.Collections.Generic.IReadOnlyCollection! -virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.StoreElement(System.Xml.Linq.XElement! element, string! friendlyName) -> void -virtual Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateResolver.ResolveCertificate(string! thumbprint) -> System.Security.Cryptography.X509Certificates.X509Certificate2? diff --git a/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt deleted file mode 100644 index ce4946328fd2..000000000000 --- a/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt +++ /dev/null @@ -1,276 +0,0 @@ -#nullable enable -abstract Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration.CreateNewDescriptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.AuthenticatedEncryptorFactory -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.AuthenticatedEncryptorFactory.AuthenticatedEncryptorFactory(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.AuthenticatedEncryptorFactory.CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! key) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngCbcAuthenticatedEncryptorFactory -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngCbcAuthenticatedEncryptorFactory.CngCbcAuthenticatedEncryptorFactory(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngCbcAuthenticatedEncryptorFactory.CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! key) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngGcmAuthenticatedEncryptorFactory -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngGcmAuthenticatedEncryptorFactory.CngGcmAuthenticatedEncryptorFactory(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngGcmAuthenticatedEncryptorFactory.CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! key) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration.AlgorithmConfiguration() -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.AuthenticatedEncryptorConfiguration() -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.EncryptionAlgorithm.get -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.EncryptionAlgorithm.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.ValidationAlgorithm.get -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.ValidationAlgorithm.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptor -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptor.AuthenticatedEncryptorDescriptor(Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration! configuration, Microsoft.AspNetCore.DataProtection.ISecret! masterKey) -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptor.ExportToXml() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer.AuthenticatedEncryptorDescriptorDeserializer() -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer.ImportFromXml(System.Xml.Linq.XElement! element) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.CngCbcAuthenticatedEncryptorConfiguration() -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithm.get -> string! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithm.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.get -> int -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithmProvider.get -> string? -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithmProvider.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.HashAlgorithm.get -> string! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.HashAlgorithm.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.HashAlgorithmProvider.get -> string? -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.HashAlgorithmProvider.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptor -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptor.CngCbcAuthenticatedEncryptorDescriptor(Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration! configuration, Microsoft.AspNetCore.DataProtection.ISecret! masterKey) -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptor.ExportToXml() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptorDeserializer -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptorDeserializer.CngCbcAuthenticatedEncryptorDescriptorDeserializer() -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptorDeserializer.ImportFromXml(System.Xml.Linq.XElement! element) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.CngGcmAuthenticatedEncryptorConfiguration() -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithm.get -> string! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithm.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.get -> int -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithmProvider.get -> string? -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithmProvider.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptor -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptor.CngGcmAuthenticatedEncryptorDescriptor(Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration! configuration, Microsoft.AspNetCore.DataProtection.ISecret! masterKey) -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptor.ExportToXml() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptorDeserializer -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptorDeserializer.CngGcmAuthenticatedEncryptorDescriptorDeserializer() -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptorDeserializer.ImportFromXml(System.Xml.Linq.XElement! element) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor.ExportToXml() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer.ImportFromXml(System.Xml.Linq.XElement! element) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.get -> int -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.EncryptionAlgorithmType.get -> System.Type! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.EncryptionAlgorithmType.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.ManagedAuthenticatedEncryptorConfiguration() -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.ValidationAlgorithmType.get -> System.Type! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.ValidationAlgorithmType.set -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptor -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptor.ExportToXml() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptor.ManagedAuthenticatedEncryptorDescriptor(Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration! configuration, Microsoft.AspNetCore.DataProtection.ISecret! masterKey) -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptorDeserializer -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptorDeserializer.ImportFromXml(System.Xml.Linq.XElement! element) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptorDeserializer.ManagedAuthenticatedEncryptorDescriptorDeserializer() -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlExtensions -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo.DeserializerType.get -> System.Type! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo.SerializedDescriptorElement.get -> System.Xml.Linq.XElement! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo.XmlSerializedDescriptorInfo(System.Xml.Linq.XElement! serializedDescriptorElement, System.Type! deserializerType) -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_128_CBC = 0 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_128_GCM = 3 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_192_CBC = 1 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_192_GCM = 4 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_256_CBC = 2 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_256_GCM = 5 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor.Decrypt(System.ArraySegment ciphertext, System.ArraySegment additionalAuthenticatedData) -> byte[]! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor.Encrypt(System.ArraySegment plaintext, System.ArraySegment additionalAuthenticatedData) -> byte[]! -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory.CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! key) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory.CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! key) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory.ManagedAuthenticatedEncryptorFactory(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm.HMACSHA256 = 0 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm -Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm.HMACSHA512 = 1 -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm -Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions -Microsoft.AspNetCore.DataProtection.DataProtectionOptions -Microsoft.AspNetCore.DataProtection.DataProtectionOptions.ApplicationDiscriminator.get -> string? -Microsoft.AspNetCore.DataProtection.DataProtectionOptions.ApplicationDiscriminator.set -> void -Microsoft.AspNetCore.DataProtection.DataProtectionOptions.DataProtectionOptions() -> void -Microsoft.AspNetCore.DataProtection.DataProtectionUtilityExtensions -Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider -Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider.CreateProtector(string! purpose) -> Microsoft.AspNetCore.DataProtection.IDataProtector! -Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider.EphemeralDataProtectionProvider() -> void -Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider.EphemeralDataProtectionProvider(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder -Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder.Services.get -> Microsoft.Extensions.DependencyInjection.IServiceCollection! -Microsoft.AspNetCore.DataProtection.Internal.IActivator -Microsoft.AspNetCore.DataProtection.Internal.IActivator.CreateInstance(System.Type! expectedBaseType, string! implementationTypeName) -> object! -Microsoft.AspNetCore.DataProtection.IPersistedDataProtector -Microsoft.AspNetCore.DataProtection.IPersistedDataProtector.DangerousUnprotect(byte[]! protectedData, bool ignoreRevocationErrors, out bool requiresMigration, out bool wasRevoked) -> byte[]! -Microsoft.AspNetCore.DataProtection.ISecret -Microsoft.AspNetCore.DataProtection.ISecret.Length.get -> int -Microsoft.AspNetCore.DataProtection.ISecret.WriteSecretIntoBuffer(System.ArraySegment buffer) -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.IKey -Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.ActivationDate.get -> System.DateTimeOffset -Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.CreateEncryptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? -Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.CreationDate.get -> System.DateTimeOffset -Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.Descriptor.get -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.ExpirationDate.get -> System.DateTimeOffset -Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.IsRevoked.get -> bool -Microsoft.AspNetCore.DataProtection.KeyManagement.IKey.KeyId.get -> System.Guid -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyEscrowSink -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyEscrowSink.Store(System.Guid keyId, System.Xml.Linq.XElement! element) -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.CreateNewKey(System.DateTimeOffset activationDate, System.DateTimeOffset expirationDate) -> Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.GetAllKeys() -> System.Collections.Generic.IReadOnlyCollection! -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.GetCacheExpirationToken() -> System.Threading.CancellationToken -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.RevokeAllKeys(System.DateTimeOffset revocationDate, string? reason = null) -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager.RevokeKey(System.Guid keyId, string? reason = null) -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.CacheableKeyRing -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution.DefaultKey -> Microsoft.AspNetCore.DataProtection.KeyManagement.IKey? -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution.DefaultKeyResolution() -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution.FallbackKey -> Microsoft.AspNetCore.DataProtection.KeyManagement.IKey? -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution.ShouldGenerateNewKey -> bool -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.ICacheableKeyRingProvider -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.ICacheableKeyRingProvider.GetCacheableKeyRing(System.DateTimeOffset now) -> Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.CacheableKeyRing! -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IDefaultKeyResolver -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IDefaultKeyResolver.ResolveDefaultKeyPolicy(System.DateTimeOffset now, System.Collections.Generic.IEnumerable! allKeys) -> Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager.CreateNewKey(System.Guid keyId, System.DateTimeOffset creationDate, System.DateTimeOffset activationDate, System.DateTimeOffset expirationDate) -> Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager.DeserializeDescriptorFromKeyElement(System.Xml.Linq.XElement! keyElement) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager.RevokeSingleKey(System.Guid keyId, System.DateTimeOffset revocationDate, string? reason) -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing.DefaultAuthenticatedEncryptor.get -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing.DefaultKeyId.get -> System.Guid -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing.GetAuthenticatedEncryptorByKeyId(System.Guid keyId, out bool isRevoked) -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor? -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRingProvider -Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRingProvider.GetCurrentKeyRing() -> Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing! -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.AuthenticatedEncryptorConfiguration.get -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration? -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.AuthenticatedEncryptorConfiguration.set -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.AuthenticatedEncryptorFactories.get -> System.Collections.Generic.IList! -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.AutoGenerateKeys.get -> bool -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.AutoGenerateKeys.set -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.KeyEscrowSinks.get -> System.Collections.Generic.IList! -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.KeyManagementOptions() -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.NewKeyLifetime.get -> System.TimeSpan -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.NewKeyLifetime.set -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.XmlEncryptor.get -> Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor? -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.XmlEncryptor.set -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.XmlRepository.get -> Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository? -Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions.XmlRepository.set -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager -Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.CreateNewKey(System.DateTimeOffset activationDate, System.DateTimeOffset expirationDate) -> Microsoft.AspNetCore.DataProtection.KeyManagement.IKey! -Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.GetAllKeys() -> System.Collections.Generic.IReadOnlyCollection! -Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.GetCacheExpirationToken() -> System.Threading.CancellationToken -Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.RevokeAllKeys(System.DateTimeOffset revocationDate, string? reason = null) -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.RevokeKey(System.Guid keyId, string? reason = null) -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.XmlKeyManager(Microsoft.Extensions.Options.IOptions! keyManagementOptions, Microsoft.AspNetCore.DataProtection.Internal.IActivator! activator) -> void -Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.XmlKeyManager(Microsoft.Extensions.Options.IOptions! keyManagementOptions, Microsoft.AspNetCore.DataProtection.Internal.IActivator! activator, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository -Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.Directory.get -> System.IO.DirectoryInfo! -Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.FileSystemXmlRepository(System.IO.DirectoryInfo! directory, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository -Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.GetAllElements() -> System.Collections.Generic.IReadOnlyCollection! -Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository.StoreElement(System.Xml.Linq.XElement! element, string! friendlyName) -> void -Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository -Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RegistryKey.get -> Microsoft.Win32.RegistryKey! -Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RegistryXmlRepository(Microsoft.Win32.RegistryKey! registryKey, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.Secret -Microsoft.AspNetCore.DataProtection.Secret.Dispose() -> void -Microsoft.AspNetCore.DataProtection.Secret.Length.get -> int -Microsoft.AspNetCore.DataProtection.Secret.Secret(byte* secret, int secretLength) -> void -Microsoft.AspNetCore.DataProtection.Secret.Secret(byte[]! value) -> void -Microsoft.AspNetCore.DataProtection.Secret.Secret(Microsoft.AspNetCore.DataProtection.ISecret! secret) -> void -Microsoft.AspNetCore.DataProtection.Secret.Secret(System.ArraySegment value) -> void -Microsoft.AspNetCore.DataProtection.Secret.WriteSecretIntoBuffer(byte* buffer, int bufferLength) -> void -Microsoft.AspNetCore.DataProtection.Secret.WriteSecretIntoBuffer(System.ArraySegment buffer) -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateResolver -Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateResolver.CertificateResolver() -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateXmlEncryptor -Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateXmlEncryptor.CertificateXmlEncryptor(string! thumbprint, Microsoft.AspNetCore.DataProtection.XmlEncryption.ICertificateResolver! certificateResolver, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateXmlEncryptor.CertificateXmlEncryptor(System.Security.Cryptography.X509Certificates.X509Certificate2! certificate, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateXmlEncryptor.Encrypt(System.Xml.Linq.XElement! plaintextElement) -> Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo! -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags.MachineKey = 32 -> Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags.NamedDescriptor = 1 -> Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags.None = 0 -> Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlDecryptor -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlDecryptor.Decrypt(System.Xml.Linq.XElement! encryptedElement) -> System.Xml.Linq.XElement! -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlDecryptor.DpapiNGXmlDecryptor() -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlDecryptor.DpapiNGXmlDecryptor(System.IServiceProvider? services) -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlEncryptor -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlEncryptor.DpapiNGXmlEncryptor(string! protectionDescriptorRule, Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags flags, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlEncryptor.Encrypt(System.Xml.Linq.XElement! plaintextElement) -> Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo! -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlDecryptor -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlDecryptor.Decrypt(System.Xml.Linq.XElement! encryptedElement) -> System.Xml.Linq.XElement! -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlDecryptor.DpapiXmlDecryptor() -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlDecryptor.DpapiXmlDecryptor(System.IServiceProvider? services) -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlEncryptor -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlEncryptor.DpapiXmlEncryptor(bool protectToLocalMachine, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlEncryptor.Encrypt(System.Xml.Linq.XElement! plaintextElement) -> Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo! -Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor -Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor.Decrypt(System.Xml.Linq.XElement! encryptedElement) -> System.Xml.Linq.XElement! -Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor.EncryptedXmlDecryptor() -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor.EncryptedXmlDecryptor(System.IServiceProvider? services) -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo -Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo.DecryptorType.get -> System.Type! -Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo.EncryptedElement.get -> System.Xml.Linq.XElement! -Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo.EncryptedXmlInfo(System.Xml.Linq.XElement! encryptedElement, System.Type! decryptorType) -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.ICertificateResolver -Microsoft.AspNetCore.DataProtection.XmlEncryption.ICertificateResolver.ResolveCertificate(string! thumbprint) -> System.Security.Cryptography.X509Certificates.X509Certificate2? -Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor -Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor.Decrypt(System.Xml.Linq.XElement! encryptedElement) -> System.Xml.Linq.XElement! -Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor -Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor.Encrypt(System.Xml.Linq.XElement! plaintextElement) -> Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo! -Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlDecryptor -Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlDecryptor.Decrypt(System.Xml.Linq.XElement! encryptedElement) -> System.Xml.Linq.XElement! -Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlDecryptor.NullXmlDecryptor() -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlEncryptor -Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlEncryptor.Encrypt(System.Xml.Linq.XElement! plaintextElement) -> Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo! -Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlEncryptor.NullXmlEncryptor() -> void -Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlEncryptor.NullXmlEncryptor(System.IServiceProvider? services) -> void -Microsoft.Extensions.DependencyInjection.DataProtectionServiceCollectionExtensions -override Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration.CreateNewDescriptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -override Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration.CreateNewDescriptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -override Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration.CreateNewDescriptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -override Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration.CreateNewDescriptor() -> Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor! -static Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlExtensions.MarkAsRequiresEncryption(this System.Xml.Linq.XElement! element) -> void -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.AddKeyEscrowSink(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyEscrowSink! sink) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.AddKeyEscrowSink(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.Func! factory) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.AddKeyEscrowSink(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.AddKeyManagementOptions(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.Action! setupAction) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.DisableAutomaticKeyGeneration(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.PersistKeysToFileSystem(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.IO.DirectoryInfo! directory) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.PersistKeysToRegistry(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.Win32.RegistryKey! registryKey) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithCertificate(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, string! thumbprint) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithCertificate(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.Security.Cryptography.X509Certificates.X509Certificate2! certificate) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithDpapi(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithDpapi(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, bool protectToLocalMachine) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithDpapiNG(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.ProtectKeysWithDpapiNG(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, string! protectionDescriptorRule, Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags flags) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.SetApplicationName(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, string! applicationName) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.SetDefaultKeyLifetime(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.TimeSpan lifetime) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UnprotectKeysWithAnyCertificate(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, params System.Security.Cryptography.X509Certificates.X509Certificate2![]! certificates) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UseCryptographicAlgorithms(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration! configuration) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UseCustomCryptographicAlgorithms(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration! configuration) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UseCustomCryptographicAlgorithms(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration! configuration) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UseCustomCryptographicAlgorithms(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration! configuration) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions.UseEphemeralDataProtectionProvider(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.AspNetCore.DataProtection.DataProtectionUtilityExtensions.GetApplicationUniqueIdentifier(this System.IServiceProvider! services) -> string? -static Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.DefaultKeyStorageDirectory.get -> System.IO.DirectoryInfo? -static Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.DefaultRegistryKey.get -> Microsoft.Win32.RegistryKey? -static Microsoft.AspNetCore.DataProtection.Secret.Random(int numBytes) -> Microsoft.AspNetCore.DataProtection.Secret! -static Microsoft.Extensions.DependencyInjection.DataProtectionServiceCollectionExtensions.AddDataProtection(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -static Microsoft.Extensions.DependencyInjection.DataProtectionServiceCollectionExtensions.AddDataProtection(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action! setupAction) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! -virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.GetAllElements() -> System.Collections.Generic.IReadOnlyCollection! -virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.StoreElement(System.Xml.Linq.XElement! element, string! friendlyName) -> void -virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.GetAllElements() -> System.Collections.Generic.IReadOnlyCollection! -virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.StoreElement(System.Xml.Linq.XElement! element, string! friendlyName) -> void -virtual Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateResolver.ResolveCertificate(string! thumbprint) -> System.Security.Cryptography.X509Certificates.X509Certificate2? diff --git a/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt deleted file mode 100644 index 3e28c1172bcf..000000000000 --- a/src/DataProtection/DataProtection/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ /dev/null @@ -1,9 +0,0 @@ -#nullable enable -Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement -Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.DeletionOrder.get -> int? -Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.DeletionOrder.set -> void -Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.Element.get -> System.Xml.Linq.XElement! -virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.CanRemoveElements.get -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool diff --git a/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs index 23b4d9c64d8e..4915b80bcae3 100644 --- a/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs @@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.DataProtection.Repositories; /// An ephemeral XML repository backed by process memory. This class must not be used for /// anything other than dev scenarios as the keys will not be persisted to storage. /// -internal sealed class EphemeralXmlRepository : IXmlRepository +internal sealed class EphemeralXmlRepository : IXmlRepositoryWithDeletion { private readonly List _storedElements = new List(); @@ -55,12 +55,8 @@ public void StoreElement(XElement element, string friendlyName) } } -#if NETCOREAPP /// - public bool CanRemoveElements => true; - - /// - public bool RemoveElements(Action> chooseElements) + bool IXmlRepositoryWithDeletion.RemoveElements(Action> chooseElements) { ArgumentNullThrowHelper.ThrowIfNull(chooseElements); @@ -113,5 +109,4 @@ public DeletableElement(XElement storedElement, XElement element) /// public int? DeletionOrder { get; set; } } -#endif } diff --git a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs index 8782833a9983..4bcb6c7c029e 100644 --- a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs @@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.DataProtection.Repositories; /// /// An XML repository backed by a file system. /// -public class FileSystemXmlRepository : IXmlRepository +public class FileSystemXmlRepository : IXmlRepositoryWithDeletion { private readonly ILogger _logger; @@ -176,9 +176,6 @@ private void StoreElementCore(XElement element, string filename) } } - /// - public virtual bool CanRemoveElements => true; - /// public virtual bool RemoveElements(Action> chooseElements) { diff --git a/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs index 8060c24725aa..fffee8f07766 100644 --- a/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/IXmlRepository.cs @@ -1,7 +1,6 @@ // 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.Collections.Generic; using System.Xml.Linq; @@ -33,27 +32,4 @@ public interface IXmlRepository /// be the id of the key being stored. /// void StoreElement(XElement element, string friendlyName); - -#if NETCOREAPP - /// - /// Indicates whether this respository supports removal. - /// - bool CanRemoveElements => false; - - /// - /// Removes selected elements from the repository. - /// - /// - /// A snapshot of the elements in this repository. - /// For each, set to a non-null value if it should be deleted. - /// Elements are deleted in increasing order. If any deletion fails, the remaining deletions *MUST* be skipped. - /// - /// - /// True if all deletions succeeded. - /// - /// - /// If is false. - /// - bool RemoveElements(Action> chooseElements) => throw new NotSupportedException(); -#endif } diff --git a/src/DataProtection/DataProtection/src/Repositories/IXmlRepositoryWithDeletion.cs b/src/DataProtection/DataProtection/src/Repositories/IXmlRepositoryWithDeletion.cs new file mode 100644 index 000000000000..9b47bf92b302 --- /dev/null +++ b/src/DataProtection/DataProtection/src/Repositories/IXmlRepositoryWithDeletion.cs @@ -0,0 +1,27 @@ +// 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.Collections.Generic; +using System.Xml.Linq; + +namespace Microsoft.AspNetCore.DataProtection.Repositories; + +/// +/// The basic interface for storing and retrieving XML elements. +/// +public interface IXmlRepositoryWithDeletion : IXmlRepository +{ + /// + /// Removes selected elements from the repository. + /// + /// + /// A snapshot of the elements in this repository. + /// For each, set to a non-null value if it should be deleted. + /// Elements are deleted in increasing order. If any deletion fails, the remaining deletions *MUST* be skipped. + /// + /// + /// True if all deletions succeeded. + /// + bool RemoveElements(Action> chooseElements); +} diff --git a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs index bec5c7f8ea15..3c9f51e0f536 100644 --- a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.IO; using System.Linq; using System.Runtime.Versioning; using System.Security.Principal; @@ -19,7 +18,7 @@ namespace Microsoft.AspNetCore.DataProtection.Repositories; /// An XML repository backed by the Windows registry. /// [SupportedOSPlatform("windows")] -public class RegistryXmlRepository : IXmlRepository +public class RegistryXmlRepository : IXmlRepositoryWithDeletion { private static readonly Lazy _defaultRegistryKeyLazy = new Lazy(GetDefaultHklmStorageKey); @@ -157,9 +156,6 @@ private void StoreElementCore(XElement element, string valueName) RegistryKey.SetValue(valueName, element.ToString(), RegistryValueKind.String); } - /// - public virtual bool CanRemoveElements => true; - /// public virtual bool RemoveElements(Action> chooseElements) { diff --git a/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs b/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs index 5d409a05c40b..674085d4af96 100644 --- a/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs +++ b/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs @@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.DataProtection.EntityFrameworkCore; /// /// An backed by an EntityFrameworkCore datastore. /// -public class EntityFrameworkCoreXmlRepository : IXmlRepository +public class EntityFrameworkCoreXmlRepository : IXmlRepositoryWithDeletion where TContext : DbContext, IDataProtectionKeyContext { private readonly IServiceProvider _services; @@ -80,9 +80,6 @@ public void StoreElement(XElement element, string friendlyName) } } - /// - public virtual bool CanRemoveElements => true; - /// public virtual bool RemoveElements(Action> chooseElements) { diff --git a/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt b/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt index ffe18c85f65b..2531fa0e7832 100644 --- a/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt +++ b/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt @@ -1,3 +1,2 @@ #nullable enable -virtual Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.EntityFrameworkCoreXmlRepository.CanRemoveElements.get -> bool virtual Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.EntityFrameworkCoreXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool diff --git a/src/DataProtection/StackExchangeRedis/src/PublicAPI.Unshipped.txt b/src/DataProtection/StackExchangeRedis/src/PublicAPI.Unshipped.txt index adf6b1606024..216a281288ef 100644 --- a/src/DataProtection/StackExchangeRedis/src/PublicAPI.Unshipped.txt +++ b/src/DataProtection/StackExchangeRedis/src/PublicAPI.Unshipped.txt @@ -1,3 +1,2 @@ #nullable enable -virtual Microsoft.AspNetCore.DataProtection.StackExchangeRedis.RedisXmlRepository.CanRemoveElements.get -> bool virtual Microsoft.AspNetCore.DataProtection.StackExchangeRedis.RedisXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool diff --git a/src/DataProtection/StackExchangeRedis/src/RedisXmlRepository.cs b/src/DataProtection/StackExchangeRedis/src/RedisXmlRepository.cs index a156453d7e10..78ce569ee019 100644 --- a/src/DataProtection/StackExchangeRedis/src/RedisXmlRepository.cs +++ b/src/DataProtection/StackExchangeRedis/src/RedisXmlRepository.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.DataProtection.StackExchangeRedis; /// /// An XML repository backed by a Redis list entry. /// -public class RedisXmlRepository : IXmlRepository +public class RedisXmlRepository : IXmlRepositoryWithDeletion { private readonly Func _databaseFactory; private readonly RedisKey _key; @@ -56,9 +56,6 @@ public void StoreElement(XElement element, string friendlyName) database.ListRightPush(_key, element.ToString(SaveOptions.DisableFormatting)); } - /// - public virtual bool CanRemoveElements => true; - /// public virtual bool RemoveElements(Action> chooseElements) { From a3e5913764d89594cad2a1d232f3f5c1e9f60607 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Fri, 12 Jul 2024 11:51:16 -0700 Subject: [PATCH 23/40] Actually stop iterating if some key deletion fails --- .../DataProtection/src/LoggingExtensions.cs | 4 ++-- .../src/Repositories/FileSystemXmlRepository.cs | 6 ++---- .../src/Repositories/RegistryXmlRepository.cs | 8 +++----- .../src/EntityFrameworkCoreXmlRepository.cs | 8 +++----- .../EntityFrameworkCore/src/LoggingExtensions.cs | 4 ++-- 5 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/DataProtection/DataProtection/src/LoggingExtensions.cs b/src/DataProtection/DataProtection/src/LoggingExtensions.cs index 3e545d38a2a7..1778ba05ab5b 100644 --- a/src/DataProtection/DataProtection/src/LoggingExtensions.cs +++ b/src/DataProtection/DataProtection/src/LoggingExtensions.cs @@ -259,13 +259,13 @@ private static bool IsLogLevelEnabledCore([NotNullWhen(true)] ILogger? logger, L [LoggerMessage(74, LogLevel.Information, "Deleting file '{FileName}'.", EventName = "DeletingFile")] public static partial void DeletingFile(this ILogger logger, string fileName); - [LoggerMessage(75, LogLevel.Information, "Failed to delete file '{FileName}'.", EventName = "FailedToDeleteFile")] + [LoggerMessage(75, LogLevel.Information, "Failed to delete file '{FileName}'. Not attempting further deletions.", EventName = "FailedToDeleteFile")] public static partial void FailedToDeleteFile(this ILogger logger, string fileName, Exception exception); [LoggerMessage(76, LogLevel.Debug, "Deleting registry key '{RegistryKeyName}', value '{Value}'.", EventName = "RemovingDataFromRegistryKeyValue")] public static partial void RemovingDataFromRegistryKeyValue(this ILogger logger, RegistryKey registryKeyName, string value); - [LoggerMessage(77, LogLevel.Error, "Failed to delete registry key '{RegistryKeyName}', value '{ValueName}'.", EventName = "FailedToRemoveDataFromRegistryKeyValue")] + [LoggerMessage(77, LogLevel.Error, "Failed to delete registry key '{RegistryKeyName}', value '{ValueName}'. Not attempting further deletions.", EventName = "FailedToRemoveDataFromRegistryKeyValue")] public static partial void FailedToRemoveDataFromRegistryKeyValue(this ILogger logger, RegistryKey registryKeyName, string valueName, Exception exception); [LoggerMessage(78, LogLevel.Trace, "Found multiple revocation entries for key {KeyId:B}.", EventName = "KeyRevokedMultipleTimes")] diff --git a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs index 4bcb6c7c029e..d80652869971 100644 --- a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs @@ -192,8 +192,6 @@ public virtual bool RemoveElements(Action chooseElements(deletableElements); - var allSucceeded = true; - var elementsToDelete = deletableElements .Where(e => e.DeletionOrder.HasValue) .OrderBy(e => e.DeletionOrder.GetValueOrDefault()); @@ -210,11 +208,11 @@ public virtual bool RemoveElements(Action { Debug.Assert(fileSystemInfo.Exists, "Having previously been deleted should not have caused an exception"); _logger.FailedToDeleteFile(fileSystemInfo.FullName, ex); - allSucceeded = false; + return false; } } - return allSucceeded; + return true; } private sealed class DeletableElement : IDeletableElement diff --git a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs index 3c9f51e0f536..0fd53cc4a1e2 100644 --- a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs @@ -174,8 +174,6 @@ public virtual bool RemoveElements(Action chooseElements(deletableElements); - var allSucceeded = true; - var elementsToDelete = deletableElements .Where(e => e.DeletionOrder.HasValue) .OrderBy(e => e.DeletionOrder.GetValueOrDefault()); @@ -186,16 +184,16 @@ public virtual bool RemoveElements(Action _logger.RemovingDataFromRegistryKeyValue(RegistryKey, valueName); try { - RegistryKey.DeleteValue(valueName); + RegistryKey.DeleteValue(valueName, throwOnMissingValue: false); } catch (Exception ex) { _logger.FailedToRemoveDataFromRegistryKeyValue(RegistryKey, valueName, ex); - allSucceeded = false; + return false; } } - return allSucceeded; + return true; } private sealed class DeletableElement : IDeletableElement diff --git a/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs b/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs index 674085d4af96..af25c9666b9e 100644 --- a/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs +++ b/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs @@ -98,8 +98,6 @@ public virtual bool RemoveElements(Action chooseElements(deletableElements); - var allSucceeded = true; - var elementsToDelete = deletableElements .Where(e => e.DeletionOrder.HasValue) .OrderBy(e => e.DeletionOrder.GetValueOrDefault()); @@ -115,7 +113,7 @@ public virtual bool RemoveElements(Action catch (Exception ex) { _logger.FailedToDeleteKeyFromDbContext(key.FriendlyName, typeof(TContext).Name, ex); - allSucceeded = false; + return false; } } @@ -126,10 +124,10 @@ public virtual bool RemoveElements(Action catch (Exception ex) { _logger.FailedToSaveKeyDeletionsToDbContext(typeof(TContext).Name, ex); - allSucceeded = false; + return false; } - return allSucceeded; + return true; } } diff --git a/src/DataProtection/EntityFrameworkCore/src/LoggingExtensions.cs b/src/DataProtection/EntityFrameworkCore/src/LoggingExtensions.cs index db6e63bdda32..a64f211d17a8 100644 --- a/src/DataProtection/EntityFrameworkCore/src/LoggingExtensions.cs +++ b/src/DataProtection/EntityFrameworkCore/src/LoggingExtensions.cs @@ -11,10 +11,10 @@ internal static partial class LoggingExtensions [LoggerMessage(2, LogLevel.Debug, "Saving key '{FriendlyName}' to '{DbContext}'.", EventName = "SavingKeyToDbContext")] public static partial void LogSavingKeyToDbContext(this ILogger logger, string friendlyName, string dbContext); - [LoggerMessage(3, LogLevel.Debug, "Deleting key '{FriendlyName}' from '{DbContext}'.", EventName = "DeletingKeyFromDbContext")] + [LoggerMessage(3, LogLevel.Debug, "Marking key '{FriendlyName}' for deletion from '{DbContext}'.", EventName = "DeletingKeyFromDbContext")] public static partial void DeletingKeyFromDbContext(this ILogger logger, string? friendlyName, string dbContext); - [LoggerMessage(4, LogLevel.Error, "Failed to delete key '{FriendlyName}' from '{DbContext}'.", EventName = "FailedToDeleteKeyFromDbContext")] + [LoggerMessage(4, LogLevel.Error, "Failed to mark key '{FriendlyName}' for deletion from '{DbContext}'. Abandoning deletion attempt.", EventName = "FailedToDeleteKeyFromDbContext")] public static partial void FailedToDeleteKeyFromDbContext(this ILogger logger, string? friendlyName, string dbContext, Exception exception); [LoggerMessage(5, LogLevel.Error, "Failed to save key deletions to '{DbContext}'.", EventName = "FailedToSaveKeyDeletionsToDbContext")] From a31d00759a567610ef4c0e2690d775138e179eeb Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Fri, 12 Jul 2024 13:12:30 -0700 Subject: [PATCH 24/40] Add FileSystemXmlRepository tests --- .../FileSystemXmlRepositoryTests.cs | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs index 37aa52699d47..b5682807e2ed 100644 --- a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs +++ b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs @@ -138,6 +138,140 @@ public void StoreElements_ThenRetrieve_SeesAllElements() }); } + [Theory] + [InlineData(false, false)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(true, true)] + public void RemoveElements(bool remove1, bool remove2) + { + WithUniqueTempDirectory(dirInfo => + { + var repository = new FileSystemXmlRepository(dirInfo, NullLoggerFactory.Instance); + + var element1 = new XElement("element1"); + var element2 = new XElement("element2"); + + repository.StoreElement(element1, friendlyName: null); + repository.StoreElement(element2, friendlyName: null); + + var ranSelector = false; + + Assert.True(repository.RemoveElements(deletableElements => + { + ranSelector = true; + Assert.Equal(2, deletableElements.Count); + + foreach (var element in deletableElements) + { + switch (element.Element.Name.LocalName) + { + case "element1": + element.DeletionOrder = remove1 ? 1 : null; + break; + case "element2": + element.DeletionOrder = remove2 ? 2 : null; + break; + default: + Assert.Fail("Unexpected element name: " + element.Element.Name.LocalName); + break; + } + } + })); + Assert.True(ranSelector); + + var elementSet = new HashSet(repository.GetAllElements().Select(e => e.Name.LocalName)); + + Assert.InRange(elementSet.Count, 0, 2); + + Assert.Equal(!remove1, elementSet.Contains(element1.Name.LocalName)); + Assert.Equal(!remove2, elementSet.Contains(element2.Name.LocalName)); + }); + } + + [Fact] + public void RemoveElementsWithFailure() + { + WithUniqueTempDirectory(dirInfo => + { + var repository = new FileSystemXmlRepository(dirInfo, NullLoggerFactory.Instance); + + repository.StoreElement(new XElement("element1"), friendlyName: "friendly1"); + repository.StoreElement(new XElement("element2"), friendlyName: "friendly2"); + repository.StoreElement(new XElement("element3"), friendlyName: "friendly3"); + + var filePath1 = Path.Combine(dirInfo.FullName, "friendly1.xml"); + var filePath2 = Path.Combine(dirInfo.FullName, "friendly2.xml"); + var filePath3 = Path.Combine(dirInfo.FullName, "friendly3.xml"); + + Assert.True(File.Exists(filePath1)); + Assert.True(File.Exists(filePath2)); + Assert.True(File.Exists(filePath3)); + + IDisposable fileLock2 = null; + try + { + var ranSelector = false; + Assert.False(repository.RemoveElements(deletableElements => + { + ranSelector = true; + + // Now that the repository has read the files from disk, lock one to prevent deletion from succeeding + fileLock2 = new FileStream(Path.Combine(dirInfo.FullName, "friendly2.xml"), FileMode.Open, FileAccess.ReadWrite, FileShare.None); + + Assert.Equal(3, deletableElements.Count); + + var i = 4; + foreach (var deletableElement in deletableElements) + { + // Delete in reverse alphabetical order, so the results aren't coincidental. + deletableElement.DeletionOrder = i--; + } + })); + Assert.True(ranSelector); + } + finally + { + fileLock2?.Dispose(); + } + + Assert.True(File.Exists(filePath1)); // Deletion not attempted after failure + Assert.True(File.Exists(filePath2)); // Deletion fails because of lock + Assert.False(File.Exists(filePath3)); // Deleted before error + }); + } + + [Fact] + public void RemoveElementsWithOutOfBandDeletion() + { + WithUniqueTempDirectory(dirInfo => + { + var repository = new FileSystemXmlRepository(dirInfo, NullLoggerFactory.Instance); + + repository.StoreElement(new XElement("element1"), friendlyName: "friendly1"); + + var filePath = Path.Combine(dirInfo.FullName, "friendly1.xml"); + Assert.True(File.Exists(filePath)); + + var ranSelector = false; + + Assert.True(repository.RemoveElements(deletableElements => + { + ranSelector = true; + + // Now that the repository has read the files from disk, delete one out of band + File.Delete(filePath); + + Assert.Equal(1, deletableElements.Count); + + deletableElements.First().DeletionOrder = 1; + })); + Assert.True(ranSelector); + + Assert.False(File.Exists(filePath)); + }); + } + [ConditionalFact] [DockerOnly] [Trait("Docker", "true")] From 80c7b4b669351ace93e2327598766b22fc02afd1 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Fri, 12 Jul 2024 13:26:10 -0700 Subject: [PATCH 25/40] Add RegistryXmlRepository tests --- .../FileSystemXmlRepositoryTests.cs | 2 +- .../RegistryXmlRepositoryTests.cs | 88 +++++++++++++++++++ 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs index b5682807e2ed..83d7ad79c4cd 100644 --- a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs +++ b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs @@ -259,7 +259,7 @@ public void RemoveElementsWithOutOfBandDeletion() { ranSelector = true; - // Now that the repository has read the files from disk, delete one out of band + // Now that the repository has read the element from disk, delete it out-of-band. File.Delete(filePath); Assert.Equal(1, deletableElements.Count); diff --git a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/RegistryXmlRepositoryTests.cs b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/RegistryXmlRepositoryTests.cs index e098785d0678..dbcdd30ae822 100644 --- a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/RegistryXmlRepositoryTests.cs +++ b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/RegistryXmlRepositoryTests.cs @@ -125,6 +125,94 @@ public void StoreElements_ThenRetrieve_SeesAllElements() }); } + [Theory] + [InlineData(false, false)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(true, true)] + public void RemoveElements(bool remove1, bool remove2) + { + WithUniqueTempRegKey(regKey => + { + var repository = new RegistryXmlRepository(regKey, NullLoggerFactory.Instance); + + var element1 = new XElement("element1"); + var element2 = new XElement("element2"); + + repository.StoreElement(element1, friendlyName: null); + repository.StoreElement(element2, friendlyName: null); + + var ranSelector = false; + + Assert.True(repository.RemoveElements(deletableElements => + { + ranSelector = true; + Assert.Equal(2, deletableElements.Count); + + foreach (var element in deletableElements) + { + switch (element.Element.Name.LocalName) + { + case "element1": + element.DeletionOrder = remove1 ? 1 : null; + break; + case "element2": + element.DeletionOrder = remove2 ? 2 : null; + break; + default: + Assert.Fail("Unexpected element name: " + element.Element.Name.LocalName); + break; + } + } + })); + Assert.True(ranSelector); + + var elementSet = new HashSet(repository.GetAllElements().Select(e => e.Name.LocalName)); + + Assert.InRange(elementSet.Count, 0, 2); + + Assert.Equal(!remove1, elementSet.Contains(element1.Name.LocalName)); + Assert.Equal(!remove2, elementSet.Contains(element2.Name.LocalName)); + }); + } + + // It would be nice to have a test paralleling the one in FileSystemXmlRepositoryTests.cs, + // but there's no obvious way to simulate a failure for only one of the values. You can + // lock a whole key, but not individual values, and we don't have a hook to let us lock the + // whole key while a particular value deletion is attempted. + //[Fact] + //public void RemoveElementsWithFailure() + + [Fact] + public void RemoveElementsWithOutOfBandDeletion() + { + WithUniqueTempRegKey(regKey => + { + var repository = new RegistryXmlRepository(regKey, NullLoggerFactory.Instance); + + repository.StoreElement(new XElement("element1"), friendlyName: "friendly1"); + + Assert.NotNull(regKey.GetValue("friendly1")); + + var ranSelector = false; + + Assert.True(repository.RemoveElements(deletableElements => + { + ranSelector = true; + + // Now that the repository has read the element from the registry, delete it out-of-band. + regKey.DeleteValue("friendly1"); + + Assert.Equal(1, deletableElements.Count); + + deletableElements.First().DeletionOrder = 1; + })); + Assert.True(ranSelector); + + Assert.Null(regKey.GetValue("friendly1")); + }); + } + /// /// Runs a test and cleans up the registry key afterward. /// From 63531ebb2a6ecd5c867ca86493953255baab32c8 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Fri, 12 Jul 2024 13:42:09 -0700 Subject: [PATCH 26/40] Rename new interfaces --- ...yManagerWithDeletion.cs => IDeletableKeyManager.cs} | 6 +++--- .../DataProtection/src/KeyManagement/XmlKeyManager.cs | 4 ++-- .../DataProtection/src/PublicAPI.Unshipped.txt | 10 +++++----- .../src/Repositories/EphemeralXmlRepository.cs | 4 ++-- .../src/Repositories/FileSystemXmlRepository.cs | 2 +- ...itoryWithDeletion.cs => IDeletableXmlRepository.cs} | 2 +- .../src/Repositories/RegistryXmlRepository.cs | 2 +- .../src/EntityFrameworkCoreXmlRepository.cs | 2 +- .../StackExchangeRedis/src/RedisXmlRepository.cs | 2 +- 9 files changed, 17 insertions(+), 17 deletions(-) rename src/DataProtection/DataProtection/src/KeyManagement/{IKeyManagerWithDeletion.cs => IDeletableKeyManager.cs} (96%) rename src/DataProtection/DataProtection/src/Repositories/{IXmlRepositoryWithDeletion.cs => IDeletableXmlRepository.cs} (94%) diff --git a/src/DataProtection/DataProtection/src/KeyManagement/IKeyManagerWithDeletion.cs b/src/DataProtection/DataProtection/src/KeyManagement/IDeletableKeyManager.cs similarity index 96% rename from src/DataProtection/DataProtection/src/KeyManagement/IKeyManagerWithDeletion.cs rename to src/DataProtection/DataProtection/src/KeyManagement/IDeletableKeyManager.cs index 3f3177d6a877..b6e225045891 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/IKeyManagerWithDeletion.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/IDeletableKeyManager.cs @@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement; /// /// Instantiations of this interface are expected to be thread-safe. /// -public interface IKeyManagerWithDeletion : IKeyManager +public interface IDeletableKeyManager : IKeyManager { /// /// Indicates whether this key manager supports key deletion. @@ -27,7 +27,7 @@ public interface IKeyManagerWithDeletion : IKeyManager /// /// Deletes keys matching a predicate. - /// + /// /// Use with caution as deleting active keys will normally cause data loss. /// /// @@ -40,7 +40,7 @@ public interface IKeyManagerWithDeletion : IKeyManager /// /// Generally, keys should only be deleted to save space. If space is not a concern, keys /// should be revoked or allowed to expire instead. - /// + /// /// This method will not mutate existing IKey instances. After calling this method, /// all existing IKey instances should be discarded, and GetAllKeys should be called again. /// diff --git a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs index f6ee9ff9f123..6f7814caff13 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs @@ -408,12 +408,12 @@ public void RevokeKey(Guid keyId, string? reason = null) } /// - public bool CanDeleteKeys => KeyRepository is IXmlRepositoryWithDeletion; + public bool CanDeleteKeys => KeyRepository is IDeletableXmlRepository; /// public bool DeleteKeys(Func shouldDelete) { - if (KeyRepository is not IXmlRepositoryWithDeletion xmlRepositoryWithDeletion) + if (KeyRepository is not IDeletableXmlRepository xmlRepositoryWithDeletion) { throw Error.XmlKeyManager_DoesNotSupportKeyDeletion(); } diff --git a/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt index c260fd6e9be8..5667d4e18cab 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt @@ -1,14 +1,14 @@ #nullable enable -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManagerWithDeletion -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManagerWithDeletion.CanDeleteKeys.get -> bool -Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManagerWithDeletion.DeleteKeys(System.Func! shouldDelete) -> bool +Microsoft.AspNetCore.DataProtection.KeyManagement.IDeletableKeyManager +Microsoft.AspNetCore.DataProtection.KeyManagement.IDeletableKeyManager.CanDeleteKeys.get -> bool +Microsoft.AspNetCore.DataProtection.KeyManagement.IDeletableKeyManager.DeleteKeys(System.Func! shouldDelete) -> bool Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.CanDeleteKeys.get -> bool Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.DeleteKeys(System.Func! shouldDelete) -> bool Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.DeletionOrder.get -> int? Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.DeletionOrder.set -> void Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.Element.get -> System.Xml.Linq.XElement! -Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepositoryWithDeletion -Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepositoryWithDeletion.RemoveElements(System.Action!>! chooseElements) -> bool +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableXmlRepository +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool diff --git a/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs index 4915b80bcae3..a04f12ba8d4a 100644 --- a/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs @@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.DataProtection.Repositories; /// An ephemeral XML repository backed by process memory. This class must not be used for /// anything other than dev scenarios as the keys will not be persisted to storage. /// -internal sealed class EphemeralXmlRepository : IXmlRepositoryWithDeletion +internal sealed class EphemeralXmlRepository : IDeletableXmlRepository { private readonly List _storedElements = new List(); @@ -56,7 +56,7 @@ public void StoreElement(XElement element, string friendlyName) } /// - bool IXmlRepositoryWithDeletion.RemoveElements(Action> chooseElements) + bool IDeletableXmlRepository.RemoveElements(Action> chooseElements) { ArgumentNullThrowHelper.ThrowIfNull(chooseElements); diff --git a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs index d80652869971..763d931a6cb6 100644 --- a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs @@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.DataProtection.Repositories; /// /// An XML repository backed by a file system. /// -public class FileSystemXmlRepository : IXmlRepositoryWithDeletion +public class FileSystemXmlRepository : IDeletableXmlRepository { private readonly ILogger _logger; diff --git a/src/DataProtection/DataProtection/src/Repositories/IXmlRepositoryWithDeletion.cs b/src/DataProtection/DataProtection/src/Repositories/IDeletableXmlRepository.cs similarity index 94% rename from src/DataProtection/DataProtection/src/Repositories/IXmlRepositoryWithDeletion.cs rename to src/DataProtection/DataProtection/src/Repositories/IDeletableXmlRepository.cs index 9b47bf92b302..ff2b96c96b28 100644 --- a/src/DataProtection/DataProtection/src/Repositories/IXmlRepositoryWithDeletion.cs +++ b/src/DataProtection/DataProtection/src/Repositories/IDeletableXmlRepository.cs @@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.DataProtection.Repositories; /// /// The basic interface for storing and retrieving XML elements. /// -public interface IXmlRepositoryWithDeletion : IXmlRepository +public interface IDeletableXmlRepository : IXmlRepository { /// /// Removes selected elements from the repository. diff --git a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs index 0fd53cc4a1e2..a27543205b47 100644 --- a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs @@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.DataProtection.Repositories; /// An XML repository backed by the Windows registry. /// [SupportedOSPlatform("windows")] -public class RegistryXmlRepository : IXmlRepositoryWithDeletion +public class RegistryXmlRepository : IDeletableXmlRepository { private static readonly Lazy _defaultRegistryKeyLazy = new Lazy(GetDefaultHklmStorageKey); diff --git a/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs b/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs index af25c9666b9e..e237057de92b 100644 --- a/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs +++ b/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs @@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.DataProtection.EntityFrameworkCore; /// /// An backed by an EntityFrameworkCore datastore. /// -public class EntityFrameworkCoreXmlRepository : IXmlRepositoryWithDeletion +public class EntityFrameworkCoreXmlRepository : IDeletableXmlRepository where TContext : DbContext, IDataProtectionKeyContext { private readonly IServiceProvider _services; diff --git a/src/DataProtection/StackExchangeRedis/src/RedisXmlRepository.cs b/src/DataProtection/StackExchangeRedis/src/RedisXmlRepository.cs index 78ce569ee019..297a53f7fa10 100644 --- a/src/DataProtection/StackExchangeRedis/src/RedisXmlRepository.cs +++ b/src/DataProtection/StackExchangeRedis/src/RedisXmlRepository.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.DataProtection.StackExchangeRedis; /// /// An XML repository backed by a Redis list entry. /// -public class RedisXmlRepository : IXmlRepositoryWithDeletion +public class RedisXmlRepository : IDeletableXmlRepository { private readonly Func _databaseFactory; private readonly RedisKey _key; From d8c1df6198e83c6c0d2462b491d2c7cf9b7d16d8 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Fri, 12 Jul 2024 13:50:45 -0700 Subject: [PATCH 27/40] Defer EF and Redis to a subsequent PR --- .../src/EntityFrameworkCoreXmlRepository.cs | 71 +------------------ .../src/PublicAPI.Unshipped.txt | 1 - .../src/PublicAPI.Unshipped.txt | 1 - .../src/RedisXmlRepository.cs | 8 +-- 4 files changed, 2 insertions(+), 79 deletions(-) diff --git a/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs b/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs index e237057de92b..b1d206da0352 100644 --- a/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs +++ b/src/DataProtection/EntityFrameworkCore/src/EntityFrameworkCoreXmlRepository.cs @@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.DataProtection.EntityFrameworkCore; /// /// An backed by an EntityFrameworkCore datastore. /// -public class EntityFrameworkCoreXmlRepository : IDeletableXmlRepository +public class EntityFrameworkCoreXmlRepository : IXmlRepository where TContext : DbContext, IDataProtectionKeyContext { private readonly IServiceProvider _services; @@ -79,73 +79,4 @@ public void StoreElement(XElement element, string friendlyName) context.SaveChanges(); } } - - /// - public virtual bool RemoveElements(Action> chooseElements) - { - using (var scope = _services.CreateScope()) - { - var context = scope.ServiceProvider.GetRequiredService(); - var deletableElements = new List(); - - foreach (var key in context.DataProtectionKeys.AsNoTracking()) - { - if (!string.IsNullOrEmpty(key.Xml)) - { - deletableElements.Add(new DeletableElement(key, XElement.Parse(key.Xml))); - } - } - - chooseElements(deletableElements); - - var elementsToDelete = deletableElements - .Where(e => e.DeletionOrder.HasValue) - .OrderBy(e => e.DeletionOrder.GetValueOrDefault()); - - foreach (var deletableElement in elementsToDelete) - { - var key = deletableElement.Key; - _logger.DeletingKeyFromDbContext(key.FriendlyName, typeof(TContext).Name); - try - { - context.DataProtectionKeys.Remove(key); - } - catch (Exception ex) - { - _logger.FailedToDeleteKeyFromDbContext(key.FriendlyName, typeof(TContext).Name, ex); - return false; - } - } - - try - { - context.SaveChanges(); - } - catch (Exception ex) - { - _logger.FailedToSaveKeyDeletionsToDbContext(typeof(TContext).Name, ex); - return false; - } - - return true; - } - } - - private sealed class DeletableElement : IDeletableElement - { - public DeletableElement(DataProtectionKey key, XElement element) - { - Key = key; - Element = element; - } - - /// - public XElement Element { get; } - - /// The from which was read. - public DataProtectionKey Key { get; } - - /// - public int? DeletionOrder { get; set; } - } } diff --git a/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt b/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt index 2531fa0e7832..7dc5c58110bf 100644 --- a/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt +++ b/src/DataProtection/EntityFrameworkCore/src/PublicAPI.Unshipped.txt @@ -1,2 +1 @@ #nullable enable -virtual Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.EntityFrameworkCoreXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool diff --git a/src/DataProtection/StackExchangeRedis/src/PublicAPI.Unshipped.txt b/src/DataProtection/StackExchangeRedis/src/PublicAPI.Unshipped.txt index 216a281288ef..7dc5c58110bf 100644 --- a/src/DataProtection/StackExchangeRedis/src/PublicAPI.Unshipped.txt +++ b/src/DataProtection/StackExchangeRedis/src/PublicAPI.Unshipped.txt @@ -1,2 +1 @@ #nullable enable -virtual Microsoft.AspNetCore.DataProtection.StackExchangeRedis.RedisXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool diff --git a/src/DataProtection/StackExchangeRedis/src/RedisXmlRepository.cs b/src/DataProtection/StackExchangeRedis/src/RedisXmlRepository.cs index 297a53f7fa10..9ef8bcc5d9a3 100644 --- a/src/DataProtection/StackExchangeRedis/src/RedisXmlRepository.cs +++ b/src/DataProtection/StackExchangeRedis/src/RedisXmlRepository.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.DataProtection.StackExchangeRedis; /// /// An XML repository backed by a Redis list entry. /// -public class RedisXmlRepository : IDeletableXmlRepository +public class RedisXmlRepository : IXmlRepository { private readonly Func _databaseFactory; private readonly RedisKey _key; @@ -55,10 +55,4 @@ public void StoreElement(XElement element, string friendlyName) var database = _databaseFactory(); database.ListRightPush(_key, element.ToString(SaveOptions.DisableFormatting)); } - - /// - public virtual bool RemoveElements(Action> chooseElements) - { - throw new NotImplementedException(); // TODO (acasey): ask Marc - } } From bf4a92bc80a1ca26e38cb47adf1a2fa655c99bc1 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Fri, 12 Jul 2024 13:56:40 -0700 Subject: [PATCH 28/40] Add EphemeralXmlRepository tests --- .../Repositories/EphemeralXmlRepository.cs | 2 +- .../EphemeralXmlRepositoryTests.cs | 73 +++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs index a04f12ba8d4a..279418712794 100644 --- a/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs @@ -56,7 +56,7 @@ public void StoreElement(XElement element, string friendlyName) } /// - bool IDeletableXmlRepository.RemoveElements(Action> chooseElements) + public bool RemoveElements(Action> chooseElements) { ArgumentNullThrowHelper.ThrowIfNull(chooseElements); diff --git a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/EphemeralXmlRepositoryTests.cs b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/EphemeralXmlRepositoryTests.cs index fd517a23d90f..bd079e38295b 100644 --- a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/EphemeralXmlRepositoryTests.cs +++ b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/EphemeralXmlRepositoryTests.cs @@ -34,4 +34,77 @@ public void Store_Then_Get() repository.StoreElement(element3, null); Assert.Equal(new[] { element1, element2, element3 }, repository.GetAllElements(), XmlAssert.EqualityComparer); } + + [Theory] + [InlineData(false, false)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(true, true)] + public void RemoveElements(bool remove1, bool remove2) + { + var repository = new EphemeralXmlRepository(NullLoggerFactory.Instance); + + var element1 = new XElement("element1"); + var element2 = new XElement("element2"); + + repository.StoreElement(element1, friendlyName: null); + repository.StoreElement(element2, friendlyName: null); + + var ranSelector = false; + + Assert.True(repository.RemoveElements(deletableElements => + { + ranSelector = true; + Assert.Equal(2, deletableElements.Count); + + foreach (var element in deletableElements) + { + switch (element.Element.Name.LocalName) + { + case "element1": + element.DeletionOrder = remove1 ? 1 : null; + break; + case "element2": + element.DeletionOrder = remove2 ? 2 : null; + break; + default: + Assert.Fail("Unexpected element name: " + element.Element.Name.LocalName); + break; + } + } + })); + Assert.True(ranSelector); + + var elementSet = new HashSet(repository.GetAllElements().Select(e => e.Name.LocalName)); + + Assert.InRange(elementSet.Count, 0, 2); + + Assert.Equal(!remove1, elementSet.Contains(element1.Name.LocalName)); + Assert.Equal(!remove2, elementSet.Contains(element2.Name.LocalName)); + } + + [Fact] + public void RemoveElementsWithOutOfBandDeletion() + { + var repository = new EphemeralXmlRepository(NullLoggerFactory.Instance); + + repository.StoreElement(new XElement("element1"), friendlyName: "friendly1"); + + var ranSelector = false; + + Assert.True(repository.RemoveElements(deletableElements => + { + ranSelector = true; + + // Now that the repository has read the element from the registry, delete it out-of-band. + repository.RemoveElements(deletableElements => deletableElements.First().DeletionOrder = 1); + + Assert.Equal(1, deletableElements.Count); + + deletableElements.First().DeletionOrder = 1; + })); + Assert.True(ranSelector); + + Assert.Empty(repository.GetAllElements()); + } } From 5661a926b72c202024f1eae8608abed33ffe81de Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Fri, 12 Jul 2024 14:01:14 -0700 Subject: [PATCH 29/40] Revert EF logging --- .../EntityFrameworkCore/src/LoggingExtensions.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/DataProtection/EntityFrameworkCore/src/LoggingExtensions.cs b/src/DataProtection/EntityFrameworkCore/src/LoggingExtensions.cs index a64f211d17a8..5491abcbeebc 100644 --- a/src/DataProtection/EntityFrameworkCore/src/LoggingExtensions.cs +++ b/src/DataProtection/EntityFrameworkCore/src/LoggingExtensions.cs @@ -10,13 +10,4 @@ internal static partial class LoggingExtensions [LoggerMessage(2, LogLevel.Debug, "Saving key '{FriendlyName}' to '{DbContext}'.", EventName = "SavingKeyToDbContext")] public static partial void LogSavingKeyToDbContext(this ILogger logger, string friendlyName, string dbContext); - - [LoggerMessage(3, LogLevel.Debug, "Marking key '{FriendlyName}' for deletion from '{DbContext}'.", EventName = "DeletingKeyFromDbContext")] - public static partial void DeletingKeyFromDbContext(this ILogger logger, string? friendlyName, string dbContext); - - [LoggerMessage(4, LogLevel.Error, "Failed to mark key '{FriendlyName}' for deletion from '{DbContext}'. Abandoning deletion attempt.", EventName = "FailedToDeleteKeyFromDbContext")] - public static partial void FailedToDeleteKeyFromDbContext(this ILogger logger, string? friendlyName, string dbContext, Exception exception); - - [LoggerMessage(5, LogLevel.Error, "Failed to save key deletions to '{DbContext}'.", EventName = "FailedToSaveKeyDeletionsToDbContext")] - public static partial void FailedToSaveKeyDeletionsToDbContext(this ILogger logger, string dbContext, Exception exception); } From 8f919e038bd3047070cd7e78457079ecc70d4934 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Fri, 12 Jul 2024 14:17:16 -0700 Subject: [PATCH 30/40] Update copy-pasta doc comments --- .../DataProtection/src/KeyManagement/IDeletableKeyManager.cs | 5 +---- .../src/Repositories/IDeletableXmlRepository.cs | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/DataProtection/DataProtection/src/KeyManagement/IDeletableKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/IDeletableKeyManager.cs index b6e225045891..9e8b4d770a6a 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/IDeletableKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/IDeletableKeyManager.cs @@ -9,11 +9,8 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement; /// -/// The basic interface for performing key management operations. +/// An extension of that supports key deletion. /// -/// -/// Instantiations of this interface are expected to be thread-safe. -/// public interface IDeletableKeyManager : IKeyManager { /// diff --git a/src/DataProtection/DataProtection/src/Repositories/IDeletableXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/IDeletableXmlRepository.cs index ff2b96c96b28..30888ae56cae 100644 --- a/src/DataProtection/DataProtection/src/Repositories/IDeletableXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/IDeletableXmlRepository.cs @@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.DataProtection.Repositories; /// -/// The basic interface for storing and retrieving XML elements. +/// An extension of that supports deletion of elements. /// public interface IDeletableXmlRepository : IXmlRepository { From 2f1f46dd2c5201af3618c18215d81e3470ab877b Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Fri, 12 Jul 2024 16:43:40 -0700 Subject: [PATCH 31/40] Add XmlKeyManager tests --- .../KeyManagement/XmlKeyManagerTests.cs | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/KeyManagement/XmlKeyManagerTests.cs b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/KeyManagement/XmlKeyManagerTests.cs index e15a94d9ff14..ecc9e83493e4 100644 --- a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/KeyManagement/XmlKeyManagerTests.cs +++ b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/KeyManagement/XmlKeyManagerTests.cs @@ -928,6 +928,97 @@ public void NovelFetchedKeyRequiresDecryption() Assert.Equal(1, decryptionCount); // Still 1 (i.e. no change) } + [Fact] + public void DeleteKeys() + { + var repository = new EphemeralXmlRepository(NullLoggerFactory.Instance); + + var keyManager = new XmlKeyManager( + Options.Create(new KeyManagementOptions() + { + AuthenticatedEncryptorConfiguration = new AuthenticatedEncryptorConfiguration(), + XmlRepository = repository, + XmlEncryptor = null + }), + SimpleActivator.DefaultWithoutServices, + NullLoggerFactory.Instance); + + var activationTime = DateTimeOffset.UtcNow.AddHours(1); + + var key1 = keyManager.CreateNewKey(activationTime, activationTime.AddMinutes(10)); + keyManager.RevokeAllKeys(DateTimeOffset.UtcNow, "Revoking all keys"); // This should revoke key1 + var key2 = keyManager.CreateNewKey(activationTime, activationTime.AddMinutes(10)); + keyManager.RevokeAllKeys(DateTimeOffset.UtcNow, "Revoking all keys"); // This should revoke key1 and key2 + var key3 = keyManager.CreateNewKey(activationTime, activationTime.AddMinutes(10)); + var key4 = keyManager.CreateNewKey(activationTime, activationTime.AddMinutes(10)); + + keyManager.RevokeKey(key2.KeyId); // Revoked by time, but also individually + keyManager.RevokeKey(key3.KeyId); + keyManager.RevokeKey(key3.KeyId); // Nothing prevents us from revoking the same key twice + + Assert.Equal(9, repository.GetAllElements().Count); // 4 keys, 2 time-revocations, 3 guid-revocations + + // The keys are stale now, but we only care about the IDs + + var keyDictWithRevocations = keyManager.GetAllKeys().ToDictionary(k => k.KeyId); + Assert.Equal(4, keyDictWithRevocations.Count); + Assert.True(keyDictWithRevocations[key1.KeyId].IsRevoked); + Assert.True(keyDictWithRevocations[key2.KeyId].IsRevoked); + Assert.True(keyDictWithRevocations[key3.KeyId].IsRevoked); + Assert.False(keyDictWithRevocations[key4.KeyId].IsRevoked); + + Assert.True(keyManager.DeleteKeys(key => key.KeyId == key1.KeyId || key.KeyId == key3.KeyId)); + + Assert.Equal(4, repository.GetAllElements().Count); // 2 keys, 1 time-revocation, 1 guid-revocations + + var keyDictWithDeletions = keyManager.GetAllKeys().ToDictionary(k => k.KeyId); + Assert.Equal(2, keyDictWithDeletions.Count); + Assert.DoesNotContain(key1.KeyId, keyDictWithDeletions.Keys); + Assert.True(keyDictWithRevocations[key2.KeyId].IsRevoked); + Assert.DoesNotContain(key3.KeyId, keyDictWithDeletions.Keys); + Assert.False(keyDictWithRevocations[key4.KeyId].IsRevoked); + } + + [Fact] + public void CanDeleteKey() + { + var withDeletion = new XmlKeyManager(Options.Create(new KeyManagementOptions() + { + XmlRepository = XmlRepositoryWithDeletion.Instance, + XmlEncryptor = null + }), SimpleActivator.DefaultWithoutServices, NullLoggerFactory.Instance); + Assert.True(withDeletion.CanDeleteKeys); + + var withoutDeletion = new XmlKeyManager(Options.Create(new KeyManagementOptions() + { + XmlRepository = XmlRepositoryWithoutDeletion.Instance, + XmlEncryptor = null + }), SimpleActivator.DefaultWithoutServices, NullLoggerFactory.Instance); + Assert.False(withoutDeletion.CanDeleteKeys); + Assert.Throws(() => withoutDeletion.DeleteKeys(_ => false)); + } + + private sealed class XmlRepositoryWithoutDeletion : IXmlRepository + { + public static readonly IXmlRepository Instance = new XmlRepositoryWithoutDeletion(); + + private XmlRepositoryWithoutDeletion() { } + + IReadOnlyCollection IXmlRepository.GetAllElements() => []; + void IXmlRepository.StoreElement(XElement element, string friendlyName) => throw new InvalidOperationException(); + } + + private sealed class XmlRepositoryWithDeletion : IDeletableXmlRepository + { + public static readonly IDeletableXmlRepository Instance = new XmlRepositoryWithDeletion(); + + private XmlRepositoryWithDeletion() { } + + IReadOnlyCollection IXmlRepository.GetAllElements() => []; + void IXmlRepository.StoreElement(XElement element, string friendlyName) => throw new InvalidOperationException(); + bool IDeletableXmlRepository.RemoveElements(Action> chooseElements) => throw new InvalidOperationException(); + } + private class MyDeserializer : IAuthenticatedEncryptorDescriptorDeserializer { public IAuthenticatedEncryptorDescriptor ImportFromXml(XElement element) From 7e6e302b3cd4fffa3e8e789e1d7d24ddda0e2976 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Wed, 17 Jul 2024 10:27:49 -0700 Subject: [PATCH 32/40] Correct log level --- src/DataProtection/DataProtection/src/LoggingExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DataProtection/DataProtection/src/LoggingExtensions.cs b/src/DataProtection/DataProtection/src/LoggingExtensions.cs index 1778ba05ab5b..76a38b9c2e51 100644 --- a/src/DataProtection/DataProtection/src/LoggingExtensions.cs +++ b/src/DataProtection/DataProtection/src/LoggingExtensions.cs @@ -259,7 +259,7 @@ private static bool IsLogLevelEnabledCore([NotNullWhen(true)] ILogger? logger, L [LoggerMessage(74, LogLevel.Information, "Deleting file '{FileName}'.", EventName = "DeletingFile")] public static partial void DeletingFile(this ILogger logger, string fileName); - [LoggerMessage(75, LogLevel.Information, "Failed to delete file '{FileName}'. Not attempting further deletions.", EventName = "FailedToDeleteFile")] + [LoggerMessage(75, LogLevel.Error, "Failed to delete file '{FileName}'. Not attempting further deletions.", EventName = "FailedToDeleteFile")] public static partial void FailedToDeleteFile(this ILogger logger, string fileName, Exception exception); [LoggerMessage(76, LogLevel.Debug, "Deleting registry key '{RegistryKeyName}', value '{Value}'.", EventName = "RemovingDataFromRegistryKeyValue")] From f41e8a2fefebb8e37bd3c084e55b66e3c6bacc56 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Wed, 17 Jul 2024 10:39:43 -0700 Subject: [PATCH 33/40] Enumerate _storedElements under lock --- .../src/Repositories/EphemeralXmlRepository.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs index 279418712794..95c98de438ee 100644 --- a/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs @@ -62,10 +62,13 @@ public bool RemoveElements(Action> choose var deletableElements = new List(); - foreach (var storedElement in _storedElements) + lock (_storedElements) { - // Make a deep copy so caller doesn't inadvertently modify it. - deletableElements.Add(new DeletableElement(storedElement, new XElement(storedElement))); + foreach (var storedElement in _storedElements) + { + // Make a deep copy so caller doesn't inadvertently modify it. + deletableElements.Add(new DeletableElement(storedElement, new XElement(storedElement))); + } } chooseElements(deletableElements); From 55d8ffa423a13249025df6115815ce8b6d9e324f Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Wed, 17 Jul 2024 13:47:27 -0700 Subject: [PATCH 34/40] Rename RemoveElements to DeleteElements for consistency --- .../DataProtection/src/KeyManagement/XmlKeyManager.cs | 2 +- .../DataProtection/src/PublicAPI.Unshipped.txt | 6 +++--- .../src/Repositories/EphemeralXmlRepository.cs | 2 +- .../src/Repositories/FileSystemXmlRepository.cs | 2 +- .../src/Repositories/IDeletableXmlRepository.cs | 4 ++-- .../src/Repositories/RegistryXmlRepository.cs | 2 +- .../KeyManagement/XmlKeyManagerTests.cs | 2 +- .../Repositories/EphemeralXmlRepositoryTests.cs | 6 +++--- .../Repositories/FileSystemXmlRepositoryTests.cs | 6 +++--- .../Repositories/RegistryXmlRepositoryTests.cs | 4 ++-- 10 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs index 6f7814caff13..e6befb0c11b8 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs @@ -418,7 +418,7 @@ public bool DeleteKeys(Func shouldDelete) throw Error.XmlKeyManager_DoesNotSupportKeyDeletion(); } - return xmlRepositoryWithDeletion.RemoveElements((deletableElements) => + return xmlRepositoryWithDeletion.DeleteElements((deletableElements) => { // It is important to delete key elements before the corresponding revocation elements, // in case the deletion fails part way - we don't want to accidentally unrevoke a key diff --git a/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt b/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt index 5667d4e18cab..de9b28a68bda 100644 --- a/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt +++ b/src/DataProtection/DataProtection/src/PublicAPI.Unshipped.txt @@ -9,6 +9,6 @@ Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.DeletionOrder Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.DeletionOrder.set -> void Microsoft.AspNetCore.DataProtection.Repositories.IDeletableElement.Element.get -> System.Xml.Linq.XElement! Microsoft.AspNetCore.DataProtection.Repositories.IDeletableXmlRepository -Microsoft.AspNetCore.DataProtection.Repositories.IDeletableXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool -virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.RemoveElements(System.Action!>! chooseElements) -> bool +Microsoft.AspNetCore.DataProtection.Repositories.IDeletableXmlRepository.DeleteElements(System.Action!>! chooseElements) -> bool +virtual Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.DeleteElements(System.Action!>! chooseElements) -> bool +virtual Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository.DeleteElements(System.Action!>! chooseElements) -> bool diff --git a/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs index 95c98de438ee..1251d2858bf6 100644 --- a/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/EphemeralXmlRepository.cs @@ -56,7 +56,7 @@ public void StoreElement(XElement element, string friendlyName) } /// - public bool RemoveElements(Action> chooseElements) + public bool DeleteElements(Action> chooseElements) { ArgumentNullThrowHelper.ThrowIfNull(chooseElements); diff --git a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs index 763d931a6cb6..b0f25491f14d 100644 --- a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs @@ -177,7 +177,7 @@ private void StoreElementCore(XElement element, string filename) } /// - public virtual bool RemoveElements(Action> chooseElements) + public virtual bool DeleteElements(Action> chooseElements) { ArgumentNullThrowHelper.ThrowIfNull(chooseElements); diff --git a/src/DataProtection/DataProtection/src/Repositories/IDeletableXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/IDeletableXmlRepository.cs index 30888ae56cae..2d428f2c1a39 100644 --- a/src/DataProtection/DataProtection/src/Repositories/IDeletableXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/IDeletableXmlRepository.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.DataProtection.Repositories; public interface IDeletableXmlRepository : IXmlRepository { /// - /// Removes selected elements from the repository. + /// Deletes selected elements from the repository. /// /// /// A snapshot of the elements in this repository. @@ -23,5 +23,5 @@ public interface IDeletableXmlRepository : IXmlRepository /// /// True if all deletions succeeded. /// - bool RemoveElements(Action> chooseElements); + bool DeleteElements(Action> chooseElements); } diff --git a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs index a27543205b47..e03faf5424ea 100644 --- a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs @@ -157,7 +157,7 @@ private void StoreElementCore(XElement element, string valueName) } /// - public virtual bool RemoveElements(Action> chooseElements) + public virtual bool DeleteElements(Action> chooseElements) { ArgumentNullThrowHelper.ThrowIfNull(chooseElements); diff --git a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/KeyManagement/XmlKeyManagerTests.cs b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/KeyManagement/XmlKeyManagerTests.cs index ecc9e83493e4..998088277438 100644 --- a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/KeyManagement/XmlKeyManagerTests.cs +++ b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/KeyManagement/XmlKeyManagerTests.cs @@ -1016,7 +1016,7 @@ private XmlRepositoryWithDeletion() { } IReadOnlyCollection IXmlRepository.GetAllElements() => []; void IXmlRepository.StoreElement(XElement element, string friendlyName) => throw new InvalidOperationException(); - bool IDeletableXmlRepository.RemoveElements(Action> chooseElements) => throw new InvalidOperationException(); + bool IDeletableXmlRepository.DeleteElements(Action> chooseElements) => throw new InvalidOperationException(); } private class MyDeserializer : IAuthenticatedEncryptorDescriptorDeserializer diff --git a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/EphemeralXmlRepositoryTests.cs b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/EphemeralXmlRepositoryTests.cs index bd079e38295b..6527c76a5edf 100644 --- a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/EphemeralXmlRepositoryTests.cs +++ b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/EphemeralXmlRepositoryTests.cs @@ -52,7 +52,7 @@ public void RemoveElements(bool remove1, bool remove2) var ranSelector = false; - Assert.True(repository.RemoveElements(deletableElements => + Assert.True(repository.DeleteElements(deletableElements => { ranSelector = true; Assert.Equal(2, deletableElements.Count); @@ -92,12 +92,12 @@ public void RemoveElementsWithOutOfBandDeletion() var ranSelector = false; - Assert.True(repository.RemoveElements(deletableElements => + Assert.True(repository.DeleteElements(deletableElements => { ranSelector = true; // Now that the repository has read the element from the registry, delete it out-of-band. - repository.RemoveElements(deletableElements => deletableElements.First().DeletionOrder = 1); + repository.DeleteElements(deletableElements => deletableElements.First().DeletionOrder = 1); Assert.Equal(1, deletableElements.Count); diff --git a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs index 83d7ad79c4cd..1916ce94c53d 100644 --- a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs +++ b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs @@ -157,7 +157,7 @@ public void RemoveElements(bool remove1, bool remove2) var ranSelector = false; - Assert.True(repository.RemoveElements(deletableElements => + Assert.True(repository.DeleteElements(deletableElements => { ranSelector = true; Assert.Equal(2, deletableElements.Count); @@ -212,7 +212,7 @@ public void RemoveElementsWithFailure() try { var ranSelector = false; - Assert.False(repository.RemoveElements(deletableElements => + Assert.False(repository.DeleteElements(deletableElements => { ranSelector = true; @@ -255,7 +255,7 @@ public void RemoveElementsWithOutOfBandDeletion() var ranSelector = false; - Assert.True(repository.RemoveElements(deletableElements => + Assert.True(repository.DeleteElements(deletableElements => { ranSelector = true; diff --git a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/RegistryXmlRepositoryTests.cs b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/RegistryXmlRepositoryTests.cs index dbcdd30ae822..a8108391616d 100644 --- a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/RegistryXmlRepositoryTests.cs +++ b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/RegistryXmlRepositoryTests.cs @@ -144,7 +144,7 @@ public void RemoveElements(bool remove1, bool remove2) var ranSelector = false; - Assert.True(repository.RemoveElements(deletableElements => + Assert.True(repository.DeleteElements(deletableElements => { ranSelector = true; Assert.Equal(2, deletableElements.Count); @@ -196,7 +196,7 @@ public void RemoveElementsWithOutOfBandDeletion() var ranSelector = false; - Assert.True(repository.RemoveElements(deletableElements => + Assert.True(repository.DeleteElements(deletableElements => { ranSelector = true; From 61734580aac328fb3e63d1a5adbfd115cac6c11d Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Wed, 17 Jul 2024 13:54:40 -0700 Subject: [PATCH 35/40] Address PR feedback --- src/DataProtection/DataProtection/src/Error.cs | 3 +-- .../src/KeyManagement/IDeletableKeyManager.cs | 10 +++++----- .../DataProtection/src/LoggingExtensions.cs | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/DataProtection/DataProtection/src/Error.cs b/src/DataProtection/DataProtection/src/Error.cs index f3b874659bb5..7d2d48ebf958 100644 --- a/src/DataProtection/DataProtection/src/Error.cs +++ b/src/DataProtection/DataProtection/src/Error.cs @@ -105,7 +105,6 @@ public static InvalidOperationException KeyRingProvider_RefreshFailedOnOtherThre public static NotSupportedException XmlKeyManager_DoesNotSupportKeyDeletion() { - var message = string.Format(CultureInfo.CurrentCulture, Resources.XmlKeyManager_DoesNotSupportKeyDeletion); - return new NotSupportedException(message); + return new NotSupportedException(Resources.XmlKeyManager_DoesNotSupportKeyDeletion); } } diff --git a/src/DataProtection/DataProtection/src/KeyManagement/IDeletableKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/IDeletableKeyManager.cs index 9e8b4d770a6a..ab97cf559d32 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/IDeletableKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/IDeletableKeyManager.cs @@ -14,12 +14,9 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement; public interface IDeletableKeyManager : IKeyManager { /// - /// Indicates whether this key manager supports key deletion. + /// Indicates whether this key manager and the underlying support key deletion. /// - /// - /// Deletion is stronger than revocation. A revoked key is retained and can even be (forcefully) applied. - /// A deleted key is indistinguishable from a key that never existed. - /// + /// bool CanDeleteKeys { get; } /// @@ -35,6 +32,9 @@ public interface IDeletableKeyManager : IKeyManager /// True if all attempted deletions succeeded. /// /// + /// Deletion is stronger than revocation. A revoked key is retained and can even be (forcefully) applied. + /// A deleted key is indistinguishable from a key that never existed. + /// /// Generally, keys should only be deleted to save space. If space is not a concern, keys /// should be revoked or allowed to expire instead. /// diff --git a/src/DataProtection/DataProtection/src/LoggingExtensions.cs b/src/DataProtection/DataProtection/src/LoggingExtensions.cs index 76a38b9c2e51..280f818606f3 100644 --- a/src/DataProtection/DataProtection/src/LoggingExtensions.cs +++ b/src/DataProtection/DataProtection/src/LoggingExtensions.cs @@ -256,7 +256,7 @@ private static bool IsLogLevelEnabledCore([NotNullWhen(true)] ILogger? logger, L [LoggerMessage(73, LogLevel.Debug, "Key {KeyId:B} method {MethodName} failed. Retrying.", EventName = "RetryingMethodOfKeyAfterFailure")] public static partial void RetryingMethodOfKeyAfterFailure(this ILogger logger, Guid keyId, string methodName, Exception exception); - [LoggerMessage(74, LogLevel.Information, "Deleting file '{FileName}'.", EventName = "DeletingFile")] + [LoggerMessage(74, LogLevel.Debug, "Deleting file '{FileName}'.", EventName = "DeletingFile")] public static partial void DeletingFile(this ILogger logger, string fileName); [LoggerMessage(75, LogLevel.Error, "Failed to delete file '{FileName}'. Not attempting further deletions.", EventName = "FailedToDeleteFile")] From 7d27727fb12837f6efbea6115f025f8f14544a91 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Wed, 17 Jul 2024 13:55:52 -0700 Subject: [PATCH 36/40] Add clarifying comments. Co-authored-by: Chris Ross --- .../DataProtection/src/Repositories/FileSystemXmlRepository.cs | 1 + .../DataProtection/src/Repositories/RegistryXmlRepository.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs index b0f25491f14d..942d5ddf45ad 100644 --- a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs @@ -208,6 +208,7 @@ public virtual bool DeleteElements(Action { Debug.Assert(fileSystemInfo.Exists, "Having previously been deleted should not have caused an exception"); _logger.FailedToDeleteFile(fileSystemInfo.FullName, ex); + // Stop processing deletions to avoid deleting a revocation entry for a key that we failed to delete. return false; } } diff --git a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs index e03faf5424ea..f8beb45cdab3 100644 --- a/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/RegistryXmlRepository.cs @@ -189,6 +189,7 @@ public virtual bool DeleteElements(Action catch (Exception ex) { _logger.FailedToRemoveDataFromRegistryKeyValue(RegistryKey, valueName, ex); + // Stop processing deletions to avoid deleting a revocation entry for a key that we failed to delete. return false; } } From b5ae7079a3c9c865b7301906bf10b7701264df67 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Wed, 17 Jul 2024 16:38:48 -0700 Subject: [PATCH 37/40] Rename tests to match updated APIs --- .../Repositories/EphemeralXmlRepositoryTests.cs | 12 ++++++------ .../Repositories/FileSystemXmlRepositoryTests.cs | 14 +++++++------- .../Repositories/RegistryXmlRepositoryTests.cs | 14 +++++++------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/EphemeralXmlRepositoryTests.cs b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/EphemeralXmlRepositoryTests.cs index 6527c76a5edf..e00b13c5d7bd 100644 --- a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/EphemeralXmlRepositoryTests.cs +++ b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/EphemeralXmlRepositoryTests.cs @@ -40,7 +40,7 @@ public void Store_Then_Get() [InlineData(false, true)] [InlineData(true, false)] [InlineData(true, true)] - public void RemoveElements(bool remove1, bool remove2) + public void DeleteElements(bool delete1, bool delete2) { var repository = new EphemeralXmlRepository(NullLoggerFactory.Instance); @@ -62,10 +62,10 @@ public void RemoveElements(bool remove1, bool remove2) switch (element.Element.Name.LocalName) { case "element1": - element.DeletionOrder = remove1 ? 1 : null; + element.DeletionOrder = delete1 ? 1 : null; break; case "element2": - element.DeletionOrder = remove2 ? 2 : null; + element.DeletionOrder = delete2 ? 2 : null; break; default: Assert.Fail("Unexpected element name: " + element.Element.Name.LocalName); @@ -79,12 +79,12 @@ public void RemoveElements(bool remove1, bool remove2) Assert.InRange(elementSet.Count, 0, 2); - Assert.Equal(!remove1, elementSet.Contains(element1.Name.LocalName)); - Assert.Equal(!remove2, elementSet.Contains(element2.Name.LocalName)); + Assert.Equal(!delete1, elementSet.Contains(element1.Name.LocalName)); + Assert.Equal(!delete2, elementSet.Contains(element2.Name.LocalName)); } [Fact] - public void RemoveElementsWithOutOfBandDeletion() + public void DeleteElementsWithOutOfBandDeletion() { var repository = new EphemeralXmlRepository(NullLoggerFactory.Instance); diff --git a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs index 1916ce94c53d..d3cbee13e847 100644 --- a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs +++ b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs @@ -143,7 +143,7 @@ public void StoreElements_ThenRetrieve_SeesAllElements() [InlineData(false, true)] [InlineData(true, false)] [InlineData(true, true)] - public void RemoveElements(bool remove1, bool remove2) + public void DeleteElements(bool delete1, bool delete2) { WithUniqueTempDirectory(dirInfo => { @@ -167,10 +167,10 @@ public void RemoveElements(bool remove1, bool remove2) switch (element.Element.Name.LocalName) { case "element1": - element.DeletionOrder = remove1 ? 1 : null; + element.DeletionOrder = delete1 ? 1 : null; break; case "element2": - element.DeletionOrder = remove2 ? 2 : null; + element.DeletionOrder = delete2 ? 2 : null; break; default: Assert.Fail("Unexpected element name: " + element.Element.Name.LocalName); @@ -184,13 +184,13 @@ public void RemoveElements(bool remove1, bool remove2) Assert.InRange(elementSet.Count, 0, 2); - Assert.Equal(!remove1, elementSet.Contains(element1.Name.LocalName)); - Assert.Equal(!remove2, elementSet.Contains(element2.Name.LocalName)); + Assert.Equal(!delete1, elementSet.Contains(element1.Name.LocalName)); + Assert.Equal(!delete2, elementSet.Contains(element2.Name.LocalName)); }); } [Fact] - public void RemoveElementsWithFailure() + public void DeleteElementsWithFailure() { WithUniqueTempDirectory(dirInfo => { @@ -242,7 +242,7 @@ public void RemoveElementsWithFailure() } [Fact] - public void RemoveElementsWithOutOfBandDeletion() + public void DeleteElementsWithOutOfBandDeletion() { WithUniqueTempDirectory(dirInfo => { diff --git a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/RegistryXmlRepositoryTests.cs b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/RegistryXmlRepositoryTests.cs index a8108391616d..dfafb9dc5d04 100644 --- a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/RegistryXmlRepositoryTests.cs +++ b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/RegistryXmlRepositoryTests.cs @@ -130,7 +130,7 @@ public void StoreElements_ThenRetrieve_SeesAllElements() [InlineData(false, true)] [InlineData(true, false)] [InlineData(true, true)] - public void RemoveElements(bool remove1, bool remove2) + public void DeleteElements(bool delete1, bool delete2) { WithUniqueTempRegKey(regKey => { @@ -154,10 +154,10 @@ public void RemoveElements(bool remove1, bool remove2) switch (element.Element.Name.LocalName) { case "element1": - element.DeletionOrder = remove1 ? 1 : null; + element.DeletionOrder = delete1 ? 1 : null; break; case "element2": - element.DeletionOrder = remove2 ? 2 : null; + element.DeletionOrder = delete2 ? 2 : null; break; default: Assert.Fail("Unexpected element name: " + element.Element.Name.LocalName); @@ -171,8 +171,8 @@ public void RemoveElements(bool remove1, bool remove2) Assert.InRange(elementSet.Count, 0, 2); - Assert.Equal(!remove1, elementSet.Contains(element1.Name.LocalName)); - Assert.Equal(!remove2, elementSet.Contains(element2.Name.LocalName)); + Assert.Equal(!delete1, elementSet.Contains(element1.Name.LocalName)); + Assert.Equal(!delete2, elementSet.Contains(element2.Name.LocalName)); }); } @@ -181,10 +181,10 @@ public void RemoveElements(bool remove1, bool remove2) // lock a whole key, but not individual values, and we don't have a hook to let us lock the // whole key while a particular value deletion is attempted. //[Fact] - //public void RemoveElementsWithFailure() + //public void DeleteElementsWithFailure() [Fact] - public void RemoveElementsWithOutOfBandDeletion() + public void DeleteElementsWithOutOfBandDeletion() { WithUniqueTempRegKey(regKey => { From 7b4ad6ebeb10ade5cbb481206503620567e11921 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Wed, 17 Jul 2024 17:29:54 -0700 Subject: [PATCH 38/40] Make registry tests conditional on registry availability --- .../Repositories/RegistryXmlRepositoryTests.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/RegistryXmlRepositoryTests.cs b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/RegistryXmlRepositoryTests.cs index dfafb9dc5d04..1835eb4b39a1 100644 --- a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/RegistryXmlRepositoryTests.cs +++ b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/RegistryXmlRepositoryTests.cs @@ -125,7 +125,8 @@ public void StoreElements_ThenRetrieve_SeesAllElements() }); } - [Theory] + [ConditionalTheory] + [ConditionalRunTestOnlyIfHkcuRegistryAvailable] [InlineData(false, false)] [InlineData(false, true)] [InlineData(true, false)] @@ -180,10 +181,12 @@ public void DeleteElements(bool delete1, bool delete2) // but there's no obvious way to simulate a failure for only one of the values. You can // lock a whole key, but not individual values, and we don't have a hook to let us lock the // whole key while a particular value deletion is attempted. - //[Fact] + //[ConditionalFact] + //[ConditionalConditionalRunTestOnlyIfHkcuRegistryAvailable] //public void DeleteElementsWithFailure() - [Fact] + [ConditionalFact] + [ConditionalRunTestOnlyIfHkcuRegistryAvailable] public void DeleteElementsWithOutOfBandDeletion() { WithUniqueTempRegKey(regKey => From 8229f263327b6a1a5182d058d9ec93ff70a668da Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Wed, 17 Jul 2024 17:31:13 -0700 Subject: [PATCH 39/40] Skip DeleteElementsWithFailure on Linux The only way I could find to make FileSystemInfo.Delete throw was to remove write permission to the parent directory and we don't have enough hooks to do and undo that around a single file deletion attempt (i.e. it's all or none). --- .../Repositories/FileSystemXmlRepositoryTests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs index d3cbee13e847..09e446a1e7dd 100644 --- a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs +++ b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs @@ -189,7 +189,8 @@ public void DeleteElements(bool delete1, bool delete2) }); } - [Fact] + [ConditionalFact] + [OSSkipCondition(OperatingSystems.Linux, SkipReason = "Making FileSystemInfo.Delete throw on Linux is hard")] public void DeleteElementsWithFailure() { WithUniqueTempDirectory(dirInfo => From 1ad9807b6547fbbcbb972eaf68e540ba75df56ba Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Wed, 17 Jul 2024 22:18:17 -0700 Subject: [PATCH 40/40] Also skip on mac --- .../Repositories/FileSystemXmlRepositoryTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs index 09e446a1e7dd..036b1ed4596d 100644 --- a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs +++ b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests/Repositories/FileSystemXmlRepositoryTests.cs @@ -191,6 +191,7 @@ public void DeleteElements(bool delete1, bool delete2) [ConditionalFact] [OSSkipCondition(OperatingSystems.Linux, SkipReason = "Making FileSystemInfo.Delete throw on Linux is hard")] + [OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Making FileSystemInfo.Delete throw on macOS is hard")] public void DeleteElementsWithFailure() { WithUniqueTempDirectory(dirInfo =>