C# 中可重现的椭圆曲线数字签名算法参数

问题描述 投票:0回答:1

使用以下代码,我可以生成椭圆曲线数字签名算法(ECDSA)参数(即公钥和私钥)。

using var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP384);
var publicKey = ecdsa.ExportParameters(false);
var privateKey = ecdsa.ExportParameters(true);

此方法每次都会生成新的密钥,这对于许多应用程序来说是正确的选择。但是,在我的应用程序中,我需要能够修复随机种子以获得可重现的密钥。

我有两个要求:

  • 仅使用内置方法;
  • 跨平台支持。

关于如何生成可复制密钥有什么建议吗?

c# .net cryptography ecdsa elliptic-curve
1个回答
0
投票

原始 EC 私钥是随机字节序列,例如对于由 48 个字节组成的 P-384。与对称密钥的密钥派生类似,密钥派生函数可用于根据给定的密钥材料确定相同的原始私钥。
如果密钥材料是熵不足的密码,则应将基于密码的密钥派生函数(例如 PBKDF2)与(非秘密)随机盐结合使用。然后可以使用密码和盐重建原始私钥。
如果密钥材料具有足够的熵,则可以使用基于哈希的密钥派生函数 (HKDF)(请参阅RFC 5869)。 NET 从 .NET 5 开始为此提供了实现,请参阅

HKDF

公钥(或相应的

ECPoint
)是通过将原始私钥乘以相应曲线的生成点而获得的。但是,没有必要直接确定公钥,因为 .NET 在幕后隐式确定它(如果由于某种原因需要直接确定:据我所知,.NET 不公开模块化算术的公共方法,这意味着必须使用其他库(例如 BouncyCastle)来直接从原始私钥确定原始公钥)。 根据问题,由于密钥材料具有足够的熵,因此以下是 HKDF 的示例实现。这不需要任何额外的库并且可以跨平台工作:

private static ECDsa CreateKeyViaHKDF(byte[] keyMaterial, ECCurve ecCurve, int size) { ECParameters ecp = new ECParameters(); ecp.Curve = ecCurve; ecp.D = HKDF.DeriveKey(HashAlgorithmName.SHA512, keyMaterial, size, null, null); return ECDsa.Create(ecp); }

测试:

using System; using System.Security.Cryptography; ... byte[] keyMaterial = Convert.FromHexString("d25a4ea14eb6ad223393fd84ab59a62ea9740057f1249ebd65074866e2192af77ca6f78bae94c329b8adaf5d344f1c55c6d20f04abe7de53b08d93e89d8820ae"); // keyMaterial with sufficient entropy ECDsa key = CreateKeyViaHKDF(keyMaterial, ECCurve.NamedCurves.nistP384, 48); // Export raw private/public key ECParameters privateKey = key.ExportParameters(true); ECParameters publicKey = key.ExportParameters(false); Console.WriteLine("Private key (raw, Base64): " + Convert.ToBase64String(privateKey.D)); Console.WriteLine("Public key, X (raw, Base64): " + Convert.ToBase64String(publicKey.Q.X)); Console.WriteLine("Public key, Y (raw, Base64): " + Convert.ToBase64String(publicKey.Q.Y)); // Export keys in PKCS#8 (private key) and SPKI (public key) format Console.WriteLine("\nPrivate key (PKCS#8): " + key.ExportPkcs8PrivateKeyPem()); Console.WriteLine("\nPublic key (SPKI): " + key.ExportSubjectPublicKeyInfoPem());

© www.soinside.com 2019 - 2024. All rights reserved.