I'm trying to implement SHA256-RSA digital signatures and I'm confused with the terminology and implementation in C#.

AFAIK, "signing a file" is to generate the hash of a file, and then encrypt that hash. I've also heard the phrase "signing the hash". Is this the same thing? Or is this hashing a hash and then encrypting hash'?

Here's the code in question:

```
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));
}
```

Here's what MSDN says on RSACryptoServiceProvider:

SignHash() Computes the signature for the specified hash value **by encrypting it** with the private key.

Encrypt() **Encrypts data** with the RSA algorithm.

Shouldnt SignHash(hash) and Encrypt(hash) be the same?

## Best Solution

The answer given by zaitsman is a good explanation of the topics related to your questions and I think should be the accepted answer, but just to help tie it back to your specific question of why encrypting the hash doesn't give you the same result as signing the hash (the

`rsa.SignHash(hashOfData, "SHA256")`

in your code):Signing a hash doesn't

justencrypt the hash data -- it also encrypts the name (or some identifier) of the hashing algorithm used to generate the hash along with it. Without that, the receiver wouldn't know what algorithm to use when computing their own hash (of the message being sent) to compare with the one they just decrypted in order to verify the authenticity of the message (which, of course, is the whole point).When you encrypted the hash yourself (with

`rsa.Encrypt(hashOfData, false)`

and`rsa.Encrypt(hashOfData, true)`

), you only encrypted the hash data and notthe combinationof hash dataandalgorithm identifier (`"SHA256"`

in your code). In other words, you encrypteddifferent data, so you gotdifferent (encrypted) results.The reason the return value of that

`SignHash`

calldoes matchthe value returned by`rsa.SignData(data, sha256)`

is that the latter method does the same thing, except it does the hashing and hash signing as one operation, so you don't have to compute the hash as a separate step if you don't need it for any purpose other than signing it.From RSACryptoServiceProvider.SignData Method on MSDN:

Also see: Why does SignHash need to know what hash algorithm was used?