DEMO of using RSACryptoServiceProvider with JSEncrypt lib
RSACryptoServiceProvider uses "raw" keys representation (see docs).
JSEncrypt uses "PEM" keys format (see ASN.1 key structures in DER and PEM, RSA key breakdown).
So, workflow could be following:
Generate keys by creation of new instance of RSACryptoServiceProvider with preferred key size.
Create PEM-formatted string to use with JSEncrypt (see RSAUtil.ExportPublicKeyToPemString
, code from here).
Code sample:
rsaProvider = new RSACryptoServiceProvider(keySize);
var pemFormattedKey = RsaUtil.ExportPublicKeyToPemString(rsaProvider); // key to use with JSEncrypt
Keys can be exported and imported from XML string (RSACryptoServiceProvider.FromXmlString
and RSACryptoServiceProvider.ToXmlString
).
CspParameters can be used as more secure way to store keys (as microsoft says, docs).
Code sample:
var cspParams = new CspParameters
{
KeyContainerName = storageName,
Flags = CspProviderFlags.UseMachineKeyStore
};
var rsaProvider = new RSACryptoServiceProvider(keySize, cspParams);
RSA key will be generated and stored in container with specified name if container does not exist. Otherwise, RSA key will be loaded from container (keySize will be ignored). Containers are stored in file system (I found them here C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys
).
Use pemFormattedKey to encrypt text on client side:
var encrypt = new JSEncrypt();
encrypt.setKey(pemFormattedKey); // use PEM-formatted key
var encryptedBase64String = encrypt.encrypt(textToEncrypt);
JSEncrypt uses the same raw key parameters inside as RSACryptoServiceProvider does, so it is possible to avoid of using PEM-format by modifying JSEncrypt code. For some reason developers haven't provided oportunity to use raw public key structure.
Now we have array of bytes in base64 format.
Sample code for decryption:
var encryptedBytes = Convert.FromBase64String(encryptedBase64String);
var decryptedBytes = rsaProvider.Decrypt(encryptedBytes, false);
var decryptedString = Encoding.UTF8.GetString(decryptedBytes);