I have a method that currently returns a string converted from a byte array:
public static readonly UnicodeEncoding ByteConverter = new UnicodeEncoding();
public static string Decrypt(string textToDecrypt, string privateKeyXml)
{
if (string.IsNullOrEmpty(textToDecrypt))
{
throw new ArgumentException(
"Cannot decrypt null or blank string"
);
}
if (string.IsNullOrEmpty(privateKeyXml))
{
throw new ArgumentException("Invalid private key XML given");
}
byte[] bytesToDecrypt = Convert.FromBase64String(textToDecrypt);
byte[] decryptedBytes;
using (var rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(privateKeyXml);
decryptedBytes = rsa.Decrypt(bytesToDecrypt, FOAEP);
}
return ByteConverter.GetString(decryptedBytes);
}
I’m trying to update this method to instead return a SecureString, but I’m having trouble converting the return value of RSACryptoServiceProvider.Decrypt from byte[] to SecureString. I tried the following:
var secStr = new SecureString();
foreach (byte b in decryptedBytes)
{
char[] chars = ByteConverter.GetChars(new[] { b });
if (chars.Length != 1)
{
throw new Exception(
"Could not convert a single byte into a single char"
);
}
secStr.AppendChar(chars[0]);
}
return secStr;
However, using this SecureString equality tester, the resulting SecureString was not equal to the SecureString constructed from the original, unencrypted text. My Encrypt and Decrypt methods worked before, when I was just using string everywhere, and I’ve also tested the SecureString equality code, so I’m pretty sure the problem here is how I’m trying to convert byte[] into SecureString. Is there another route I should take for using RSA encryption that would allow me to get back a SecureString when I decrypt?
Edit: I didn’t want to convert the byte array to a regular string and then stuff that string into a SecureString, because that seems to defeat the point of using a SecureString in the first place. However, is it also bad that Decrypt returns byte[] and I’m then trying to stuff that byte array into a SecureString? It’s my guess that if Decrypt returns a byte[], then that’s a safe way to pass around sensitive information, so converting one secure representation of the data to another secure representation seems okay.
Based on Coding Gorilla’s answer, I tried the following in my
Decryptmethod:When debugging,
decryptedString1anddecryptedString2were not equal:So it looks like I can just go through the
byte[]array, do a direct cast tochar, and skip\0characters. Like Coding Gorilla said, though, this does seem to again in part defeat the point ofSecureString, because the sensitive data is floating about in memory in littlebyte-size chunks. Any suggestions for gettingRSACryptoServiceProvider.Decryptto return aSecureStringdirectly?Edit: yep, this works:
Edit: correction: this works with plain old English strings. Encrypting and then attempting to decrypt the string
"標準語 明治維新 english やった"doesn’t work as expected because the resulting decrypted string, using thisforeach (byte b in decryptedBytes)technique, does not match the original unencrypted string.Edit: using the following works for both:
This still leaves a byte array and a char array of the password in memory, which sucks. Maybe I should find another RSA class that returns a
SecureString. :/