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

How to extract the text private and public key from ECDsa or ECDsaCng object?

创建 ECDSA 对象并尝试提取私有和 public 密钥对象时 returns 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

以上 ECParameters 可以访问 curveD (private key)Q (public key)

知道这些字节数组中使用的是哪种格式吗?我们如何将其转换为字符串格式,例如:private and public keys to PKCS#8?

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

自 .NET Core 3.0 起,直接 以 PKCS#8 格式 (ExportPkcs8PrivateKey()) and SEC1 format (ExportECPrivateKey()) is supported and of public ECDSA keys in X.509 format (ExportSubjectPublicKeyInfo()) 导出私有 ECDSA 密钥。没有必要绕道ExportParameters()!导出的密钥是 DER 编码的。

示例:

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

byte[] privatePkcs8Der = ecdsa.ExportPkcs8PrivateKey();
byte[] privateSec1Der = ecdsa.ExportECPrivateKey();
byte[] publicX509Der = ecdsa.ExportSubjectPublicKeyInfo();

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

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());

自 .NET 5 起,PEM 编码也直接 支持,但仅用于导入:ImportFromPem().

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