数字签名:加密散列与签署散列?

Digital Signatures: Encrypting the Hash vs Signing the Hash?

我正在尝试实现 SHA256-RSA 数字签名,但我对 C# 中的术语和实现感到困惑。

AFAIK,"signing a file" 是生成文件的哈希值,然后加密该哈希值。我也听说过 "signing the hash" 这个短语。这是一回事吗?或者这是散列一个散列然后加密散列'?

这是有问题的代码:

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() 通过使用私钥加密 来计算指定哈希值的签名。

Encrypt() 使用 RSA 算法加密数据

SignHash(hash) 和 Encrypt(hash) 不应该一样吗?

您需要分离关注点,这将有助于您理解术语。

任何任意数据块都可以hash编辑and/or encrypt任何组合。 Hash 表示:使用密码算法生成一个不可逆的值(即仅仅知道算法和散列你无法重构原始数据)和一致的(即给定相同的数据和算法,生成的哈希值始终相同)。

Encrypt 表示:使用密码算法用给定的密钥(密钥可以是对称的或非对称的)对数据(全部或块)进行加密。

Sign 表示:Hash 数据和 Encrypt 具有给定键的散列。然后,给定一对(对于非对称)或相同(对于对称)密钥,消费者可以验证:

  1. 哈希匹配,这意味着数据在传输过程中没有被更改
  2. 哈希确实来自至少具有配对密钥(对于非对称)或相同密钥(对于对称)的来源

很好地解释了与您的问题相关的主题,我认为应该是可以接受的答案,但只是为了帮助将其与您的特定问题联系起来,即为什么加密哈希不给您与签署散列的结果相同(代码中的 rsa.SignHash(hashOfData, "SHA256")):

对散列进行签名并不只是加密散列数据——它还加密了用于生成散列的散列算法的名称(或某些标识符)以及它.否则,接收方将不知道在计算他们自己的哈希值(正在发送的消息)时使用什么算法来与他们刚刚解密的哈希值进行比较以验证消息的真实性(当然,这是整点)。

当您自己加密哈希值时(使用 rsa.Encrypt(hashOfData, false)rsa.Encrypt(hashOfData, true)),您只加密了哈希数据而不是哈希数据的组合 算法标识符(代码中的"SHA256")。换句话说,您加密了不同的数据,所以您得到了不同的(加密)结果

SignHash 调用 的 return 值与 rsa.SignData(data, sha256) 编辑的值 return 匹配的原因是

来自 MSDN 上的 RSACryptoServiceProvider.SignData Method

Computes the hash value of the specified data and signs it.


另见:Why does SignHash need to know what hash algorithm was used?