我试图实施SHA256-RSA数字签名,并且我对C#中的术语和实现感到困惑。
AFAIK,"签署文件"是生成文件的哈希值,然后加密该哈希值。我也听过这句话"签署哈希"。这是一回事吗?或者这是哈希哈希,然后加密哈希'?
以下是有问题的代码:
public void SignatureTest(byte[] data, X509Certificate2 cert)
{
var sha256 = new SHA256CryptoServiceProvider();
var rsa = (RSACryptoServiceProvider)cert.PrivateKey;
var hashOfData = sha256.ComputeHash(data);
var encryptedHash = rsa.Encrypt(hashOfData, false);
var encryptedHashOAEP = rsa.Encrypt(hashOfData, true);
var signedHash = rsa.SignHash(hashOfData, "SHA256");
//Shouldn't one of these be true?
var false1 = CompareAsBase64Str(encryptedHash, signedHash);
var false2 = CompareAsBase64Str(encryptedHashOAEP, signedHash);
//This is the one that actually matches
var true1 = CompareAsBase64Str(signedHash, rsa.SignData(data, sha256));
}
public bool CompareAsBase64Str(byte[] b1, byte[] b2)
{
return (Convert.ToBase64String(b1) == Convert.ToBase64String(b2));
}
这是MSDN在RSACryptoServiceProvider上所说的内容:
SignHash()使用私钥计算指定哈希值的签名 。
使用RSA算法加密()加密数据。
不应该使用SignHash(哈希)和加密(哈希)相同吗?
答案 0 :(得分:5)
您需要分开关注点,这有助于您理解术语。
任意组合的任意blob都可以hash
和/或encrypt
组合。
Hash
表示:使用加密算法生成不可逆的值(即,简单地通过了解您无法重构原始数据的算法和哈希)和一致性(即,给定相同的数据和算法,产生的哈希值总是相同的。)
Encrypt
表示:使用加密算法用给定密钥加密数据(完全或在块中)(密钥可以是对称的或非对称的)。
Sign
表示:Hash
数据和Encrypt
具有给定键的哈希值。然后,给定对(用于非对称)或相同(用于对称)密钥,消费者可以验证:
答案 1 :(得分:5)
The answer given by zaitsman是对与您的问题相关的主题的一个很好的解释,我认为应该是接受的答案,但只是为了帮助将其与您的特定问题联系起来,为什么加密哈希不会给您带来与签名哈希(代码中的rsa.SignHash(hashOfData, "SHA256")
)相同的结果:
签署哈希不会仅加密哈希数据 - 它还会加密用于生成哈希的哈希算法的名称(或某些标识符)。如果没有这个,接收器就不会知道在计算他们自己的哈希(被发送的消息)时要使用什么算法来与他们刚刚解密的哈希进行比较,以便验证消息的真实性(当然,这是整点)。
当您自己加密哈希值(使用rsa.Encrypt(hashOfData, false)
和rsa.Encrypt(hashOfData, true)
)时,您只加密了哈希数据,而不是哈希数据的组合 和算法标识符(代码中为"SHA256"
)。换句话说,您加密了不同的数据,因此您获得了不同(加密)的结果。
SignHash
调用的返回值匹配 rsa.SignData(data, sha256)
返回的值的原因是后一种方法做同样的事情,除了它进行散列和散列签名作为一个操作,因此如果除了签名之外不需要将哈希用于任何目的,则不必将哈希计算为单独的步骤。
来自MSDN上的RSACryptoServiceProvider.SignData Method:
计算指定数据的哈希值并对其进行签名。
另请参阅:Why does SignHash need to know what hash algorithm was used?