c# - ECDSA 使用来自 Java 的公钥和签名验证 C# 中的签名
问题描述
我有一个用 Java 生成的公钥和签名,我想使用 ECDsaCng 在 C# 中进行验证。公钥是MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExeg15CVOUcspdO0Pm27hPVx50thn0CGk3/3NLl08qcK+0U7cesOUUwxQetMgtUHrh0lNao5XRAAurhcBtZpo6w==
我通过获取最后 64 个字节并在其前面添加 0x45、0x43、0x53、0x31、... 将其转换为 C# ECDsaCng 可以使用的密钥。
签名是使用 SHA256 在 Java 中生成的。有趣的是,如果我在这里使用工具测试签名https://kjur.github.io/jsrsasign/sample/sample-ecdsa.html,它说它是一个有效的签名。
我一直在网上搜索,仍然没有快乐。
代码如下
static void VerifySignature()
{
var publicKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExeg15CVOUcspdO0Pm27hPVx50thn0CGk3/3NLl08qcK+0U7cesOUUwxQetMgtUHrh0lNao5XRAAurhcBtZpo6w==";
byte[] publicKeyBytes = Convert.FromBase64String(publicKey);
var keyType = new byte[] { 0x45, 0x43, 0x53, 0x31 };
var keyLength = new byte[] { 0x20, 0x00, 0x00, 0x00 };
var key = keyType.Concat(keyLength).Concat(publicKeyBytes.TakeLast(64)).ToArray(); // 4543533120000000c5e835e4254e51cb2974ed0f9b6ee13d5c79d2d867d021a4dffdcd2e5d3ca9c2bed14edc7ac394530c507ad320b541eb87494d6a8e5744002eae1701b59a68eb
// For testing in online tool
Debug.WriteLine(ByteArrayToString(publicKeyBytes.TakeLast(65).ToArray())); //04c5e835e4254e51cb2974ed0f9b6ee13d5c79d2d867d021a4dffdcd2e5d3ca9c2bed14edc7ac394530c507ad320b541eb87494d6a8e5744002eae1701b59a68eb
var signature = "MEQCIFNEZQRzIrvr6dtJ4j4HP8nXHSts3w3qsRt8cFXBaOGAAiAJO/EjzCZlNLQSvKBinVHfSvTEmor0dc3YX7FPMnnYCg==";
var signatureBytes = Convert.FromBase64String(signature); // 30440220534465047322bbebe9db49e23e073fc9d71d2b6cdf0deab11b7c7055c168e1800220093bf123cc266534b412bca0629d51df4af4c49a8af475cdd85fb14f3279d80a
var data = Encoding.UTF8.GetBytes("ABCDEFGH");
CngKey cngKey = CngKey.Import(key, CngKeyBlobFormat.EccPublicBlob);
ECDsaCng eCDsaCng = new ECDsaCng(cngKey);
bool result = eCDsaCng.VerifyData(data, signatureBytes); // result is false
string ByteArrayToString(byte[] ba)
{
StringBuilder hex = new StringBuilder(ba.Length * 2);
foreach (byte b in ba)
hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
}
解决方案
原因是格式不同。r|s
当您的签名在 -format 中指定时,Microsoft 需要该格式ASN.1
(在 ECDSA 的上下文中对此进行了解释):
0x30|b1|0x02|b2|r|0x02|b3|s
b1 = Length of remaining data
b2 = Length of r
b3 = Length of s
你的签名
30440220534465047322bbebe9db49e23e073fc9d71d2b6cdf0deab11b7c7055c168e1800220093bf123cc266534b412bca0629d51df4af4c49a8af475cdd85fb14f3279d80a
可分为以下几部分
30 44 02 20 534465047322bbebe9db49e23e073fc9d71d2b6cdf0deab11b7c7055c168e180 02 20 093bf123cc266534b412bca0629d51df4af4c49a8af475cdd85fb14f3279d80a
以便可以轻松识别各个部分:
b1 = 0x44
b2 = 0x20
r = 0x534465047322bbebe9db49e23e073fc9d71d2b6cdf0deab11b7c7055c168e180
b3 = 0x20
s = 0x093bf123cc266534b412bca0629d51df4af4c49a8af475cdd85fb14f3279d80a
因此
r|s = 534465047322bbebe9db49e23e073fc9d71d2b6cdf0deab11b7c7055c168e180093bf123cc266534b412bca0629d51df4af4c49a8af475cdd85fb14f3279d80a
如果您使用此格式运行代码,则验证成功。
推荐阅读
- javascript - javascript 到 HTML 文件和测试覆盖率
- go - 当我在另一个文件中使用外部包时,去 mod “找不到包”
- java - 使用 Local_policy.jar 和 US_export_policy.jar 和
- javascript - 向服务 URL 发出请求失败,但对版本 url 没有
- neural-network - 如何正确实现我的突变功能?
- scroll - Skrollr - 如何允许未知大小的长文本滚动到最后
- swiftui - 为什么在 SwiftUI 中滚动后所选行不保持选中状态?
- ios - iOS UIPasterboard 不在设备上显示消息
- python - 如何在 Python 中仅从一个 Ray 进程启用打印?
- visual-studio-code - 无法更改 vscode 字体