如何从 ECDsa 或 ECDsaCng 对象中提取文本私钥和公钥?

Has*_*ena 2 .net c# cryptography ecdsa .net-6.0

创建 ECDSA 对象并尝试提取私钥和公钥对象时,它会返回一个byte[]. 但是当尝试将其转换为字符串时,它给出的输出看起来不正确。

// Creating the object with default parameters
ECDsa ecdSa = ECDsa.Create(ECCurve.NamedCurves.nistP256);

// Export parameters
ECParameters ecParamters = ecdSa.ExportParameters(true);

// Private Key
byte[] privateKey = ecParamters.D;

// Public key params
ECPoint publicKey = ecParamters.Q;

// Coordinates
byte[] publicKeyX = publicKey.X; // What format? int, double, etc
byte[] publicKeyY = publicKey.Y; // What format? int, double, etc
Run Code Online (Sandbox Code Playgroud)

上面提供了对,和 的ECParameters访问。curveD (private key)Q (public key)

知道这些字节数组中使用了哪种格式吗?我们如何将其转换为字符串格式,例如:私钥和公钥到PKCS#8

Top*_*aco 6

D 就是私钥,X 和 Y 是公钥raw的两个坐标。raw对于 P-256,每个都是 32 个字节。

自 .NET Core 3.0 起,支持直接导出 PKCS#8 格式 ( ExportPkcs8PrivateKey()) 和 SEC1 格式 ( ExportECPrivateKey()) 的 ECDSA 私钥以及 X.509 格式 ( ExportSubjectPublicKeyInfo()) 的 ECDSA 公钥。ExportParameters()无需绕道!导出的密钥采用 DER 编码。

例子:

ECDsa ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP256);

byte[] privatePkcs8Der = ecdsa.ExportPkcs8PrivateKey();
byte[] privateSec1Der = ecdsa.ExportECPrivateKey();
byte[] publicX509Der = ecdsa.ExportSubjectPublicKeyInfo();
Run Code Online (Sandbox Code Playgroud)

从 DER 到 PEM 编码的转换很简单:Base64 编码,每 64 个字符后插入一个换行符,并添加特定于格式的页眉和页脚。或者,您可以使用 BouncyCastle(例如,通过 PKCS#8 Org.BouncyCastle.Utilities.IO.Pem.PemWriter):

using Org.BouncyCastle.Utilities.IO.Pem;
using System.IO;
...
StringWriter stringWriter = new StringWriter();
PemWriter pemWriter = new PemWriter(stringWriter);
pemWriter.WriteObject((PemObjectGenerator)new PemObject("PRIVATE KEY", privatePkcs8Der)); // SEC1: EC PRIVATE KEY, X.509: PUBLIC KEY
Console.WriteLine(stringWriter.ToString());
Run Code Online (Sandbox Code Playgroud)

从 .NET 5 开始,也直接支持PEM 编码,但仅限于导入:ImportFromPem().

请注意,ECDH 和 RSA 密钥也存在类似的支持。

  • .NET 7 预览版已经内置了 PEM 导出(例如 ExportSubjectPublicKeyInfoPem)。我们还有一个内置的 PEM 读取器/写入器,我们称之为 PemEncoding (.NET 5+) (3认同)