这是我的解密过程代码:
private RSACryptoServiceProvider _rsa;
private string _privateKey;
private string _publicKey;
public RsaLibrary()
{
//initialsing the RSA object taking the option of a 1024 key size
_rsa = new RSACryptoServiceProvider(1024);
_privateKey = _rsa.ToXmlString(true);
_publicKey = _rsa.ToXmlString(false);
}
public string Decrypt(string ciphertext, string privateKey_ = null)
{
if (String.IsNullOrEmpty(privateKey_))
{
return DecryptToBytes(ciphertext, _privateKey);
}
else
{
return DecryptToBytes(ciphertext, privateKey_);
}
}
private string DecryptToBytes(string ciphertext, string privateKey)
{
if (String.IsNullOrEmpty(privateKey))
{
throw new ArgumentNullException("Error: No key provided.");
}
if (ciphertext.Length<=0)
{
throw new ArgumentNullException("Error: No message to decrypt.");
}
byte[] plaintext;
byte[] ciphertext_Bytes = Encoding.Unicode.GetBytes(ciphertext);
_rsa.FromXmlString(privateKey);
plaintext = _rsa.Decrypt(ciphertext_Bytes, false);
return Encoding.Unicode.GetString(plaintext);
}
加密代码:
private string EncryptToByte(string plaintext, string publicKey)
{
if (String.IsNullOrEmpty(publicKey))
{
throw new ArgumentNullException("Error: No key provided.");
}
if (plaintext.Length<=0)
{
throw new ArgumentNullException("Error: No message to incrypt");
}
byte[] ciphertext;
byte[] plaintext_Bytes = Encoding.Unicode.GetBytes(plaintext);
_rsa.FromXmlString(publicKey);
ciphertext = _rsa.Encrypt(plaintext_Bytes, false);
return Convert.ToBase64String(ciphertext);
}
我看不出我错在哪里。我确保钥匙是正确的。我在构造函数中使用此行提取的公共一个: _publicKey = _rsa.ToXmlString(false); 此公钥显示在我创建的表单上。私人我用“真”而不是假。
有什么想法吗?
答案 0 :(得分:5)
密文不太可能是真正的UTF-16编码文本。假设加密方面有类似的内容:
string encryptedText = Encoding.Unicode.GetString(encryptedBytes);
你基本上丢失了数据。加密的结果是不文本 - 它是任意二进制数据。如果由于某些传输原因要将其转换为文本,则应使用Base64,例如
string base64EncryptedText = Convert.ToBase64String(encryptedBytes);
然后使用Convert.FromBase64String
恢复准备解密的原始加密二进制数据。
答案 1 :(得分:0)
以下是您使用base-64字符串的RsaLibrary
类,如Jon建议的那样:
class RsaLibrary
{
//initializing the RSA object taking the option of a 1024 key size
readonly RSACryptoServiceProvider _rsa = new RSACryptoServiceProvider(1024);
readonly string _privateKey;
readonly string _publicKey;
public RsaLibrary()
{
_privateKey = _rsa.ToXmlString(true);
_publicKey = _rsa.ToXmlString(false);
}
public string Decrypt(string ciphertext, string privateKey_ = null)
{
if (ciphertext.Length <= 0) throw new ArgumentNullException("ciphertext");
string key = String.IsNullOrEmpty(privateKey_) ? _privateKey : privateKey_;
return DecryptToBytes(ciphertext, key);
}
private string DecryptToBytes(string ciphertext, string privateKey)
{
if (String.IsNullOrEmpty(privateKey)) throw new ArgumentNullException("privateKey");
byte[] ciphertext_Bytes = Convert.FromBase64String(ciphertext);
_rsa.FromXmlString(privateKey);
byte[] plaintext = _rsa.Decrypt(ciphertext_Bytes, false);
return Encoding.Unicode.GetString(plaintext);
}
public string Encrypt(string plaintext, string publicKey_ = null)
{
if (plaintext.Length <= 0) throw new ArgumentNullException("plaintext");
string key = String.IsNullOrEmpty(publicKey_) ? _publicKey : publicKey_;
return EncryptToBytes(plaintext, key);
}
private string EncryptToBytes(string plaintext, string publicKey)
{
if (String.IsNullOrEmpty(publicKey)) throw new ArgumentNullException("publicKey");
byte[] plaintext_Bytes = Encoding.Unicode.GetBytes(plaintext);
_rsa.FromXmlString(publicKey);
byte[] ciphertext = _rsa.Encrypt(plaintext_Bytes, false);
return Convert.ToBase64String(ciphertext);
}
}
你真的应该使用SecureString
作为你的明文。
class RsaLibrary2
{
//initializing the RSA object taking the option of a 1024 key size
readonly RSACryptoServiceProvider _rsa = new RSACryptoServiceProvider(1024);
readonly string _privateKey;
readonly string _publicKey;
public RsaLibrary2()
{
_privateKey = _rsa.ToXmlString(true);
_publicKey = _rsa.ToXmlString(false);
}
public SecureString Decrypt(string ciphertext, string privateKey_ = null)
{
if (ciphertext.Length <= 0) throw new ArgumentNullException("ciphertext");
string key = String.IsNullOrEmpty(privateKey_) ? _privateKey : privateKey_;
return DecryptToBytes(ciphertext, key);
}
private SecureString DecryptToBytes(string ciphertext, string privateKey)
{
if (String.IsNullOrEmpty(privateKey)) throw new ArgumentNullException("privateKey");
byte[] ciphertext_Bytes = Convert.FromBase64String(ciphertext);
_rsa.FromXmlString(privateKey);
byte[] plainbytes = _rsa.Decrypt(ciphertext_Bytes, false);
char[] plain = Encoding.Unicode.GetChars(plainbytes);
var retval = new SecureString();
FromArray(retval, ref plain);
return retval;
}
public string Encrypt(SecureString plaintext, string publicKey_ = null)
{
if (plaintext == null) throw new ArgumentNullException("plaintext");
if (plaintext.Length <= 0) throw new ArgumentOutOfRangeException("plaintext");
string key = String.IsNullOrEmpty(publicKey_) ? _publicKey : publicKey_;
return EncryptToBytes(plaintext, key);
}
private string EncryptToBytes(SecureString plaintext, string publicKey)
{
if (String.IsNullOrEmpty(publicKey)) throw new ArgumentNullException("publicKey");
byte[] plaintext_Bytes = SecureStringToByteArray(plaintext);
_rsa.FromXmlString(publicKey);
byte[] ciphertext = _rsa.Encrypt(plaintext_Bytes, false);
return Convert.ToBase64String(ciphertext);
}
// YIKES! Copies the SecureString to a byte[] array; use with caution!
static byte[] SecureStringToByteArray(SecureString secureString)
{
if (secureString == null) throw new ArgumentNullException(/*MSG0*/"secureString");
// copy plaintext from unmanaged memory into managed byte[]s
int stringSize = secureString.Length * sizeof(char); // http://blogs.msdn.com/shawnfa/archive/2005/02/25/380592.aspx
byte[] bytes = new byte[stringSize];
IntPtr pString = Marshal.SecureStringToGlobalAllocUnicode(secureString); // do this last to minimize the availability of "pString"
try // free "pString" even if Copy() throws
{
Marshal.Copy(pString, bytes, 0, stringSize);
}
finally
{
Marshal.ZeroFreeGlobalAllocUnicode(pString); // clear plaintext from unmanaged memory ASAP
}
return bytes;
}
static void ArrayZero<T>(ref T[] array)
{
Array.Clear(array, 0, array.Length); // clear from managed memory
Array.Resize(ref array, 0); // set Length=0 ASAP; even the length can be valuable
array = null; // just to "help" callers know there's nothing in the array anymore
}
static void FromArray(SecureString secureString, ref char[] array)
{
try // clear "array" even if AppendChar() throws
{
for (int i = 0; i < array.Length; i++)
{
secureString.AppendChar(array[i]);
array[i] = default(char); // clear plaintext ASAP
}
}
finally
{
ArrayZero(ref array); // clear plaintext from managed memory
}
}
}