C++(crypto++)与C#加密匹配
C ++ (crypto ++) and C # encryption matching
为了客户端和服务器之间的安全通信,我想对来自客户端和服务器的数据进行加密和解密,但是我无法得到相同的结果,从客户端到服务器的数据没有解密,同样,当从服务器加密相同的相同数据时,我从客户端加密得到了一个独特的结果。
客户端是使用 Crypto ++ 用 C ++ 编写的。代码:
string data = "teststring,teststring,teststring";
string encryptedData = client.encrypt(userData, "01234567891234560123456789123456", "0123456789123456");
string Client::encrypt(const string& str_in, const string& key, const string& iv)
{
try {
string str_out;
AES::Encryption aesEncryption((byte*)key.c_str(), key.length());
CBC_Mode_ExternalCipher::Encryption encryption(aesEncryption, (byte*)iv.c_str());
StringSource encryptor(str_in, true,
new StreamTransformationFilter(encryption,
new Base64Encoder(
new StringSink(str_out),
false
)
)
);
return str_out;
}
catch (exception e) {
return "null";
}
}
string Client::decrypt(const string& str_in, const string& key, const string& iv)
{
try {
string str_out;
CBC_Mode<AES>::Decryption decryption((byte*)key.c_str(), key.length(), (byte*)iv.c_str());
StringSource decryptor(str_in, true,
new Base64Decoder(
new StreamTransformationFilter(decryption,
new StringSink(str_out)
)
)
);
return str_out;
}
catch (exception e) {
return "null";
}
}
给出以下输出:
data: "teststring,teststring,teststring"
encryptedData: "STpuD/dRgYard+Yqpdd5KOYET7607i7ZRUoKm5eshHzR3ErafaxgZ2+T1tSp0lWJ"
服务器端的代码是用C#写的(ASP.NET Core 3.1):
public static string Encrypt(string input)
{
byte[] clearBytes = Encoding.Default.GetBytes(input);
using (Aes encryptor = Aes.Create("AES"))
{
// encryptor.BlockSize = 32;
encryptor.Padding = PaddingMode.Zeros;
encryptor.KeySize = 128;
encryptor.Mode = CipherMode.CBC;
encryptor.Key = Encoding.Default.GetBytes("01286567891233460123456789123456");
encryptor.IV = Encoding.Default.GetBytes("0123456789123456");
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
byte[] bt = ms.ToArray();
input = Convert.ToBase64String(bt);
}
}
return input;
}
public static string Decrypt(string input)
{
byte[] clearBytes = Encoding.ASCII.GetBytes(input);
using (Aes decryptor = Aes.Create("AES"))
{
//decryptor.BlockSize = 32;
decryptor.Padding = PaddingMode.Zeros;
decryptor.KeySize = 128;
decryptor.Mode = CipherMode.CBC;
decryptor.Key = Encoding.ASCII.GetBytes("01234567891234560123456789123456");
decryptor.IV = Encoding.ASCII.GetBytes("0123456789123456");
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, decryptor.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
byte[] bt = ms.ToArray();
input = Encoding.ASCII.GetString(bt);
}
}
return input;
}
输出:
data: "teststring,teststring,teststring"
encryptedData: "tIDlWnnzOQWh5HIvRDJya6z7jOglkIlYrICeYW9RoEM="
我无法解密来自客户端和服务器的数据。请帮助我。
张贴的C++代码很好。它 returns 在我的机器上发布的密文 STpu...0lWJ
并且密文可以用 decrypt()
方法解密。
相比之下,虽然贴出C#代码returns贴出密文tIDl...RoEM=
,但密文无法使用Decrypt()
方法解密。这有两个原因:
- 在
Encrypt()
和 Decrypt()
方法中使用了不同的键。 Decrypt()
方法的键与 C++ 代码中应用的键匹配。关于两个密码的密文比较,Encrypt()
方法中的密钥应该被替换。
- 密文在
Encrypt()
方法中是Base64编码的,但在Decrypt()
方法中不是Base64解码的(而是ASCII编码)。这里必须在 Decrypt()
方法中进行 Base64 解码(请注意,Encrypt()
方法中的 ASCII 解码不是替代方案,因为这会破坏密文)。
如果修复这两个bug,C++和C#代码的密文除尾部外都匹配。最后一个不匹配是由不同的填充引起的。在 C++ 代码中使用 PKCS7 填充,在 C# 代码中使用零填充。如果将 C# 代码中的填充(在 Encrypt()
和 Decrypt()
方法中)更改为 PaddingMode.PKCS7
,则密文匹配。
C# 代码中的其他问题是:
- 在
Encrypt()
方法中使用Encoding.Default
,在Decrypt()
方法中使用Encoding.ASCII
。这里是一致的编码,例如Encoding.UTF8
应适用。
- 指定的 128 位密钥大小与使用的 256 位密钥不一致。这没有任何效果,因为显式密钥规范会自动更正密钥大小(尽管如此,应正确指定或完全省略密钥大小)。
此外,需要注意的是静态 IV 是不安全的(出于测试目的,当然没关系)。
为了客户端和服务器之间的安全通信,我想对来自客户端和服务器的数据进行加密和解密,但是我无法得到相同的结果,从客户端到服务器的数据没有解密,同样,当从服务器加密相同的相同数据时,我从客户端加密得到了一个独特的结果。
客户端是使用 Crypto ++ 用 C ++ 编写的。代码:
string data = "teststring,teststring,teststring";
string encryptedData = client.encrypt(userData, "01234567891234560123456789123456", "0123456789123456");
string Client::encrypt(const string& str_in, const string& key, const string& iv)
{
try {
string str_out;
AES::Encryption aesEncryption((byte*)key.c_str(), key.length());
CBC_Mode_ExternalCipher::Encryption encryption(aesEncryption, (byte*)iv.c_str());
StringSource encryptor(str_in, true,
new StreamTransformationFilter(encryption,
new Base64Encoder(
new StringSink(str_out),
false
)
)
);
return str_out;
}
catch (exception e) {
return "null";
}
}
string Client::decrypt(const string& str_in, const string& key, const string& iv)
{
try {
string str_out;
CBC_Mode<AES>::Decryption decryption((byte*)key.c_str(), key.length(), (byte*)iv.c_str());
StringSource decryptor(str_in, true,
new Base64Decoder(
new StreamTransformationFilter(decryption,
new StringSink(str_out)
)
)
);
return str_out;
}
catch (exception e) {
return "null";
}
}
给出以下输出:
data: "teststring,teststring,teststring"
encryptedData: "STpuD/dRgYard+Yqpdd5KOYET7607i7ZRUoKm5eshHzR3ErafaxgZ2+T1tSp0lWJ"
服务器端的代码是用C#写的(ASP.NET Core 3.1):
public static string Encrypt(string input)
{
byte[] clearBytes = Encoding.Default.GetBytes(input);
using (Aes encryptor = Aes.Create("AES"))
{
// encryptor.BlockSize = 32;
encryptor.Padding = PaddingMode.Zeros;
encryptor.KeySize = 128;
encryptor.Mode = CipherMode.CBC;
encryptor.Key = Encoding.Default.GetBytes("01286567891233460123456789123456");
encryptor.IV = Encoding.Default.GetBytes("0123456789123456");
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
byte[] bt = ms.ToArray();
input = Convert.ToBase64String(bt);
}
}
return input;
}
public static string Decrypt(string input)
{
byte[] clearBytes = Encoding.ASCII.GetBytes(input);
using (Aes decryptor = Aes.Create("AES"))
{
//decryptor.BlockSize = 32;
decryptor.Padding = PaddingMode.Zeros;
decryptor.KeySize = 128;
decryptor.Mode = CipherMode.CBC;
decryptor.Key = Encoding.ASCII.GetBytes("01234567891234560123456789123456");
decryptor.IV = Encoding.ASCII.GetBytes("0123456789123456");
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, decryptor.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
byte[] bt = ms.ToArray();
input = Encoding.ASCII.GetString(bt);
}
}
return input;
}
输出:
data: "teststring,teststring,teststring"
encryptedData: "tIDlWnnzOQWh5HIvRDJya6z7jOglkIlYrICeYW9RoEM="
我无法解密来自客户端和服务器的数据。请帮助我。
张贴的C++代码很好。它 returns 在我的机器上发布的密文 STpu...0lWJ
并且密文可以用 decrypt()
方法解密。
相比之下,虽然贴出C#代码returns贴出密文tIDl...RoEM=
,但密文无法使用Decrypt()
方法解密。这有两个原因:
- 在
Encrypt()
和Decrypt()
方法中使用了不同的键。Decrypt()
方法的键与 C++ 代码中应用的键匹配。关于两个密码的密文比较,Encrypt()
方法中的密钥应该被替换。 - 密文在
Encrypt()
方法中是Base64编码的,但在Decrypt()
方法中不是Base64解码的(而是ASCII编码)。这里必须在Decrypt()
方法中进行 Base64 解码(请注意,Encrypt()
方法中的 ASCII 解码不是替代方案,因为这会破坏密文)。
如果修复这两个bug,C++和C#代码的密文除尾部外都匹配。最后一个不匹配是由不同的填充引起的。在 C++ 代码中使用 PKCS7 填充,在 C# 代码中使用零填充。如果将 C# 代码中的填充(在 Encrypt()
和 Decrypt()
方法中)更改为 PaddingMode.PKCS7
,则密文匹配。
C# 代码中的其他问题是:
- 在
Encrypt()
方法中使用Encoding.Default
,在Decrypt()
方法中使用Encoding.ASCII
。这里是一致的编码,例如Encoding.UTF8
应适用。 - 指定的 128 位密钥大小与使用的 256 位密钥不一致。这没有任何效果,因为显式密钥规范会自动更正密钥大小(尽管如此,应正确指定或完全省略密钥大小)。
此外,需要注意的是静态 IV 是不安全的(出于测试目的,当然没关系)。