数字签名:加密哈希与签署哈希?

nr-*_*-91 7 c# encryption cryptography certificate

我正在尝试实现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));
}
Run Code Online (Sandbox Code Playgroud)

以下是MSDN在RSACryptoServiceProvider上所说的内容:

SignHash()通过使用私钥加密指定哈希值的签名.

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

SignHash(哈希)和加密(哈希)不一样吗?

zai*_*man 5

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

可以以任何组合hash编辑和/或encrypt编辑任何任意数据块. Hash意味着:使用加密算法生成不可逆的值(即,简单地通过了解您无法重构原始数据的算法和哈希)和一致性(即,给定相同的数据和算法,生成的哈希值)总是一样的).

Encrypt 表示:使用加密算法用给定密钥加密数据(完全或在块中)(密钥可以是对称的或非对称的).

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

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


小智 5

zaitsman给出的答案是对与您的问题相关的主题的一个很好的解释,我认为应该是接受的答案,但只是为了帮助将它与特定的问题联系起来,为什么加密哈希不会给你带来相同的结果.签署哈希(rsa.SignHash(hashOfData, "SHA256")在您的代码中):

对散列进行签名不仅会加密散列数据 - 它还会加密用于生成散列的散列算法的名称(或某些标识符).如果没有这个,接收器就不会知道在计算他们自己的哈希(被发送的消息)时要使用什么算法来与他们刚刚解密的哈希进行比较,以便验证消息的真实性(当然,这是整点).

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

SignHash调用的返回值与返回的值匹配的原因rsa.SignData(data, sha256)是后一种方法执行相同的操作,除了它将散列和散列签名作为一个操作,因此您不必将散列计算为单独的步骤如果您不需要签名以外的任何其他目的.

从MSDN上的RSACryptoServiceProvider.SignData方法:

计算指定数据的哈希值并对其进行签名.


另请参阅:为什么SignHash需要知道使用了哪种哈希算法?