为何篡改后的ECDSA公钥仍可能通过签名验证?
ECDSA篡改公钥后仍能验证签名的原因分析
问题描述
我是ECDSA新手,正在进行哈希签名验证,现有一段可正常完成签名创建与验证的示例代码:
.... //Signing byte[] ecdsa_sig = ecdsa.SignHash(hash256); str1 += "\n\nECDSA Signature (Hex)=" + BitConverter.ToString(ecdsa_sig).Replace("-", string.Empty); str1 += "\nECDSA Signature (Base64)=" + System.Convert.ToBase64String(ecdsa_sig).Replace("-", string.Empty); //On the receiver side ECParameters ecparams_rec = new ECParameters(); ecparams_rec.Q = new ECPoint(); ecparams_rec.Q.X = System.Convert.FromBase64String("RfXXNxTu8xRb48jrJs9kjhQun3+PXqzowby8RwIVTkE="); ecparams_rec.Q.Y = System.Convert.FromBase64String("YC77gvGyFYA+iJ/+Ak7lN8H4hY7tV7TUiY/rPTJOajk="); ecparams_rec.Curve = ECCurve.NamedCurves.nistP256; //32 bytes private key ECDsa ecdsa_rec = System.Security.Cryptography.ECDsa.Create(ecparams_rec); string word_rec = "Hello Crypto World! "; //Verifying byte[] hash256_rec = System.Security.Cryptography.HashAlgorithm.Create(hashmethod).ComputeHash(System.Text.Encoding.UTF8.GetBytes(word_rec)); bool res = ecdsa_rec.VerifyHash(hash256_rec, ecdsa_sig); if (res == true) str1 += "\n\nSignature verifies - OK"; else str1 += "\n\nSignature not verified!!!!!"; Console.WriteLine("{0}",str1);
我使用公钥(Q.X和Q.Y参数)验证签名,但发现修改公钥Base64末尾的部分字符(如将最后一个'E'改为'F')后,偶尔仍能通过签名验证,想请教为何被篡改的公钥仍可验证签名?
原因分析
Base64修改未影响实际公钥字节
NIST P256曲线的公钥X、Y坐标固定为32字节,.NET的ECDsa实现会自动截断超长的解码字节。如果你修改的Base64字符刚好对应解码后第33字节及以后的内容,这部分会被直接丢弃,实际参与验证的还是原合法公钥,自然能通过验证。极小概率的数学巧合
ECDSA验证本质是匹配椭圆曲线的数学等式。篡改后的公钥对应的点,存在极低概率刚好满足验证等式的条件,这种情况属于随机巧合,概率约为1/2^256量级,仅在修改少数位时可能偶然触发。未验证公钥的曲线合法性
.NET的ECDsa.Create方法默认不会检查传入的X、Y坐标是否属于指定的NIST P256曲线。即便篡改后的公钥是无效点,验证逻辑仍会执行计算,若计算结果恰好匹配就会返回true。正确做法是在验证前调用ecdsa_rec.ValidatePublicKey(),先确认公钥是曲线上的有效点,避免无效公钥参与验证。
内容的提问来源于stack exchange,提问作者toto'
相关产品推荐
相关产品推荐

