BugFree.Security.Key
1.1.2026.120-beta1028
See the version list below for details.
dotnet add package BugFree.Security.Key --version 1.1.2026.120-beta1028
NuGet\Install-Package BugFree.Security.Key -Version 1.1.2026.120-beta1028
<PackageReference Include="BugFree.Security.Key" Version="1.1.2026.120-beta1028" />
<PackageVersion Include="BugFree.Security.Key" Version="1.1.2026.120-beta1028" />
<PackageReference Include="BugFree.Security.Key" />
paket add BugFree.Security.Key --version 1.1.2026.120-beta1028
#r "nuget: BugFree.Security.Key, 1.1.2026.120-beta1028"
#:package BugFree.Security.Key@1.1.2026.120-beta1028
#addin nuget:?package=BugFree.Security.Key&version=1.1.2026.120-beta1028&prerelease
#tool nuget:?package=BugFree.Security.Key&version=1.1.2026.120-beta1028&prerelease
BugFree.Security.Key
企业级密钥全生命周期管理组件,支持对称和非对称密钥的存储、轮换和泄露检测
概述
BugFree.Security.Key 是 BugFree 框架的密钥管理组件,提供密钥的完整生命周期管理功能。采用完全委托模式,零依赖 BugFree.Security,专注于密钥的存储、轮换、访问控制和策略管理。
核心特性
- 🔐 全生命周期管理:密钥创建、存储、轮换、归档、销毁
- 🔄 自动轮换:基于时间、使用次数或策略的自动密钥轮换
- 💾 多种存储后端:文件存储(默认)、内存存储
- 📊 密钥版本控制:支持多版本密钥共存,加密用最新,解密用指定版本
- 🎯 完全委托模式:零依赖
BugFree.Security,算法实现由调用方提供 - 🚀 依赖注入友好:原生支持 Microsoft.Extensions.DependencyInjection
- 🔒 安全密钥句柄:
SafeKeyMaterialHandle确保密钥材料安全存储在非托管内存 - 🌐 跨平台支持:完全支持 Windows、Linux、macOS(.NET 8+)
目标框架
net8.0和net10.0多目标框架
设计理念
完全委托模式:本组件不依赖任何加密算法实现,密钥的生成完全由调用方通过委托提供。这使得组件可以与任何加密库(如 BugFree.Security、BouncyCastle、系统 API 等)无缝集成。
对称/非对称分离:v8.0 重构后,对称密钥和非对称密钥管理器完全分离,各自独立管理,提供更清晰的职责划分和类型安全。
架构设计
核心组件
BugFree.Security.Key
├── SymmetricKeyManager # 对称密钥管理器(ISymmetricKeyManager)
├── AsymmetricKeyManager # 非对称密钥管理器(IAsymmetricKeyManager)
├── SafeKeyMaterialHandle # 安全密钥材料句柄(非托管内存管理)
├── Abstractions/
│ ├── ISymmetricKeyManager # 对称密钥管理器接口
│ ├── IAsymmetricKeyManager # 非对称密钥管理器接口
│ ├── IKeyStore<T> # 泛型密钥存储接口
│ ├── IKeyResolver<T> # 泛型密钥解析器接口
│ ├── Delegate.cs # 委托类型定义
│ └── KeyStoreType # 存储类型枚举
├── Core/
│ ├── DefaultKeyResolver<T> # 默认密钥解析器实现
│ ├── DefaultSymmetricKeyRotator # 对称密钥轮换器
│ ├── DefaultAsymmetricKeyRotator # 非对称密钥轮换器
│ └── Store/
│ ├── FileKeyStore<T> # 文件存储实现(泛型)
│ └── MemoryKeyStore<T> # 内存存储实现(泛型)
├── Models/
│ ├── KeyRecord # 密钥记录基类
│ ├── SymmetricKeyRecord # 对称密钥记录(含 Key 属性)
│ ├── AsymmetricKeyRecord # 非对称密钥记录(含 PublicKey/PrivateKey 属性)
│ ├── KeyMetadata # 密钥元数据(不含密钥材料)
│ ├── KeyPolicy # 密钥策略
│ ├── KeyStatus # 密钥状态枚举
│ └── KeyPurpose # 密钥用途枚举
└── ServiceCollectionExtensions.cs # DI 扩展方法
设计模式
- 门面模式(Facade):
SymmetricKeyManager和AsymmetricKeyManager作为统一入口 - 策略模式(Strategy):通过泛型
IKeyStore<T>支持多种存储后端 - 委托模式(Delegate):密钥生成由调用方提供,实现零依赖
- 泛型设计:
IKeyStore<T>、IKeyResolver<T>等泛型接口提供类型安全 - 仓库模式(Repository):
IKeyStore<T>提供密钥持久化抽象
核心概念
密钥生命周期
创建 → Active(活跃) → DecryptOnly(仅解密,已轮换) → Retired(退役) → 销毁
↓
Compromised(已泄露) → 强制轮换
密钥状态(KeyStatus)
| 状态 | 说明 | 是否可用于加密/签名 | 是否可用于解密/验签 |
|---|---|---|---|
| Active | 活跃状态,当前使用的密钥 | ✅ 是 | ✅ 是 |
| DecryptOnly | 已轮换,仅用于解密历史数据 | ❌ 否 | ✅ 是 |
| Retired | 已退役,不再用于任何操作 | ❌ 否 | ❌ 否 |
| Compromised | 已泄露,必须立即轮换 | ❌ 否 | ⚠️ 谨慎使用 |
密钥用途(KeyPurpose)
| 用途 | 说明 | 推荐算法类型 | 允许的状态 |
|---|---|---|---|
| Encryption | 对称加密 | AES/AES-GCM | Active |
| Decryption | 对称解密(历史版本) | AES/AES-GCM | Active, DecryptOnly |
| Signing | 数字签名生成 | RSA/ECDSA/Ed25519 | Active |
| Verification | 签名验证(历史版本) | RSA/ECDSA/Ed25519 | Active, DecryptOnly |
密钥策略(KeyPolicy)
public class KeyPolicy
{
/// <summary>轮换间隔,默认 90 天</summary>
public TimeSpan RotationInterval { get; set; } = TimeSpan.FromDays(90);
/// <summary>最大使用次数,默认 1000 次</summary>
public Int32 MaxUsageCount { get; set; } = 1000;
/// <summary>过期日期,可选</summary>
public DateTime? ExpirationDate { get; set; }
/// <summary>是否启用自动轮换,默认 true</summary>
public Boolean EnableAutoRotation { get; set; } = true;
}
存储实现
| 存储类型 | 枚举值 | 适用场景 | 线程安全 | 持久化 |
|---|---|---|---|---|
| File | KeyStoreType.File |
生产环境(默认) | ✅ 是 | ✅ 是 |
| Memory | KeyStoreType.Memory |
开发/测试环境 | ✅ 是 | ❌ 否 |
文件存储(FileKeyStore<T>):
- 泛型设计,支持
SymmetricKeyRecord和AsymmetricKeyRecord - 每个
KeyId + Version对应一个 JSON 文件 - 文件命名规则:
{keyId}_v{version}.json - 默认存储目录:
AppContext.BaseDirectory/KeyStore - 支持自定义存储目录
- 使用内存缓存提高读取性能
安全密钥句柄(SafeKeyMaterialHandle)
跨平台安全:
- 完全支持 Windows、Linux、macOS
- 使用
Marshal.AllocHGlobal进行平台无关的内存分配 - 释放时自动清零内存,防止密钥泄露到内存转储中
- 继承
SafeHandleZeroOrMinusOneIsInvalid,确保确定性释放
零开销访问:
- 提供
DangerousGetSpan()方法返回ReadOnlySpan<Byte>(零拷贝) - 提供
DangerousGetMemory()方法返回ReadOnlyMemory<Byte>(数据副本) - 密钥存储在非托管内存中,避免 CLR 垃圾回收器的可见性
快速开始
基础用法
1. 配置密钥管理服务
using BugFree.Security.Key;
using BugFree.Security.Key.Abstractions;
using Microsoft.Extensions.DependencyInjection;
// 配置依赖注入
var services = new ServiceCollection();
// 注册对称密钥管理器
services.AddSymmetricKeyManagerCore(
keyGenerator: () =>
{
var algorithm = "AES-GCM";
var keySize = 32; // AES-256
using var rng = System.Security.Cryptography.RandomNumberGenerator.Create();
var key = new Byte[keySize];
rng.GetBytes(key);
return (algorithm, new ReadOnlyMemory<Byte>(key));
}
);
// 注册非对称密钥管理器
services.AddAsymmetricKeyManagerCore(
keyGenerator: () =>
{
// 使用 BugFree.Security 或其他库生成密钥对
var asymmetricService = AsymmetricService.Instance;
var keyPair = asymmetricService.GenerateKeyPair(KeyPairGeneratorProviderType.ECDSA);
return ("ECDSA", keyPair.PublicKey, keyPair.PrivateKey);
}
);
var serviceProvider = services.BuildServiceProvider();
var symmetricKeyManager = serviceProvider.GetRequiredService<ISymmetricKeyManager>();
var asymmetricKeyManager = serviceProvider.GetRequiredService<IAsymmetricKeyManager>();
2. 对称密钥加密/解密
// 加密数据(自动轮换,使用最新密钥)
var plaintext = Encoding.UTF8.GetBytes("Sensitive Data");
var encrypted = symmetricKeyManager.ResolveForKey(
keyId: "user-data-key",
handler: keySpan =>
{
// 使用 keySpan 加密数据
var algorithm = AesGcm.Create();
var nonce = new Byte[12];
var tag = new Byte[16];
var ciphertext = new Byte[plaintext.Length];
using var rng = RandomNumberGenerator.Create();
rng.GetBytes(nonce);
algorithm.Encrypt(nonce, plaintext, ciphertext, tag);
return (ciphertext, nonce, tag);
}
);
Console.WriteLine($"Encrypted successfully");
// 解密数据(指定密钥版本)
var decrypted = symmetricKeyManager.ResolveForKey(
keyId: "user-data-key",
version: encrypted.Version,
handler: keySpan =>
{
// 使用 keySpan 解密数据
var algorithm = AesGcm.Create();
var plaintext = new Byte[encrypted.Value.Ciphertext.Length];
algorithm.Decrypt(encrypted.Value.Nonce, encrypted.Value.Ciphertext, encrypted.Value.Tag, plaintext);
return plaintext;
}
);
Console.WriteLine($"Decrypted: {Encoding.UTF8.GetString(decrypted)}");
3. 非对称密钥签名/验签
// 签名数据(自动轮换,使用最新私钥)
var document = Encoding.UTF8.GetBytes("Important Document");
var signature = asymmetricKeyManager.ResolveForKey(
keyId: "signing-key",
handler: privateKeySpan =>
{
// 使用 privateKeySpan 签名数据
var asymmetricService = AsymmetricService.Instance;
return asymmetricService.Sign(
SignatureProviderType.ECDSA,
privateKeySpan,
document
);
},
isPublicKey: false // 使用私钥
);
Console.WriteLine($"Signed successfully");
// 验证签名(指定密钥版本,使用公钥)
var isValid = asymmetricKeyManager.ResolveForKey(
keyId: "signing-key",
version: signature.Version,
handler: publicKeySpan =>
{
// 使用 publicKeySpan 验证签名
var asymmetricService = AsymmetricService.Instance;
return asymmetricService.Verify(
SignatureProviderType.ECDSA,
publicKeySpan,
document,
signature.Value
);
},
isPublicKey: true // 使用公钥
);
Console.WriteLine($"Signature valid: {isValid}");
4. 密钥查询和管理
// 使用密钥存储接口查询密钥
// 注意:需要单独注入 IKeyStore<SymmetricKeyRecord> 或 IKeyStore<AsymmetricKeyRecord>
// 删除指定版本的密钥
symmetricKeyManager.Delete("user-data-key", version: 1);
// 删除密钥的所有版本
symmetricKeyManager.Delete("user-data-key");
高级用法
自定义密钥策略
// 使用自定义策略覆盖默认策略
var customPolicy = new KeyPolicy
{
RotationInterval = TimeSpan.FromDays(30),
MaxUsageCount = 100,
EnableAutoRotation = true
};
var result = symmetricKeyManager.ResolveForKey(
keyId: "my-key",
handler: keySpan =>
{
// 使用密钥
return EncryptData(keySpan);
},
policy: customPolicy // 覆盖默认策略
);
自定义密钥存储
using BugFree.Security.Key.Abstractions;
// 实现 IKeyStore<T> 接口
public class CustomKeyStore : IKeyStore<SymmetricKeyRecord>
{
public KeyStoreType StoreType => KeyStoreType.Custom;
public SymmetricKeyRecord? GetKey(String keyId, Int32 version)
{
// 从自定义存储中读取密钥
throw new NotImplementedException();
}
public SymmetricKeyRecord? GetLatestKey(String keyId)
{
// 获取最新版本的密钥
throw new NotImplementedException();
}
public KeyMetadata? GetMetadata(String keyId, Int32 version)
{
// 获取密钥元数据
throw new NotImplementedException();
}
public void Save(SymmetricKeyRecord key)
{
// 保存密钥到自定义后端
throw new NotImplementedException();
}
public void Delete(String keyId, Int32? version = null)
{
// 从自定义后端删除密钥
throw new NotImplementedException();
}
public IEnumerable<KeyMetadata> GetAllMetadata()
{
// 返回所有密钥的元数据
throw new NotImplementedException();
}
public void RemoveExpired(Func<KeyMetadata, Boolean> expired)
{
// 移除过期记录
throw new NotImplementedException();
}
}
// 使用自定义存储
services.AddSymmetricKeyManagerCore(
keyGenerator: () => ("AES", new ReadOnlyMemory<Byte>(GenerateKey())),
keyStore: new CustomKeyStore()
);
直接使用密钥管理器(不通过 DI)
// 不使用 DI,直接创建对称密钥管理器
var symmetricKeyManager = new SymmetricKeyManager(
keyGenerator: () => ("AES", new ReadOnlyMemory<Byte>(GenerateKey())),
keyStore: new FileKeyStore<SymmetricKeyRecord>("./custom-keys")
);
// 使用方式相同
var result = symmetricKeyManager.ResolveForKey(
"my-key",
keySpan => EncryptData(keySpan)
);
安全注意事项
密钥存储
- ✅ 文件存储:默认使用文件存储,密钥以 JSON 格式保存到磁盘
- ✅ 访问控制:确保密钥存储目录有正确的文件系统权限(仅允许应用程序访问)
- ✅ 生产环境:推荐使用专业密钥管理服务(HSM/KMS)
- ❌ 内存存储:仅用于开发和测试,不适用于生产环境(应用重启后丢失)
密钥轮换
- ✅ 定期轮换:推荐对称密钥 90 天,非对称密钥 180 天
- ✅ 使用次数限制:设置合理的
MaxUsageCount防止密钥过度使用 - ✅ 平滑轮换:新密钥用于加密,旧密钥保留用于解密历史数据
- ⚠️ 归档策略:制定密钥归档和销毁策略
- ⚠️ 保留期限:旧密钥必须保留足够长时间以解密历史数据
密钥访问
- ✅ 最小权限:仅授予必要的密钥访问权限
- ✅ 密钥分离:加密密钥和签名密钥分离使用
- ✅ 委托模式:使用
KeyHandler<T>委托确保密钥材料的安全访问 - ❌ 日志记录:禁止在日志中输出密钥材料
- ❌ 异常处理:密钥访问异常不应泄露密钥信息
密钥生成
- ✅ 强随机数:使用
RandomNumberGenerator或RandomNumberGenerator.GetBytes生成密钥 - ✅ 密钥长度:AES 推荐 256 位(32 字节),RSA 推荐 2048 位以上
- ✅ 算法选择:优先使用 AES-GCM、ECDSA、Ed25519 等现代算法
- ✅ 唯一性:每个密钥 ID 应该有唯一且描述性的名称
跨平台安全
- ✅ SafeKeyMaterialHandle:使用安全句柄管理非托管内存中的密钥材料
- ✅ 自动清零:句柄释放时自动清零内存,防止内存转储泄露
- ✅ 零拷贝访问:通过
DangerousGetSpan()提供零开销的只读访问 - ⚠️ 句柄生命周期:调用者必须确保在使用期间不释放句柄
最佳实践
1. 密钥命名规范
// 好的命名(包含用途和环境)
"user-data-encryption-prod"
"api-signing-key-staging"
"session-key-cache"
"database-encryption-primary"
// 避免的命名(过于简单或含糊)
"key1"
"test"
"my-key"
"encryption"
2. 密钥策略配置
// 生产环境策略
var productionPolicy = new KeyPolicy
{
RotationInterval = TimeSpan.FromDays(90),
MaxUsageCount = 1000,
EnableAutoRotation = true,
ExpirationDate = DateTime.UtcNow.AddYears(1)
};
// 开发环境策略
var developmentPolicy = new KeyPolicy
{
#if DEBUG
RotationInterval = TimeSpan.FromSeconds(10), // 便于测试
#else
RotationInterval = TimeSpan.FromDays(90),
#endif
MaxUsageCount = 10000, // 宽松限制
EnableAutoRotation = true
};
// 高安全场景策略
var highSecurityPolicy = new KeyPolicy
{
RotationInterval = TimeSpan.FromDays(30), // 更短的轮换周期
MaxUsageCount = 100, // 更严格的使用限制
EnableAutoRotation = true,
ExpirationDate = DateTime.UtcNow.AddMonths(6)
};
3. 密钥生命周期管理
// 1. 加密数据(自动使用最新密钥)
var (ciphertext, nonce, tag) = symmetricKeyManager.ResolveForKey(
"my-encryption-key",
keySpan =>
{
var algorithm = AesGcm.Create();
var nonceBytes = new Byte[12];
var tagBytes = new Byte[16];
var ciphertextBytes = new Byte[data.Length];
using var rng = RandomNumberGenerator.Create();
rng.GetBytes(nonceBytes);
algorithm.Encrypt(nonceBytes, data, ciphertextBytes, tagBytes);
return (ciphertextBytes, nonceBytes, tagBytes);
}
);
// 2. 保存密钥版本号(与密文一起)
SaveToDatabase(ciphertext, nonce, tag, keyVersion: 1);
// 3. 解密时使用相同版本
var plaintext = symmetricKeyManager.ResolveForKey(
"my-encryption-key",
version: keyVersion,
keySpan =>
{
var algorithm = AesGcm.Create();
var plaintextBytes = new Byte[ciphertext.Length];
algorithm.Decrypt(nonce, ciphertext, tag, plaintextBytes);
return plaintextBytes;
}
);
// 4. 删除过期密钥(当确定不再需要时)
symmetricKeyManager.Delete("my-encryption-key", version: 1);
4. 错误处理
try
{
var result = symmetricKeyManager.ResolveForKey(
"my-key",
keySpan => EncryptData(keySpan)
);
}
catch (ArgumentNullException ex)
{
// 密钥 ID 为空
logger.LogError($"Invalid key ID: {ex.Message}");
}
catch (Exception ex) when (ex.Message.Contains("Key not found"))
{
// 密钥不存在(首次使用会自动创建)
logger.LogWarning($"Key will be created automatically");
}
catch (Exception ex)
{
// 其他错误(如密钥访问失败)
logger.LogError($"Key operation failed: {ex.Message}");
throw;
}
API 参考
SymmetricKeyManager
public sealed class SymmetricKeyManager : ISymmetricKeyManager
{
// 获取默认密钥策略
public KeyPolicy DefaultPolicy { get; }
// 获取密钥生成委托
public SymmetricKeyGeneratorDelegate KeyGenerator { get; }
// 删除密钥
public void Delete(String keyId, Int32? version = null);
// 使用密钥执行操作(自动轮换,使用最新版本)
public T ResolveForKey<T>(String keyId, KeyHandler<T> handler, KeyPolicy? policy = null);
// 使用指定版本的密钥执行操作
public T ResolveForKey<T>(String keyId, Int32 version, KeyHandler<T> handler);
}
AsymmetricKeyManager
public sealed class AsymmetricKeyManager : IAsymmetricKeyManager
{
// 获取默认密钥策略
public KeyPolicy DefaultPolicy { get; }
// 获取密钥生成委托
public AsymmetricKeyGeneratorDelegate KeyGenerator { get; }
// 删除密钥
public void Delete(String keyId, Int32? version = null);
// 使用密钥执行操作(自动轮换,使用最新版本)
public T ResolveForKey<T>(String keyId, KeyHandler<T> handler, Boolean isPublicKey, KeyPolicy? policy = null);
// 使用指定版本的密钥执行操作
public T ResolveForKey<T>(String keyId, Int32 version, KeyHandler<T> handler, Boolean isPublicKey);
}
SafeKeyMaterialHandle
public sealed class SafeKeyMaterialHandle : SafeHandleZeroOrMinusOneIsInvalid
{
// 非托管内存指针
IntPtr _memory;
// 密钥数据的长度(字节)
Int32 _length;
// 获取密钥的 ReadOnlySpan<Byte> 视图(零开销)
public ReadOnlySpan<Byte> DangerousGetSpan();
// 获取密钥的 ReadOnlyMemory<Byte> 视图
public ReadOnlyMemory<Byte> DangerousGetMemory();
// 获取密钥数据的长度(字节)
public Int32 Length { get; }
// 获取一个值,指示密钥数据是否为空
public Boolean IsEmpty { get; }
// 释放句柄关联的非托管内存
protected override Boolean ReleaseHandle();
}
依赖项
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.0" />
外部依赖说明
- Microsoft.Extensions.DependencyInjection.Abstractions:依赖注入抽象
- Microsoft.Extensions.Options:选项模式支持
- 零 BugFree.Security 依赖:密钥生成完全由调用方提供(委托模式)
版本历史
v8.0(当前版本)
重大重构:
- ✅ 对称和非对称密钥管理器完全分离
- ✅ 泛型化的
IKeyStore<T>接口 - ✅ 分离的
SymmetricKeyRecord和AsymmetricKeyRecord - ✅ 新增
SafeKeyMaterialHandle安全密钥句柄 - ✅ 跨平台支持(Windows、Linux、macOS)
- ✅ 委托模式优化,使用
KeyHandler<T>确保密钥安全访问
破坏性变更:
KeyManager拆分为SymmetricKeyManager和AsymmetricKeyManagerEnsureFreshSymmetricKey和EnsureFreshAsymmetricKey方法移除,使用ResolveForKey替代ResolveForEncryption、ResolveForDecryption、ResolveForSigning、ResolveForVerification方法移除,统一使用ResolveForKey- DI 注册方法改为
AddSymmetricKeyManagerCore和AddAsymmetricKeyManagerCore
迁移指南:
// 旧版本(v7.x)
var keyRecord = keyManager.EnsureFreshSymmetricKey("my-key", () => ("AES", key));
var encryptionKey = keyManager.ResolveForEncryption("my-key");
// 新版本(v8.0)
var result = symmetricKeyManager.ResolveForKey("my-key", keySpan => EncryptData(keySpan));
路线图
| 功能 | 当前状态 | 计划 |
|---|---|---|
| 文件存储 | ✅ 已实现 | 优化加密性能 |
| 内存存储 | ✅ 已实现 | 增加缓存策略 |
| SafeKeyMaterialHandle | ✅ 已实现 | 跨平台验证 |
| Azure Key Vault | ❌ 未实现 | 计划支持 |
| AWS KMS | ❌ 未实现 | 计划支持 |
| HashiCorp Vault | ❌ 未实现 | 计划支持 |
| 密钥导入/导出 | ❌ 未实现 | 计划支持 |
| 密钥备份/恢复 | ❌ 未实现 | 计划支持 |
| 密钥权限管理 | ❌ 未实现 | 计划支持 RBAC |
| 访问日志审计 | ❌ 未实现 | 计划支持 |
相关组件
- BugFree.Security:安全加密组件库
- BugFree.Core:核心平台抽象和工具
贡献指南
- 提交 PR 前请确保添加相应的单元测试
- 若扩展
IKeyStore<T>,请提供完整的文档和示例 - 密钥存储实现必须考虑线程安全性
- 遵循现有的代码风格和命名规范
许可证
本项目遵循 BugFree 框架的许可证。
联系方式
如有问题或建议,请联系邮箱:ligengrong@hotmail.com
最后更新: 2026-01-20 版本: 1.1.2026.120 目标框架: net8.0;net10.0 依赖: 零依赖 BugFree.Security(完全委托模式) 跨平台: Windows、Linux、macOS
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.0)
- Microsoft.Extensions.Options (>= 10.0.0)
-
net8.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.0)
- Microsoft.Extensions.Options (>= 10.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.1.2026.121-beta1051 | 205 | 1/21/2026 |
| 1.1.2026.120-beta1330 | 73 | 1/20/2026 |
| 1.1.2026.120-beta1028 | 73 | 1/20/2026 |
| 1.1.2026.118-beta1029 | 100 | 1/18/2026 |