How to handle asymmetric encryption with RSACryptoServicePro
Posted: Fri Feb 03, 2012 8:14 am
Traditional symmetric cryptography is all about hiding a secret using an algorithm and a key. The same key is used for encryption and decryption.
Asymmetric encryption does much more. In Asymmetric encryption there are two key: one is kept secret (private) and the other is distributed (public). Both keys are mathematically the same – What makes the public key public is the fact that it was distributed.
To perform a full cycle both keys are required (i.e. encryption with one key and decryption with the other).
There are two possible scenarios:
To obtain public and private key you can wrap them in X.509 certificate. You can put it in a file (cer, pfx) or install it in the certificate store. Certificates can be created using Certmgr.exe, IIS manager or plenty of other tools.
It is also possible to create special xml strings from certificates that will hold the private and public keys.
The Class System.Security provides us to execute Asymmetric Cryptography is called: RSACryptoServiceProvider and it is very simple to use.
Remember: Asymmetric encryption is expensive. It cannot be used for large data! In the next post I will show how to use symmetric encryption together with Asymmetric encryption to handle large data.
As you can see I implemented the first scenario. It happens that RSACryptoServiceProvider does not allow to execute the second scenario as is. If you will try to encrypt with the private and decrypt with the public you will get an exception! What you are trying to do is to prove to the world that you are the origin of the data. To do that RSACryptoServiceProvider provides digital signature methods.
Asymmetric encryption does much more. In Asymmetric encryption there are two key: one is kept secret (private) and the other is distributed (public). Both keys are mathematically the same – What makes the public key public is the fact that it was distributed.
To perform a full cycle both keys are required (i.e. encryption with one key and decryption with the other).
There are two possible scenarios:
- "Send a secret" : Encrypt some data with the public key and send it to the one who has the private key. Only she can decrypt the secret.
- "Proof of origin" : Encrypt some data with your private and send it to anyone who has your public. Assuming that "everyone" has your public it means that everyone can read your data. What you gained from the encryption is the fact that anyone who decrypted your data is absolutely certain that you are the source of the data because only the holder of the private key could have encrypted it.
To obtain public and private key you can wrap them in X.509 certificate. You can put it in a file (cer, pfx) or install it in the certificate store. Certificates can be created using Certmgr.exe, IIS manager or plenty of other tools.
It is also possible to create special xml strings from certificates that will hold the private and public keys.
The Class System.Security provides us to execute Asymmetric Cryptography is called: RSACryptoServiceProvider and it is very simple to use.
Remember: Asymmetric encryption is expensive. It cannot be used for large data! In the next post I will show how to use symmetric encryption together with Asymmetric encryption to handle large data.
Code: Select all
public byte[] EncryptAsyncPublic(byte[] data, X509Certificate2 certificate)
{
try
{
RSACryptoServiceProvider rsa = certificate.PublicKey.Key as RSACryptoServiceProvider;
return rsa.Encrypt(data, true);
}
catch (Exception ex)
{
...
return null;
}
}
public byte[] DecrypyAsyncPrivate(byte[] cipher, X509Certificate2 certificate)
{
try
{
RSACryptoServiceProvider rsa = certificate.PrivateKey as RSACryptoServiceProvider;
return rsa.Decrypt(cipher, true);
}
catch (Exception ex)
{
...
return null;
}
}
Code: Select all
public byte[] SignPrivate(byte[] data, X509Certificate2 certificate)
{
try
{
RSACryptoServiceProvider rsa = certificate.PrivateKey as RSACryptoServiceProvider;
return rsa.SignData(data, new SHA1CryptoServiceProvider());
}
catch (Exception ex)
{
...
return null;
}
}
public bool VerifySinatutePublic(byte[] data, byte[] signature, X509Certificate2 certificate)
{
if ((data == null) || (signature == null))
return false;
try
{
RSACryptoServiceProvider rsa = certificate.PublicKey.Key as RSACryptoServiceProvider;
return rsa.VerifyData(data, new SHA1CryptoServiceProvider(), signature);
}
catch (Exception ex)
{
...
return false;
}
}