解密在 PHP 中加密的 C# 字符串(Blowfish)
Decrypt string in C# encrypted in PHP (Blowfish)
我正在努力尝试解密在 PHP 中加密的 C# 中的一些值。 PHP 中的加密是使用以下方法完成的:
function encrypt($pure_string, $encryption_key) {
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
$iv = 'fÔdñá1f¦';
$encrypted_string = mcrypt_encrypt(MCRYPT_BLOWFISH, $encryption_key, utf8_encode($pure_string), MCRYPT_MODE_ECB, $iv);
$encrypted_string = base64_encode($encrypted_string);
return $encrypted_string;
}
由于使用了 ECB 模式,IV 可能未使用它,但这仍然无济于事。最大的问题是 PHP 文档太差了,它没有指定函数使用的编码!传递的字符串根据编码具有不同的字节值,最终加密(在本例中为 Blowfish)处理字节。
在不知道编码的情况下,我只是在我的 C# 代码中尝试不同的编码,但没有成功。我在某处读到 PHP 正在使用内部 "iso-8859-1" 编码,但即使这样它也不起作用。
有没有人在 C# 中使用愚蠢的函数 mcrypt_encrypt() 成功解密了一些在 PHP 中加密的值?
更新
我在PHP中做了一个例子。代码:
define("ENCRYPTION_KEY", "1234asdf");
define("IV", "1#^ÊÁñÔ0");
$clearText = "abc";
function encrypt($pure_string, $encryption_key, $iv) {
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
$encrypted_string = mcrypt_encrypt(MCRYPT_BLOWFISH, $encryption_key, utf8_encode($pure_string), MCRYPT_MODE_ECB, $iv);
$encrypted_string = base64_encode($encrypted_string);
return $encrypted_string;
}
$encrypted_string = encrypt($clearText, ENCRYPTION_KEY, IV);
echo "Key:" . ENCRYPTION_KEY . "<br />";
echo "IV:" . IV . "<br />";
echo "Clear Text:" . $clearText . "<br />";
echo "Encrypted Text:" . $encrypted_string . "<br />";
结果是:
Key:1234asdf
IV:1#^ÊÁñÔ0
Clear Text:abc
Encrypted Text:OiZ6QIdhXYk=
另外我确认没有使用IV,我传递的任何值结果都是一样的。
最后还是做到了。几点建议:
C# 中的某些 Blowfish 库似乎实现不佳。正确工作的是 https://github.com/b1thunt3r/blowfish-csharp
切勿使用直接处理字符串的方法。首先在任何库中提供这都是愚蠢的(即使是上面的库也有与字符串一起使用的重载,并且 "supposes" 字符串是 Unicode!)
在处理不同平台的时候,尽量说服对方使用base64编码
最后,我很惊讶为什么这么多开发人员(甚至是开发加密库的开发人员)不明白使用字符串而不指定编码是愚蠢的,没有任何意义!
好吧,你案例中的问题 不是 c# 中的河豚解密部分,而是 php 中的加密部分。不,这不是关于使用 mcrypt_encrypt
,而是在已经 utf8 编码的字符串上调用 utf8_encode
是错误的...
我创建的解密函数使用了BouncyCastle。有两个加密字符串,第一个是使用您发布的 php 函数创建的,对于第二个,我删除了 mbcrypt_encrypt
.[=17= 中的 utf8_encode
调用]
第一个样本使用了(错误的)php_utf8_encoded字符串,我们需要将解密后的字节数组来回转换才能得到正确的结果。
调试c#解密函数的第二次调用,看看Encoding.UTF8.GetBytes
生成的第一个str1
的结果。没错,没有字符集的来回转换。
public static string BlowfishDecrypt(string encrypted, string key)
{
var cipher = new BufferedBlockCipher(new BlowfishEngine());
var k = new KeyParameter(Encoding.UTF8.GetBytes(key));
cipher.Init(false, k);
var input = Convert.FromBase64String(encrypted);
var length = cipher.GetOutputSize(input.Length);
var block = new byte[length];
var len = cipher.ProcessBytes(input, 0, input.Length, block, 0);
var output = cipher.DoFinal(block, len);
// dont know how we get the real length of the content here... but this will do it. But I am sure there is a better way...
var idx = Array.IndexOf(block, (byte)0);
var str1 = Encoding.UTF8.GetString(block, 0, idx);
var raw1 = Encoding.GetEncoding("iso-8859-1").GetBytes(str1);
var str2 = Encoding.UTF8.GetString(raw1);
return str2;
}
static string original = "@€~>|";
static string encrypted_with_utf8_encode = "7+XyF+QGcA8lz5AQlLf1FA==";
static string encrypted_without = "3oWsAOEF+Kc=";
static string key = "t0ps3cr3t";
public static void Main()
{
var decrypted1 = BlowfishDecrypt(encrypted_with_utf8_encode, key);
var decrypted2 = BlowfishDecrypt(encrypted_without, key);
var same = original.Equals(decrypted1);
Debugger.Break();
}
我正在努力尝试解密在 PHP 中加密的 C# 中的一些值。 PHP 中的加密是使用以下方法完成的:
function encrypt($pure_string, $encryption_key) {
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
$iv = 'fÔdñá1f¦';
$encrypted_string = mcrypt_encrypt(MCRYPT_BLOWFISH, $encryption_key, utf8_encode($pure_string), MCRYPT_MODE_ECB, $iv);
$encrypted_string = base64_encode($encrypted_string);
return $encrypted_string;
}
由于使用了 ECB 模式,IV 可能未使用它,但这仍然无济于事。最大的问题是 PHP 文档太差了,它没有指定函数使用的编码!传递的字符串根据编码具有不同的字节值,最终加密(在本例中为 Blowfish)处理字节。
在不知道编码的情况下,我只是在我的 C# 代码中尝试不同的编码,但没有成功。我在某处读到 PHP 正在使用内部 "iso-8859-1" 编码,但即使这样它也不起作用。
有没有人在 C# 中使用愚蠢的函数 mcrypt_encrypt() 成功解密了一些在 PHP 中加密的值?
更新
我在PHP中做了一个例子。代码:
define("ENCRYPTION_KEY", "1234asdf");
define("IV", "1#^ÊÁñÔ0");
$clearText = "abc";
function encrypt($pure_string, $encryption_key, $iv) {
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
$encrypted_string = mcrypt_encrypt(MCRYPT_BLOWFISH, $encryption_key, utf8_encode($pure_string), MCRYPT_MODE_ECB, $iv);
$encrypted_string = base64_encode($encrypted_string);
return $encrypted_string;
}
$encrypted_string = encrypt($clearText, ENCRYPTION_KEY, IV);
echo "Key:" . ENCRYPTION_KEY . "<br />";
echo "IV:" . IV . "<br />";
echo "Clear Text:" . $clearText . "<br />";
echo "Encrypted Text:" . $encrypted_string . "<br />";
结果是:
Key:1234asdf
IV:1#^ÊÁñÔ0
Clear Text:abc
Encrypted Text:OiZ6QIdhXYk=
另外我确认没有使用IV,我传递的任何值结果都是一样的。
最后还是做到了。几点建议:
C# 中的某些 Blowfish 库似乎实现不佳。正确工作的是 https://github.com/b1thunt3r/blowfish-csharp
切勿使用直接处理字符串的方法。首先在任何库中提供这都是愚蠢的(即使是上面的库也有与字符串一起使用的重载,并且 "supposes" 字符串是 Unicode!)
在处理不同平台的时候,尽量说服对方使用base64编码
最后,我很惊讶为什么这么多开发人员(甚至是开发加密库的开发人员)不明白使用字符串而不指定编码是愚蠢的,没有任何意义!
好吧,你案例中的问题 不是 c# 中的河豚解密部分,而是 php 中的加密部分。不,这不是关于使用 mcrypt_encrypt
,而是在已经 utf8 编码的字符串上调用 utf8_encode
是错误的...
我创建的解密函数使用了BouncyCastle。有两个加密字符串,第一个是使用您发布的 php 函数创建的,对于第二个,我删除了 mbcrypt_encrypt
.[=17= 中的 utf8_encode
调用]
第一个样本使用了(错误的)php_utf8_encoded字符串,我们需要将解密后的字节数组来回转换才能得到正确的结果。
调试c#解密函数的第二次调用,看看Encoding.UTF8.GetBytes
生成的第一个str1
的结果。没错,没有字符集的来回转换。
public static string BlowfishDecrypt(string encrypted, string key)
{
var cipher = new BufferedBlockCipher(new BlowfishEngine());
var k = new KeyParameter(Encoding.UTF8.GetBytes(key));
cipher.Init(false, k);
var input = Convert.FromBase64String(encrypted);
var length = cipher.GetOutputSize(input.Length);
var block = new byte[length];
var len = cipher.ProcessBytes(input, 0, input.Length, block, 0);
var output = cipher.DoFinal(block, len);
// dont know how we get the real length of the content here... but this will do it. But I am sure there is a better way...
var idx = Array.IndexOf(block, (byte)0);
var str1 = Encoding.UTF8.GetString(block, 0, idx);
var raw1 = Encoding.GetEncoding("iso-8859-1").GetBytes(str1);
var str2 = Encoding.UTF8.GetString(raw1);
return str2;
}
static string original = "@€~>|";
static string encrypted_with_utf8_encode = "7+XyF+QGcA8lz5AQlLf1FA==";
static string encrypted_without = "3oWsAOEF+Kc=";
static string key = "t0ps3cr3t";
public static void Main()
{
var decrypted1 = BlowfishDecrypt(encrypted_with_utf8_encode, key);
var decrypted2 = BlowfishDecrypt(encrypted_without, key);
var same = original.Equals(decrypted1);
Debugger.Break();
}