![](/img/trans.png)
[英]Verify BouncyCastle ECDsa signature with .NET libraries ECDsaCng
[英]Verifying ECDSA signature with BouncyCastle
我正在測試 BouncyCastle 以使用ECDSA
驗證簽名,nist nist P251
。 (Xamarin 的加密 API 尚未實現,我開始使用 Bouncy Castle 庫。)
無論如何,我在下面的代碼中面臨的是......方法 B 與C#
API 一起正常工作,方法 A 不是。 A 方法的 ECPoint 看起來有問題,但我無法檢查詳細信息。
(我已經檢查過,但無法修復。)
我應該如何更改A方法? 歡迎任何想法。提前致謝。
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Nist;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
namespace TestMe
{
class Program
{
public static byte[] HexStringToByteArray(string Hex)
{
byte[] Bytes = new byte[Hex.Length / 2];
int[] HexValue = new int[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0B, 0x0C, 0x0D,
0x0E, 0x0F };
for (int x = 0, i = 0; i < Hex.Length; i += 2, x += 1)
{
Bytes[x] = (byte)(HexValue[Char.ToUpper(Hex[i + 0]) - '0'] << 4 |
HexValue[Char.ToUpper(Hex[i + 1]) - '0']);
}
return Bytes;
}
static void Main(string[] args)
{
String sig
= "e1f5cecccedfe5228d9331098e84b69a0675cdd9ac066ecfada7fea761f52a4cde902a0abd362883127230326fb556af14e894d39a3e14437aaa4134a3476c84";
String msg = "00000000dcb320137ddd6f825660750ab655219fad66951c64f0420be8ac902975197ed2b0da54cd3d502d34dd04c8d74b2958a0b8792ae4730df6d25a6969bcad9f93a7d6229e5a0100000017cf5242732bba21a0b0e7dad7102cf7bdb2c8d7a665045816a886d7";
String pub = "b679e27513e2fff8fdeb54409c242776f3517f370440d26885de574a0b0e5309a9de4ea055b0bf302d9f00875f80e28cd29bb95a48aa53746d7de9465123dbb7";
A(HexStringToByteArray(msg), HexStringToByteArray(sig), HexStringToByteArray(pub));
B(HexStringToByteArray(msg), HexStringToByteArray(sig), HexStringToByteArray(pub));
}
//incorrect
static void A(byte[] message, byte[] signature, byte[] pubkey)
{
BigInteger x = new BigInteger(1, pubkey.Take(32).ToArray());
BigInteger y = new BigInteger(1, pubkey.Skip(32).ToArray());
X9ECParameters ecParams = NistNamedCurves.GetByName("P-256");
ECDomainParameters domainParameters = new ECDomainParameters(ecParams.Curve, ecParams.G, ecParams.N, ecParams.H, ecParams.GetSeed());
var G = ecParams.G;
Org.BouncyCastle.Math.EC.ECCurve curve = ecParams.Curve;
Org.BouncyCastle.Math.EC.ECPoint q = curve.CreatePoint(x, y);
ECPublicKeyParameters pubkeyParam = new ECPublicKeyParameters(q, domainParameters);
var verifier = SignerUtilities.GetSigner("SHA-256withECDSA");
verifier.Init(false, pubkeyParam);
verifier.BlockUpdate(message, 0, message.Length);
bool result = verifier.VerifySignature(signature);
Console.WriteLine("result: " + result);
}
// correct
static void B(byte[] message, byte[] signature, byte[] pubkey)
{
var Q = new System.Security.Cryptography.ECPoint();
var param = new ECParameters();
Q.X = pubkey.Take(32).ToArray();
Q.Y = pubkey.Skip(32).ToArray();
param.Curve = System.Security.Cryptography.ECCurve.NamedCurves.nistP256;
param.Q = Q;
var ecdsa = ECDsa.Create(param);
bool result = ecdsa.VerifyData(message, signature, HashAlgorithmName.SHA256);
Console.WriteLine("result: " + result);
}
}
}
您使用充氣城堡驗證簽名的代碼是正確的。 問題在於簽名格式。
ECDSA 簽名基本上是兩個數字,通常稱為r
和s
。 在您的示例簽名中,這兩個數字只是連接在一起。 每個都是 32 字節,所以你的簽名是 64 字節。
這種格式(連接數字)是 .NET api 所期望的,但不是 Bouncy Castle 所期望的。 Bouncy Castle 期望簽名是 DER 編碼的(就像規范規定的那樣)。
因此,您需要將簽名從當前格式“轉換”為 BC 期望的格式,如下所示:
// expected format is SEQUENCE {INTEGER r, INTEGER s}
var derSignature = new DerSequence(
// first 32 bytes is "r" number
new DerInteger(new BigInteger(1, signature.Take(32).ToArray())),
// last 32 bytes is "s" number
new DerInteger(new BigInteger(1, signature.Skip(32).ToArray())))
.GetDerEncoded();
然后驗證這個簽名(順便說一下,現在是 70 個字節):
bool result = verifier.VerifySignature(derSignature);
它會正常工作。
使用最新版本的 Bouncy Castle,可以使用“SHA-256withPLAIN-ECDSA”創建驗證器。 這允許您傳入原始的 64 字節簽名數組,而無需創建DerSequence
。
var verifier = SignerUtilities.GetSigner("SHA-256withPLAIN-ECDSA");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.