使用RSA加密/解密时会间歇性地发生CryptographicException

Sar*_*els 6 c# security encryption rsa rsacryptoserviceprovider

我正在尝试使用C#中的RSA加密和解密数据.我有以下MSTest单元测试:

const string rawPassword = "mypass";

// Encrypt
string publicKey, privateKey;
string encryptedPassword = RSAUtils.Encrypt(rawPassword, out publicKey, out privateKey);
Assert.AreNotEqual(rawPassword, encryptedPassword,
    "Raw password and encrypted password should not be equal");

// Decrypt
string decryptedPassword = RSAUtils.Decrypt(encryptedPassword, privateKey);
Assert.AreEqual(rawPassword, decryptedPassword,
    "Did not get expected decrypted password");
Run Code Online (Sandbox Code Playgroud)

它在解密过程中失败,但有时只会失败.似乎每当我设置断点并逐步完成测试时,它就会通过.这让我觉得也许有些事情没有及时完成解密才能成功发生,而且我在调试过程中放慢了步伐,给了它足够的时间来完成.当它失败时,它似乎失败的行是decryptedBytes = rsa.Decrypt(bytesToDecrypt, false);在以下方法中:

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 = ByteConverter.GetBytes(textToDecrypt);
    byte[] decryptedBytes;
    using (var rsa = new RSACryptoServiceProvider())
    {
        rsa.FromXmlString(privateKeyXml);
        decryptedBytes = rsa.Decrypt(bytesToDecrypt, false); // fail here
    }
    return ByteConverter.GetString(decryptedBytes);
}
Run Code Online (Sandbox Code Playgroud)

它失败并出现此异常:

System.Security.Cryptography.CryptographicException:错误数据

我的Encrypt方法如下:

public static string Encrypt(string textToEncrypt, out string publicKey,
    out string privateKey)
{
    byte[] bytesToEncrypt = ByteConverter.GetBytes(textToEncrypt);
    byte[] encryptedBytes;
    using (var rsa = new RSACryptoServiceProvider())
    {
        encryptedBytes = rsa.Encrypt(bytesToEncrypt, false);
        publicKey = rsa.ToXmlString(false);
        privateKey = rsa.ToXmlString(true);
    }
    return ByteConverter.GetString(encryptedBytes);
}
Run Code Online (Sandbox Code Playgroud)

整个ByteConverter使用的只是以下内容:

public static readonly UnicodeEncoding ByteConverter = new UnicodeEncoding();
Run Code Online (Sandbox Code Playgroud)

我在StackOverflow上看到了一些关于RSA加密和.NET解密的问题. 这个是由于使用私钥加密并尝试使用公钥解密,但我不认为我这样做. 这个问题与我有相同的例外,但选择的答案是使用OpenSSL.NET,我不想这样做.

我究竟做错了什么?

SwD*_*n81 8

你可以取代ByteConverter.GetBytes使用Convert.FromBase64String和替换ByteConverter.GetStringConvert.ToBase64String,看看是否有帮助. Bad Data异常通常表示数据中包含无效字符或者长度不是正确的解密长度.我认为使用Convert函数可能会解决您的问题.

  public static readonly UnicodeEncoding ByteConverter = new UnicodeEncoding();

  public static string Encrypt(string textToEncrypt, out string publicKey,
    out string privateKey)
  {
     byte[] bytesToEncrypt = ByteConverter.GetBytes(textToEncrypt);
     byte[] encryptedBytes;
     using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
     {
        encryptedBytes = rsa.Encrypt(bytesToEncrypt, false);
        publicKey = rsa.ToXmlString(false);
        privateKey = rsa.ToXmlString(true);
     }
     return Convert.ToBase64String(encryptedBytes);
  }

  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 (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
     {
        rsa.FromXmlString(privateKeyXml);
        decryptedBytes = rsa.Decrypt(bytesToDecrypt, false); // fail here
     }
     return ByteConverter.GetString(decryptedBytes);
  }
Run Code Online (Sandbox Code Playgroud)