RSA 解密期间的错误数据异常
Bad Data exception during RSA decryption
我正在做一个项目。加密工作正常,但在解密时我的程序抛出 "Bad data Exception"。我该如何解决这个问题?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Text;
using System.IO;
using System.Security.Cryptography;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
byte[] cipher;
byte[] plain;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private static string Encrypt(byte[] plain)
{
byte[] encrypted;
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
StreamReader StRe = new StreamReader("D:\PjesaVetemPublike.xml");
string VetemPublikeXML = StRe.ReadToEnd();
rsa.FromXmlString(VetemPublikeXML);
StRe.Close();
encrypted = rsa.Encrypt(plain, true);
return Encoding.UTF8.GetString(encrypted);
}
private static string Decrypt(byte[] encrypted)
{
byte[] decrypted;
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
StreamReader StRe = new
StreamReader("D:\PjesaPublikeDhePrivate.xml");
string PublikeDhePrivate = StRe.ReadToEnd();
rsa.FromXmlString(PublikeDhePrivate);
StRe.Close();
decrypted = rsa.Decrypt(encrypted, false); //THE ERROR APPEARS RIGHT HERE
return Encoding.UTF8.GetString(decrypted);
}
private void button1_Click(object sender, EventArgs e)
{
plain = Encoding.UTF8.GetBytes(txtPlain.Text);
txtCipher.Text = Encrypt(plain);
}
private void button2_Click(object sender, EventArgs e)
{
txtDekriptuar.Text = Decrypt(cipher);
}
}
}
假设您的密钥对是正确的,问题是您使用不同的 padding schemes 进行加密和解密。
传递给RSACryptoServiceProvider#Encrypt
和RSACryptoServiceProvider#Decrypt
的第二个参数表示是否使用OAEP。在加密期间您请求 OAEP,但在解密期间您请求 PKCS#1 v1.5 填充。那些不兼容。就用更安全的OAEP吧。
你应该使用
decrypted = rsa.Decrypt(encrypted, true);
在其他问题中,您假设密文可以有意义地转换为 UTF-8,但这并不能保证。
如果你想加密文本并且transmit/store加密的内容作为文本你需要遵循这个模式:
加密(文本输入 => 文本输出):
- 通过某种编码将 textIn 转换为 bytesIn。 UTF-8 已经很不错了。
- 将 bytesIn 加密为 bytesOut。
- 对 bytesOut 应用无损编码。 Base64 几乎总是为此的最佳选择,并且是 .NET 中内置的最佳选择。 (
textOut = Convert.ToBase64String(bytesOut)
).
- Return textOut.
解密(文本输入 => 文本输出):
- 应用 Encrypt 的逆变换将 textIn 转换为 bytesIn。很有可能
Convert.FromBase64String
.
- 将 bytesIn 解密为 bytesOut。
- 应用文本编码转换将 bytesOut 转换为 textOut。没有什么真正说明这需要与 Encrypt 中使用的相同,但这样做可能是有意义的。
使用 UTF-8(或 ASCII 或 UCS-2 等)作为加密数据的文本表示的问题在于,加密数据可以合法地包含值为 0x00
(或控制代码、换行符等)。虽然 .NET 在大多数情况下可以愉快地在字符串中传输嵌入的空字符,但它肯定会造成很大的混淆(而且并非所有 languages/functions 都以相同的方式处理它)。
其他有趣的角色:
- 您的 language/function 对嵌入式
0x7F
做了什么(删除)?
- 如果将字符串存储在单行文本字段中,CR 或 LF 字符会怎样?如果在没有 LF 的情况下获得 CR,或者在没有 CR 的情况下获得 LF,您的程序在 Windows 上会做什么?
- 带有
0x13
(^S) 的 Unix 命令行可能看起来挂起,但它只是在等待 0x11
(^Q)。
用什么编码来存储密文?好吧,任何安全包装控制字符的东西。
- Base64:存储增加 33%:3 字节 => 4 个 ASCII 字符 == 4 字节
- 十六进制(又名 Base16):存储增加 100%,但比 Base64 更容易检查
- 其他不太常见的选项总结在 https://en.wikipedia.org/wiki/Binary-to-text_encoding#Encoding_standards。
我正在做一个项目。加密工作正常,但在解密时我的程序抛出 "Bad data Exception"。我该如何解决这个问题?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Text;
using System.IO;
using System.Security.Cryptography;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
byte[] cipher;
byte[] plain;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private static string Encrypt(byte[] plain)
{
byte[] encrypted;
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
StreamReader StRe = new StreamReader("D:\PjesaVetemPublike.xml");
string VetemPublikeXML = StRe.ReadToEnd();
rsa.FromXmlString(VetemPublikeXML);
StRe.Close();
encrypted = rsa.Encrypt(plain, true);
return Encoding.UTF8.GetString(encrypted);
}
private static string Decrypt(byte[] encrypted)
{
byte[] decrypted;
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
StreamReader StRe = new
StreamReader("D:\PjesaPublikeDhePrivate.xml");
string PublikeDhePrivate = StRe.ReadToEnd();
rsa.FromXmlString(PublikeDhePrivate);
StRe.Close();
decrypted = rsa.Decrypt(encrypted, false); //THE ERROR APPEARS RIGHT HERE
return Encoding.UTF8.GetString(decrypted);
}
private void button1_Click(object sender, EventArgs e)
{
plain = Encoding.UTF8.GetBytes(txtPlain.Text);
txtCipher.Text = Encrypt(plain);
}
private void button2_Click(object sender, EventArgs e)
{
txtDekriptuar.Text = Decrypt(cipher);
}
}
}
假设您的密钥对是正确的,问题是您使用不同的 padding schemes 进行加密和解密。
传递给RSACryptoServiceProvider#Encrypt
和RSACryptoServiceProvider#Decrypt
的第二个参数表示是否使用OAEP。在加密期间您请求 OAEP,但在解密期间您请求 PKCS#1 v1.5 填充。那些不兼容。就用更安全的OAEP吧。
你应该使用
decrypted = rsa.Decrypt(encrypted, true);
在其他问题中,您假设密文可以有意义地转换为 UTF-8,但这并不能保证。
如果你想加密文本并且transmit/store加密的内容作为文本你需要遵循这个模式:
加密(文本输入 => 文本输出):
- 通过某种编码将 textIn 转换为 bytesIn。 UTF-8 已经很不错了。
- 将 bytesIn 加密为 bytesOut。
- 对 bytesOut 应用无损编码。 Base64 几乎总是为此的最佳选择,并且是 .NET 中内置的最佳选择。 (
textOut = Convert.ToBase64String(bytesOut)
). - Return textOut.
解密(文本输入 => 文本输出):
- 应用 Encrypt 的逆变换将 textIn 转换为 bytesIn。很有可能
Convert.FromBase64String
. - 将 bytesIn 解密为 bytesOut。
- 应用文本编码转换将 bytesOut 转换为 textOut。没有什么真正说明这需要与 Encrypt 中使用的相同,但这样做可能是有意义的。
使用 UTF-8(或 ASCII 或 UCS-2 等)作为加密数据的文本表示的问题在于,加密数据可以合法地包含值为 0x00
(或控制代码、换行符等)。虽然 .NET 在大多数情况下可以愉快地在字符串中传输嵌入的空字符,但它肯定会造成很大的混淆(而且并非所有 languages/functions 都以相同的方式处理它)。
其他有趣的角色:
- 您的 language/function 对嵌入式
0x7F
做了什么(删除)? - 如果将字符串存储在单行文本字段中,CR 或 LF 字符会怎样?如果在没有 LF 的情况下获得 CR,或者在没有 CR 的情况下获得 LF,您的程序在 Windows 上会做什么?
- 带有
0x13
(^S) 的 Unix 命令行可能看起来挂起,但它只是在等待0x11
(^Q)。
用什么编码来存储密文?好吧,任何安全包装控制字符的东西。
- Base64:存储增加 33%:3 字节 => 4 个 ASCII 字符 == 4 字节
- 十六进制(又名 Base16):存储增加 100%,但比 Base64 更容易检查
- 其他不太常见的选项总结在 https://en.wikipedia.org/wiki/Binary-to-text_encoding#Encoding_standards。