【问题标题】:Import an OpenSSL ECDSA PEM private key and sign it导入 OpenSSL ECDSA PEM 私钥并签名
【发布时间】:2021-11-07 03:42:09
【问题描述】:

要使用 OpenSSL 生成私钥和公钥,我已经运行

openssl ecparam -genkey -name secp256k1 -out private-key.pem
openssl ec -in private-key.pem -out public-key.pem -pubout

我将公钥上传到远程服务器。然后将private-key.pem 导入到 .Net Framework(必须是 .Net Framework)C# 服务以使用它来签署 API 有效负载:

public string LoadFromCng(byte[] request, string privateKeyFile)
{
    CngKey cng = CngKey.Open(privateKeyFile);

    // Sign the request body with the private key.
    ECDsaCng dsa = new ECDsaCng(cng);
    byte[] signedRequest = dsa.SignData(request, HashAlgorithmName.SHA256);
    return Convert.ToBase64String(signedRequest);
}

使用privateKeyFile = private-key.pem,上面的代码给出Keyset does not exist

如果我使用mkcert 并运行mkcert -ecdsa -pkcs12 private-key.pem,它会生成一个名为private-key.pem.p12 的PKCS#12 密钥,然后:

public string LoadFromX509(byte[] request, string privateKeyFile)
{
    var cert = new X509Certificate2(privateKeyFile, "changeit");
    var key = cert.GetECDsaPrivateKey();
    byte[] signedRequest = key.SignData(request, HashAlgorithmName.SHA256);
    return Convert.ToBase64String(signedRequest);
}

使用privateKeyFile = private-key.pem.p12,上面的代码似乎对请求进行了签名,但API 响应是The remote server returned an error: (400) Bad Request,这意味着API 提供者无法解码来自public key 的有效负载。

在查看cheat sheet here 并创建 X509 pfx 证书时,我遇到了同样的 400 错误。

openssl req -new -x509 -key private-key.pem -out cert.pem -days 360
openssl pkcs12 -export -inkey private-key.pem -in cert.pem -out cert.pfx

上述方法似乎对负载进行了签名,但提供者以 400 响应。

herehereherehere 等建议都没有奏效。

我不能使用 Net Core 或 NET 5,所以 this 也不起作用。 ImportPkcs8PrivateKey 方法在 Net Framework 中不可用。

如果我尝试使用 here 的 Bouncy Castle,我会得到 Unable to cast object of type 'Org.BouncyCastle.Crypto.Parameters.ECPrivateKeyParameters' to type 'Org.BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters'

【问题讨论】:

  • 一个问题是我们并不确切地知道服务器期望什么。您要连接到哪个服务器?协议规范在哪里?没有它,你就是在盲目地开枪。您似乎可以签名,所以问题一定存在于其他地方。

标签: c# openssl cryptography ecdsa


【解决方案1】:

第一个 OpenSSL 语句创建一个 EC 参数文件 private-key.pem,其中包含一个 PEM 编码的 SEC1 格式的私有 EC 密钥等。

使用 .NET Framework 最简单的方法是使用 BouncyCastle 进行密钥导入。 BouncyCastle 还支持用于 EC 签名的 ASN.1/DER 格式和 IEEE P1363 (r|s) 格式。

以下代码以 SEC1 格式导入 PEM 编码的私有 EC 密钥并签署消息。

using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
...
string pkcs8 =  @"-----BEGIN EC PRIVATE KEY-----
                MHQCAQEEIMmN/YG6BtIqm9eAcYtKdcbJosNKbB76vGMTSltPLNiioAcGBSuBBAAK
                oUQDQgAESGnGxuBPdrwv1TkJEorsaNk74+ZFh2jzww2SpLTqQqkvOf5IP6fuODS/
                hzztSBpsBpX9LUZh8TYHX0HRMagkaA==
                -----END EC PRIVATE KEY-----";

TextReader privateKeyTextReader = new StringReader(pkcs8);
AsymmetricCipherKeyPair privateKeyParams = (AsymmetricCipherKeyPair)new PemReader(privateKeyTextReader).ReadObject();

byte[] message = Encoding.UTF8.GetBytes("The quick brown fox jumps over the lazy dog");
ISigner signer = SignerUtilities.GetSigner("SHA-256withECDSA"); // ASN.1/DER format
//ISigner signer = SignerUtilities.GetSigner("SHA-256withPLAIN-ECDSA"); // r|s format
signer.Init(true, privateKeyParams.Private);
signer.BlockUpdate(message, 0, message.Length);
byte[] signature = signer.GenerateSignature();
Console.WriteLine(Hex.ToHexString(signature)); // 3046022100967c2e890d933c75468dceaf61152add41f143568dcb967583e1b307a0b495e30221008f6837c0d9cc01fc7bfe54ed5b6267fd3e64c2d3ff771e72762f24c20071c454

【讨论】:

    猜你喜欢
    • 2019-05-13
    • 2016-08-26
    • 2016-11-11
    • 2012-09-10
    • 2022-09-25
    • 2016-07-26
    • 1970-01-01
    • 2020-06-11
    • 2011-01-29
    相关资源
    最近更新 更多