首页 > 解决方案 > 为什么我的 RSA 签名实施适用于某些消息,但不适用于其他消息?

问题描述

我试图在 C# 中实现一个简单的 RSA 签名算法,只使用 BigInteger,没有内置的加密工具。为了签署一条消息,我用私钥对其进行加密,为了验证它,我用公钥对其进行解密。在下面的代码中,我注意到一个非常奇怪的行为。对于某些输入字符串(例如“Test”),它成功验证了签名,但对于其他字符串(例如“Test1”),它失败了。

我注意到的是,只有当m变量(消息的哈希)为负数时它才会失败,这会导致解密的ver变量变成一个非常大的数字并且代码打印“错误签名”。

// Generating RSA keys
var random = new Random();
var p = new BigInteger(256, 100, random);
var q = new BigInteger(256, 100, random);

var n = p.Multiply(q);
var phi = p.Subtract(BigInteger.One).Multiply(q.Subtract(BigInteger.One));

var e = new BigInteger("65537");
var d = e.ModInverse(phi);

// Preparing the message
var messageHash = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes("Test"));
var m = new BigInteger(messageHash);

// Signing the message
var signature = m.ModPow(d, n);

// Verifying the message
var ver = signature.ModPow(e, n);

Console.Out.WriteLine(m);
Console.Out.WriteLine(ver);

if(ver.Equals(m))
    Console.Out.WriteLine("Valid Signature");
else
    Console.Out.WriteLine("Wrong Signature");

我使用 BouncyCastle 作为BigInteger类型。

消息“测试”的示例输出:

16928957987407306249184430693954511195  
16928957987407306249184430693954511195  
Valid Signature

消息“Test1”的示例输出:

-40249184872970767997805928798048797124
10061048024793920770364189111057222210443355984675629704584018449091407182950576678391694061743052292040531884029654111183675927763342349593675935744009443
Wrong Signature

我相信错误是在签名过程中的某个地方,而不是在验证中。也许我不应该尝试加密负数?如果哈希是负数怎么办?如何修复此代码,使其在任何输入字符串上都能可靠运行?

标签: c#encryptionrsadigital-signature

解决方案


@Topaco 帮助我解决了我的问题。

对于消息 m 和模数 n,RSA 算法需要 0 <= m < n,这里。为了防止负数, var m = new BigInteger(1, messageHash); 可以使用,它创建相应的无符号值而不是有符号值


推荐阅读