删除数据库中所有Data Protection密钥后解密仍生效的原因?
为何删除数据库中所有.NET Data Protection密钥后仍能解密?
我在项目中使用.NET Data Protection组件,相关代码如下:
初始化密钥代码
ServiceProvider services; private void InitializeKeys() { var serviceCollection = new ServiceCollection(); serviceCollection.AddDbContext<MyContext>(); serviceCollection.AddDataProtection().SetDefaultKeyLifetime(TimeSpan.FromDays(14)).PersistKeysToDbContext<MyContext>(); services = serviceCollection.BuildServiceProvider(); services.GetDataProtector("MyClass.v1").Protect("payload"); }
MyContext代码
public class MyContext : DbContext, IDataProtectionKeyContext { public MyContext() { } public MyContext(DbContextOptions<MyContext> options) : base(options) { } public DbSet<DataProtectionKey> DataProtectionKeys { get; set; } = null!; protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer("Server=.;Database=ThisIsMyDB;Trusted_Connection=True;TrustServerCertificate=True"); } }
运行项目后,数据库中成功生成一个密钥,且加密操作完成。最初的加密代码如下:
var Provider = DataProtectionProvider.Create("MyClass.v1"); IDataProtector _protector = Provider.CreateProtector("MyClass.v1"); txtEncryptResult.Text = _protector.Protect(txtEncryptValue.Text);
随后我停止运行的应用,并删除了数据库中的所有密钥,但使用以下解密代码仍能成功解密之前得到的加密值:
var Provider = DataProtectionProvider.Create("MyClass.v1"); IDataProtector _protector = Provider.CreateProtector("MyClass.v1"); txtDecryptResult.Text = _protector.Unprotect(txtDecryptValue.Text);
请问为何删除所有密钥后解密仍能正常工作?
编辑1
根据@Dai的回答,我更新了加密代码,目前运行正常:
var Provider = services.GetDataProtector("MyClass.v1"); IDataProtector _protector = Provider.CreateProtector("MyClass.v1"); txtEncryptResult.Text = _protector.Protect(txtEncryptValue.Text);
问题原因分析
核心问题是加密操作并未使用你配置了数据库密钥持久化的Data Protection实例:
- 你的
InitializeKeys方法确实配置了将密钥持久化到数据库的Data Protection服务,但最初的加密代码通过DataProtectionProvider.Create("MyClass.v1")创建了一个全新的独立实例。 - 这个默认创建的实例不会复用DI容器中配置的数据库持久化逻辑,而是使用.NET Data Protection的默认密钥存储位置(对于桌面应用,通常是用户目录下的
AppData\Local\ASP.NET\DataProtection-Keys文件夹,而非你指定的数据库)。 - 因此你之前的加密值实际是用本地文件系统中的密钥加密的,删除数据库密钥自然不会影响解密——因为解密时用的还是本地存储的那套密钥。
修正后的代码说明
你在编辑1中更新的代码改为从DI容器中获取IDataProtector实例,这才真正使用了你配置的、密钥持久化到数据库的Data Protection服务。此时如果删除数据库中的密钥,解密操作就会失败,符合预期。
内容的提问来源于stack exchange,提问作者DooDoo
相关产品推荐
相关产品推荐

