c#充气城堡验证签名上的InvalidCastException

Posted

技术标签:

【中文标题】c#充气城堡验证签名上的InvalidCastException【英文标题】:InvalidCastException on c# bouncy castle verify signature 【发布时间】:2013-04-12 08:45:04 【问题描述】:

我尝试验证一个 ecdsa (256) 签名,我唯一需要做的数据是下面给定格式的公钥、原始数据和签名:

        string pubKey_ecdsa = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+noecsW+vdfd8DNo5dsAxU4DOaNt6PGmSCLFo/EvQG4xmVzv464qXvDPIrPN8GtLnubzoa9rtWJD52VlGOpFsA==";

        string data_ecdsa = ";\"4399901526945\";\"AAAA-BBBBBBBBB-123456789000\";\"5010112544615\";\"20130802063109143\";";

        string signature_ecdsa = @"BEcwRQIgJFwnCvm8lRjlRt+G+f4viJktDYVyOiXUd5BJ0V761eECIQDBTHLjJI7KK3FhczEHjunenYWXylDdW91jbS23EmeznA==";

当我尝试使用充气城堡通过调用验证签名时:

        //Create the public key from string
        AsymmetricKeyParameter pubKey = PublicKeyFactory.CreateKey(Convert.FromBase64String(pubKey_ecdsa));

        // create byte array from string
        byte[] b_signature = Convert.FromBase64String(signature_ecdsa);

        ASCIIEncoding encoder = new ASCIIEncoding();
        byte[] inputData = encoder.GetBytes(data_ecdsa);
        ISigner signer = SignerUtilities.GetSigner("SHA-256withECDSA");
        signer.Init(false, pubKey);
        signer.BlockUpdate(inputData, 0, inputData.Length);

        bool valid =  signer.VerifySignature(b_signature);

我收到InvalidCastException

Unable to cast object of type 'Org.BouncyCastle.Asn1.DerOctetString'
to type 'Org.BouncyCastle.Asn1.Asn1Sequence'. 

在以下行:

bool valid =  signer.VerifySignature(b_signature);

所以,签名似乎有问题,但我无法弄清楚。我希望任何人都可以提供一个好主意。

顺便说一下,这个例子中提供的数据被修改了,所以签名会被评估为假,如果它可以工作的话。

【问题讨论】:

你用的是什么版本的充气城堡? 您好,是c#版本的BouncyCastle.Crypto.dll,版本1.7.4114.6375 【参考方案1】:

这可能为时已晚,但为了以后读者的利益:

DSA 签名应该是包含两个 INTEGER 的 SEQUENCE 的 ASN.1 编码。这里的问题是 b_signature 实际上是一个八位字节字符串,其中的八位字节是正确的编码。所以有一个额外的“外层”包裹着真实的签名。您可以通过转储结构来看到这一点:

Asn1OctetString outer =(Asn1OctetString)Asn1Object.FromByteArray(b_signature);
byte[] inner = outer.GetOctets();

Console.WriteLine(Asn1Dump.DumpAsString(outer));
Console.WriteLine(Asn1Dump.DumpAsString(Asn1Object.FromByteArray(inner)));

对我来说,这打印出来:

DER 八位组字符串[71]

DER序列 整数(16446081942964531772961165410855935370418106604815444975891408706004345083361) 整数(87431453076334980518600256741994746667679967157867025465393185500427926877084)

因此,“内部”八位字节看起来已正确编码。现在:

bool valid = signer.VerifySignature(inner);

对我来说,这会打印“假”,您说这是预期的,因为数据已被修改。

【讨论】:

以上是关于c#充气城堡验证签名上的InvalidCastException的主要内容,如果未能解决你的问题,请参考以下文章

使用充气城堡验证签名

X509 RSA充气城堡标志数据和验证

C# ecdsa 签名 - 我可以选择哪个密钥规范?

使用充气城堡和证书私钥的数字签名

充气城堡 C# 中的 PBKDF2

Chaum 盲签名,在 JavaScript 中使用盲法并在 Java 中进行验证