在 .NET 中加载椭圆曲线 (EC) 密钥
在 .NET 中加载椭圆曲线 (EC) 密钥
本文将讨论在.NET 中解析和加载EC 密钥的不同方式。在本文中,您将了解 EC 密钥的构成,然后了解如何以四种不同的方式使用这些知识ECDsa
在 .NET 中加载或创建对象。到本文结束时,您应该能够加载 EC 密钥,无论格式如何。
本文针对 .NET Core 3.1 及更高版本。
椭圆曲线 (EC) 密钥的参数
加载 EC 密钥时,您将需要了解三件事:
1.私钥(可选)2.公钥3.您需要使用的曲线
私钥d是一个随机整数,其长度取决于您使用的曲线。如果你有私钥,你就可以对数据进行签名。
公钥是椭圆曲线上的一个点,使用坐标x&y。因此,公钥特定于该曲线,并使用私钥乘以曲线上的生成点G生成。使用公钥,您将能够验证签名。
这表明您需要了解正在使用的椭圆曲线(例如,NIST 的 P-256[1]或secp256k1[2])才能使用椭圆曲线加密 (ECC)。如果不知道曲线,您将不知道私钥应该有多长、提供的安全级别或公钥是否有效(如果它们是曲线上的点)。
如果您想了解有关椭圆曲线密码学工作原理的更多信息,我发现开发人员实用密码学[3]是一本有用的读物。
.NET 的ECDsa对象
.NET 对 ECDSA 的抽象是ECDsa
在System.Security.Cryptography
. 这继承AsymmetricAlgorithm
并遵循RSA
您之前可能使用过的类的类似模式。 ECDsa
是一个抽象类,具有使用不同实现的各种平台(例如,Windows 上的 CNG 和 Linux 上的 OpenSSL)。
此类的主要用途是调用SignData
和VerifyData
方法。否则,您可能会将其传递到SecurityKey 实现[4]或 SignedXml。
本文的其余部分将重点介绍如何创建ECDsa
实现。
使用ECDsa和命名曲线生成 EC 密钥
创建新 EC 密钥的最简单方法是使用 .NETCreate
上的方法让 .NET 为您完成ECDsa
。这将在您选择的曲线上创建一个私钥。您通常会使用已知的命名曲线,例如 NIST 的 P-256,又名 secp256r1。您可以在ECCurve.NamedCurve
课程中找到 .NET 支持的开箱即用曲线。
ECDsa key = ECDsa.Create(ECCurve.NamedCurves.nistP256);
这种方法非常适合在测试期间即时生成密钥,但是一旦对象被处置,您就会丢失密钥。幸运的是,您可以使用各种导出方法ECDsa
;否则,您可以使用该ExportParameters
方法直接访问 EC 参数。这些导出方法使您可以访问ECParameters
包含关键点曲线、D 和 Q ( x & y ) 点的对象,您将在接下来的操作中看到这些点。
创建ECDSA使用为ECParameters
假设您已经收到曲线的原始点,并且您需要以这种方式加载密钥。这在使用 JSON Web Keys (JWK) 和OpenID Connect[5]时很常见。
这是来自 RFC 7517 的 JWK 示例:
{"kty": "EC","crv": "P-256","x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU","y": "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0","kid": "my EC key"
}
要加载密钥,您需要知道密钥使用什么曲线以及公钥参数(x和y坐标)。也可以使用d参数将私钥包含在 JWK 中;然而,这种情况很少见。
您可以再次使用ECDsa
的Create
方法加载这些坐标,但这次您将传入一些ECParameters
.
// parse curve from JOSE format
// https://www.iana.org/assignments/jose/jose.xhtml#web-key-elliptic-curve
var curve = crv switch
{"P-256" => ECCurve.NamedCurves.nistP256,"P-384" => ECCurve.NamedCurves.nistP384,"P-521" => ECCurve.NamedCurves.nistP521,_ => throw new NotSupportedException()
};ECDsa key = ECDsa.Create(new ECParameters
{Curve = curve,D = Base64UrlEncoder.DecodeBytes(d), // optionalQ = new ECPoint{X = Base64UrlEncoder.DecodeBytes(x),Y = Base64UrlEncoder.DecodeBytes(y)}
});
在这里,您正在解析 JOSE 名称中的曲线,并使用 中找到的编码器对其他参数进行 base64url 解码Microsoft.IdentityModel.Tokens
。
此解析特定于 JWK 使用的格式,但它演示了如何在知道其参数的情况下加载 EC 密钥。
有一种Validate
方法ECParameters
可以检查关键和坐标大小并检查曲线是否有效。但是,Create
on的方法ECDsa
会为您调用它。
如果您确实有 JWK 并打算使用它来验证 JWT,我建议将 JWK 直接传递到构造函数中Microsoft.IdentityModel.Tokens.JsonWebKey
并跳过我在上面演示的手动解析。
从X509Certificate2加载ECDsa
从 an 加载 EC 密钥X509Certificate2
是简单使用GetECDsaPrivateKey
和GetECDsaPublicKey
方法的一种情况。
ECDsa key = cert.HasPrivateKey ? cert.GetECDsaPrivateKey() : cert.GetECDsaPublicKey();
为了首先加载X509Certificate2
,您可以从 PEM 文件加载它[6]。
X509Certificate2.PrivateKey与GetRSAPrivateKey和GetECDsaPrivateKey
过去,您可能在 上使用了PrivateKey
和PublicKey
属性X509Certificate2
。但是,如果您尝试在包含 EC 密钥的证书上使用这些属性,您将获得 null forPrivateKey
和以下异常PublicKey
:
System.NotSupportedException: 不支持证书密钥算法。在 System.Security.Cryptography.X509Certificates.PublicKey.get_Key()
要使用来自 X.509 的 EC 密钥,您需要使用GetECDsaPrivateKey
和GetECDsaPublicKey
方法。
从 .NET 6 开始,PrivateKey
和PublicKey
属性被标记为过时。因此,您必须使用RSA
和ECDsa
特定方法来全面加载密钥。
从十六进制字符串加载ECDsa
有时,您会看到 EC 密钥作为十六进制字符串共享。这在加密社区中很常见,我的意思是密码学和加密货币。我不能说它在密码学中是否有很大用处。这些键看起来像这样:
Private: c711e5080f2b58260fe19741a7913e8301c1128ec8e80b8009406e5047e6e1ef
Public: 04e33993f0210a4973a94c26667007d1b56fe886e8b3c2afdd66aa9e4937478ad20acfbdc666e3cec3510ce85d40365fc2045e5adb7e675198cf57c6638efa1bdb
这些键起初可能看起来有点奇怪,但它们实际上映射回您已经使用的参数。私钥只是d参数的十六进制表示,公钥是连接在一起的x &y坐标(第一个字节是标签)。
因此,您可以再次使用ECParameters
来创建您的ECDsa
对象:
public static ECDsa LoadFromHex()
{var privateKeyBytes = FromHexString("c711e5080f2b58260fe19741a7913e8301c1128ec8e80b8009406e5047e6e1ef");var publicKeyBytes = FromHexString("04e33993f0210a4973a94c26667007d1b56fe886e8b3c2afdd66aa9e4937478ad20acfbdc666e3cec3510ce85d40365fc2045e5adb7e675198cf57c6638efa1bdb");return ECDsa.Create(new ECParameters{Curve = ECCurve.NamedCurves.nistP256, // you'd need to know the curve before handD = privateKeyBytes,Q = new ECPoint{X = publicKeyBytes.Skip(1).Take(32).ToArray(),Y = publicKeyBytes.Skip(33).ToArray()}});
}private static byte[] FromHexString(string hex) {var numberChars = hex.Length;var hexAsBytes = new byte[numberChars / 2];for (var i = 0; i < numberChars; i += 2)hexAsBytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);return hexAsBytes;
}
源代码
您可以在我的GitHub 示例存储库中[7]找到演示上述方法的可执行代码。此代码是多目标 .NET Core 3.1 及以上版本,可在 Windows 和 Linux 上运行。
查看原文:https://www.scottbrady91.com/c-sharp/ecdsa-key-loading
References
[1]
NIST 的 P-256: https://www.scottbrady91.com/C-Sharp/JWT-Signing-using-ECDSA-in-dotnet-Core
[2]
secp256k1: https://www.scottbrady91.com/C-Sharp/Supporting-Custom-JWT-Signing-Algorithms-in-dotnet-Core
[3]
开发人员实用密码学: https://cryptobook.nakov.com/asymmetric-key-ciphers/elliptic-curve-cryptography-ecc
[4]
SecurityKey 实现: https://www.scottbrady91.com/C-Sharp/JWT-Signing-using-ECDSA-in-dotnet-Core
[5]
OpenID Connect: https://www.scottbrady91.com/OpenID-Connect/OpenID-Connect-Overview
[6]
从 PEM 文件加载它: https://www.scottbrady91.com/C-Sharp/PEM-Loading-in-dotnet-core-and-dotnet
[7]
GitHub 示例存储库中: https://github.com/scottbrady91/Blog-Example-Classes/tree/master/EcdsaKeyLoading
在 .NET 中加载椭圆曲线 (EC) 密钥相关推荐
- 在C++中加载TorchScript模型
在C++中加载TorchScript模型 本教程已更新为可与PyTorch 1.2一起使用 顾名思义,PyTorch的主要接口是Python编程语言.尽管Python是合适于许多需要动态性和易于迭代的 ...
- xBIM 实战01 在浏览器中加载IFC模型文件
系列目录 [已更新最新开发文章,点击查看详细] 一.创建Web项目 打开VS,新建Web项目,选择 .NET Framework 4.5 选择一个空的项目 新建完成后,项目结构如下: 二.添 ...
- Spring中加载xml配置文件的六种方式
Spring中加载xml配置文件的六种方式 博客分类: Spring&EJB XMLSpringWebBeanBlog 因为目前正在从事一个项目,项目中一个需求就是所有的功能都是插件的形式装 ...
- 如何在Author中加载SDE栅格图层?
如何在Author中加载SDE栅格图层? 版本: ArcIMS 9.1 在Author中加载SDE栅格图层,并保存AXL文件. 过程描述 1.使用ArcIMS Author工具正常的连接ArcSDE ...
- 如何找出R中加载的软件包版本?
本文翻译自:How to find out which package version is loaded in R? I am in a process of figuring out how to ...
- pyharm虚拟环境_手把手教你如何在Pycharm中加载和使用虚拟环境
/1 前言/ 上次小编给大家介绍了Python虚拟环境及其使用和操作教程,没来得及上车的小伙伴,可以戳这个文章进行阅览.这篇文章基于虚拟环境的搭建,也相对比较基础,主要是介绍如何在Pycharm中加载 ...
- Activity中加载器的总结
继续总结加载器 加载器可以支持在Activity或片段中异步加载数据,加载器具有以下特征: 可用于每个Activity和Fragment: 支持异步加载数据: 监控其数据源并在内容变化时传递新结果: ...
- webpack 中的加载器简介||webpack 中加载器的基本使用——1. 打包处理 css 文件 2. 打包处理 less 文件 3.打包处理 scss 文件
webpack 中的加载器 1. 通过 loader 打包非 js 模块 在实际开发过程中,webpack 默认只能打包处理以 .js 后缀名结尾的模块,其他非 .js 后缀名结尾的模块, webpa ...
- 通过超图在网页中加载3dmax模型
接此: https://blog.csdn.net/bcbobo21cn/article/details/116806866 在场景中加载了3dmax模型后,保存场景: 场景节点下面出来一个场景: 保 ...
最新文章
- 不能成为专业软件测试人员的10大理由
- 参会邀请 | “新时代与新范式:新兴交叉学科的研究议程与发展路径”——第三届全国计算社会科学高端论坛...
- linux ifconfig命令配置ip地址
- python回顾(四)——面向对象
- 2.3.3 Softmax回归介绍
- CS这么难申,小哥哥你怎么拿到全美最高额度奖学金的?
- Vista新特征(Features)(英文)
- 自制H3C交换机CONSOLE线
- mui switch 实现方案 让你的html 设计更贴近原生
- 学英语---(2)脱口而出100句经典英语口语
- 数据库服务的安装,启动,关闭
- 配置实体框架DbContext的可扩展方案
- java jlabel 字体大小_java – 如何在调整大小时更改JLabel字体大小以填充JPanel可用空间?...
- numpy教程:numpy基本数据类型及多维数组元素存取
- Java JVM调优
- Ubuntu22.04运行网易云音乐错误
- 【pyqt5学习】——pyqt5中.qrc资源文件的创建与编写
- SetWindowsHookEx 全局钩子
- 使用导入 Excel 的方式批量修改文件名称及文件扩展名
- 资源池、虚拟机、集群的关系