c# - 使用 RSA 加密/解密时间歇性出现 CryptographicException

标签 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");

它在解密过程中失败,但只是偶尔失败。似乎每当我设置断点并单步执行测试时,它就会通过。这让我觉得也许有些事情没有及时完成才能成功解密,我在调试时放慢了步进速度,给了它足够的时间来完成。当它失败时,它似乎失败的行是 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);
}

失败并出现以下异常:

System.Security.Cryptography.CryptographicException: Bad Data

我的加密方法如下:

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);
}

整个过程中使用的 ByteConverter 如下:

public static readonly UnicodeEncoding ByteConverter = new UnicodeEncoding();

我在 StackOverflow 上看到了一些关于使用 .NET 进行 RSA 加密和解密的问题。 This one是由于使用私钥加密并尝试使用公钥解密,但我不认为我正在这样做。 This question和我有同样的异常(exception),但选择的答案是使用 OpenSSL.NET,我不想这样做。

我做错了什么?

最佳答案

能否将 ByteConverter.GetBytes 替换为 Convert.FromBase64String 并将 ByteConverter.GetString 替换为 Convert.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);
  }

关于c# - 使用 RSA 加密/解密时间歇性出现 CryptographicException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3152698/

相关文章:

c# - 如何使用 Linq 获取 sitecore 字段

security - 如何防止密码被保存?

php - PHP 的 "HTTP_X_FORWARDED_FOR"或 "HTTP_CLIENT_IP"与 "REMOTE_ADDR"不同是否有任何合法原因?

encryption - 安全的随机种子和 derby 数据库创建

javascript - 可搜索的加密方法(对于傻瓜来说!)

c# - 为什么添加 Microsoft.Bcl.Async 包后,app.config 文件中会添加一个 "bindingRedirect"?

c# - 将 DataGridView 绑定(bind)到 List<>,某些属性不应显示

c# - 获取前 3 个最受欢迎的项目 c# linq EF

oauth-2.0 - 作为 OAuth 服务器,我应该如何生成和存储 OAuth 2.0 token ?

android - 尝试在android中解密加密数据库时出现"File is encrypted or is not a database"错误