我用PHP和c#写了(我认为是)相同的加密函数。但是,加密相同的字符串不会产生相同的结果。我既不是c#也不是PHP的专家,所以我希望有人能够发现由于某种原因我在这里没有捕捉到的差异。
PHP功能:function encrypt($string, $key) {
$result = NULL;
for($i=0; $i<strlen($string); $i++) {
$char = substr($string, $i, 1);
$keychar = substr($key, ($i % strlen($key))-1, 1);
$char = chr(ord($char)+ord($keychar));
$result.=$char;
}
//return $result;
return $result;
}
c#功能: public static string encrypt_php_data(string stringToEncrypt, string key)
{
var result = string.Empty;
for (int i = 0; i < stringToEncrypt.Length; i++)
{
string keychar = phpSubStr_replacement(key, (i % key.Length) - 1);
result += (char)(Convert.ToChar(stringToEncrypt.Substring(i, 1)) + Convert.ToChar(keychar));
}
return result;
}
private static string phpSubStr_replacement(string stringToGrab, int startIndex)
{
if (startIndex < 0)
{
// Take from end of string
return stringToGrab.Substring(stringToGrab.Length + startIndex, 1);
}
else
{
// Take from beginning of string
return stringToGrab.Substring(startIndex, 1);
}
}
下面是对相同字符串加密的结果:
String encrypted: 09/16/2011 15:27:45
使用的密码:somekey
C# Result: ©¬©¤ «ª©¡
PHP Result: ©¬žž›š—©¤ – Ÿ«ª©¡š
注意:
并非所有输出都彼此不同。我不明白为什么有些不同,而另一些却产生相同的结果,这没有意义。
我期待你的回复,
艾凡首先,您确实应该使用密码学强的加密函数,因为像这种将单个字节与密钥字节相加的方案很容易被破解。也就是说,这两种代码输出不同的主要原因是PHP对8位ascii编码的字节执行加法运算,而c#对16位UTF-16编码单元执行加法运算(参见:. net内部编码)。
c#方面的"修复"是在执行加法操作之前将要加密的字符串和密钥转换为它们的ASCII编码:using System;
using System.Collections.Generic;
using System.Text;
namespace Test
{
public class SO7449615
{
public static string encrypt_php_data(string stringToEncrypt, string key) {
ASCIIEncoding asciiEncoding = new ASCIIEncoding();
byte[] stringToEncryptBytes = asciiEncoding.GetBytes(stringToEncrypt);
byte[] keyBytes = asciiEncoding.GetBytes(key);
byte[] retBytes = new byte[stringToEncryptBytes.Length];
for (int i = 0; i < stringToEncryptBytes.Length; ++i) {
byte keyByte = keyBytes[(i + keyBytes.Length - 1) % keyBytes.Length];
retBytes[i] = (byte)(stringToEncryptBytes[i] + keyByte);
//Console.Write(' ');
//Console.Write(retBytes[i]);
}
//Console.WriteLine();
return asciiEncoding.GetString(retBytes);
}
public static void Main(string[] args)
{
string stringToEncrypt = "test";
string key = "somekey";
Console.WriteLine(encrypt_php_data(stringToEncrypt, key));
}
}
}
它相当于您的原始PHP代码以及以下版本:
<?php
function encrypt($string, $key) {
$string_len = strlen($string);
$key_len = strlen($key);
$ret = "";
for ($i = 0; $i < $string_len; ++$i) {
$key_char = $key[($i + $key_len - 1) % $key_len];
$b = ord($string[$i]) + ord($key_char);
$ret .= chr($b);
//echo " $b";
}
//echo "'n";
return $ret;
}
echo encrypt("test", "somekey") . "'n";
但是,我还是不建议使用这些函数来加密数据。这个encrypt()
函数采用了一个很容易被破解的弱加密方案。此外,它不允许非ascii字符串被加密或用作密钥。
你提到你正在一个不允许扩展的web主机上运行PHP。您是否特别检查了加密扩展的存在?
用十六进制写输出,有很多字符是看不见的
您的"加密"功能可能会溢出。当您像在PHP版本中使用ord($char) + ord($keychar)
那样添加两个ASCII值时,您很容易得到一个不再是有效ASCII字符的值。PHP和c#可能会以不同的方式处理这个问题,这就是您所看到的。对于像数字这样的字符,它工作得很好,但对于像'''和':'这样的字符,它会变得混乱。
您确实应该在这里使用已建立的加密或编码函数,但如果您确实需要使用自己的加密或编码函数,则可能需要重新设计它,因为这个函数已经损坏。
我怀疑c#添加了键模2^16(它使用16位字符)和php模2^8使用8位字符。
而且你的c#代码非常臃肿。我将尝试如下操作:
public static string encrypt_php_data(string stringToEncrypt, string key)
{
var result = string.Empty;
for (int i = 0; i < stringToEncrypt.Length; i++)
{
char keychar = key[(i+key.Length- 1) % key.Length];
result += (char)((stringToEncrypt[i] + keychar));
}
return result;
}