php到C#一个JSON数据数组,使用Rijindael-256算法加密,使用base64算法编码
我正在尝试将以下php代码转换为C:php到C#一个JSON数据数组,使用Rijindael-256算法加密,使用base64算法编码,c#,php,api,encryption,aes,C#,Php,Api,Encryption,Aes,我正在尝试将以下php代码转换为C: $m_params = urlencode(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256,$key, json_encode($arParams), MCRYPT_MODE_ECB))); var additional_params = new object[] { new {&quo
$m_params = urlencode(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256,$key, json_encode($arParams), MCRYPT_MODE_ECB)));
var additional_params = new object[]
{
new {"http://google.com/new_success_url"},
new {"http://google.com/new_fail_url"},
new {"http://google.com/new_status_url"},
};
string m_params ="";
//converting to Json object additional params
var jsonEncoded = JsonConvert.SerializeObject(additional_params);
try
{
string original = jsonEncoded;
// Create a new instance of the RijndaelManaged
// class. This generates a new key and initialization
// vector (IV).
using (RijndaelManaged myRijndael = new RijndaelManaged())
{
var final_Key = CreateMD5(payeer.m_key + payeer.m_orderid);
var rfc = CreateKey(final_Key);
// Encrypt the string to an array of bytes.
byte[] encrypted = EncryptStringToBytes(original, rfc[0], rfc[1]);
var base64String = Convert.ToBase64String(encrypted);
m_params = HttpUtility.UrlEncode(base64String, Encoding.UTF8);
// Decrypt the bytes to a string.
string roundtrip = DecryptStringFromBytes(encrypted, rfc[0], rfc[1]);
//Display the original data and the decrypted data.
Console.WriteLine("Original: {0}", original);
Console.WriteLine("Round Trip: {0}", roundtrip);
}
static byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
byte[] encrypted;
// Create an RijndaelManaged object
// with the specified key and IV.
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
rijAlg.Mode = CipherMode.ECB;
// rijAlg.KeySize = 256;
rijAlg.BlockSize = 256;
rijAlg.Padding = PaddingMode.PKCS7;
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
public static string CreateMD5(string input)
{
// Use input string to calculate MD5 hash
using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
{
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes);
// Convert the byte array to hexadecimal string
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
{
sb.Append(hashBytes[i].ToString("X2"));
}
return sb.ToString();
}
}
public static dynamic CreateKey(string password)
{
var salt = new byte[] { 1, 2, 23, 234, 37, 48, 134, 63, 248, 4 };
const int Iterations = 9872;
using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, Iterations))
{
var key = rfc2898DeriveBytes.GetBytes(32);
var IV = rfc2898DeriveBytes.GetBytes(16);
dynamic[] arr = new dynamic[2];
arr[0] = key;
arr[1] = IV;
return arr;
}
}
文档内容:
$m_params = urlencode(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256,$key, json_encode($arParams), MCRYPT_MODE_ECB)));
var additional_params = new object[]
{
new {"http://google.com/new_success_url"},
new {"http://google.com/new_fail_url"},
new {"http://google.com/new_status_url"},
};
string m_params ="";
//converting to Json object additional params
var jsonEncoded = JsonConvert.SerializeObject(additional_params);
try
{
string original = jsonEncoded;
// Create a new instance of the RijndaelManaged
// class. This generates a new key and initialization
// vector (IV).
using (RijndaelManaged myRijndael = new RijndaelManaged())
{
var final_Key = CreateMD5(payeer.m_key + payeer.m_orderid);
var rfc = CreateKey(final_Key);
// Encrypt the string to an array of bytes.
byte[] encrypted = EncryptStringToBytes(original, rfc[0], rfc[1]);
var base64String = Convert.ToBase64String(encrypted);
m_params = HttpUtility.UrlEncode(base64String, Encoding.UTF8);
// Decrypt the bytes to a string.
string roundtrip = DecryptStringFromBytes(encrypted, rfc[0], rfc[1]);
//Display the original data and the decrypted data.
Console.WriteLine("Original: {0}", original);
Console.WriteLine("Round Trip: {0}", roundtrip);
}
static byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
byte[] encrypted;
// Create an RijndaelManaged object
// with the specified key and IV.
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
rijAlg.Mode = CipherMode.ECB;
// rijAlg.KeySize = 256;
rijAlg.BlockSize = 256;
rijAlg.Padding = PaddingMode.PKCS7;
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
public static string CreateMD5(string input)
{
// Use input string to calculate MD5 hash
using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
{
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes);
// Convert the byte array to hexadecimal string
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
{
sb.Append(hashBytes[i].ToString("X2"));
}
return sb.ToString();
}
}
public static dynamic CreateKey(string password)
{
var salt = new byte[] { 1, 2, 23, 234, 37, 48, 134, 63, 248, 4 };
const int Iterations = 9872;
using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, Iterations))
{
var key = rfc2898DeriveBytes.GetBytes(32);
var IV = rfc2898DeriveBytes.GetBytes(16);
dynamic[] arr = new dynamic[2];
arr[0] = key;
arr[1] = IV;
return arr;
}
}
m_params:数据的JSON数组
附加参数
使用
Rijindael-256算法及其应用
使用base64编码
算法
我的假设是什么?
步骤1:创建一个参数数组,即$arParams
对于php,其声明如下:
$arParams = array(
'success_url' => 'http://google.com/new_success_url',
'fail_url' => 'http://google.com/new_fail_url',
'status_url' => 'http://google.com/new_status_url',
);
对于C#我这样宣布:
var additional_params = new object[]
{
new {"http://google.com/new_success_url"},
new {"http://google.com/new_fail_url"},
new {"http://google.com/new_status_url"},
};
步骤2:编码为JSON字符串,我使用了JsonConvert.SerializeObject(附加参数)代码>
第3步:使用ECB使用RIJNDAEL-256算法加密结果(我也使用了CBC)
步骤4:使用base64对结果进行编码。我使用了Convert.ToBase64String(加密)代码>
步骤5:Url编码结果。我使用了HttpUtility.UrlEncode(base64String,Encoding.UTF8)代码>
步骤6:将结果保存在m_参数中
我当前的代码如下所示:
$m_params = urlencode(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256,$key, json_encode($arParams), MCRYPT_MODE_ECB)));
var additional_params = new object[]
{
new {"http://google.com/new_success_url"},
new {"http://google.com/new_fail_url"},
new {"http://google.com/new_status_url"},
};
string m_params ="";
//converting to Json object additional params
var jsonEncoded = JsonConvert.SerializeObject(additional_params);
try
{
string original = jsonEncoded;
// Create a new instance of the RijndaelManaged
// class. This generates a new key and initialization
// vector (IV).
using (RijndaelManaged myRijndael = new RijndaelManaged())
{
var final_Key = CreateMD5(payeer.m_key + payeer.m_orderid);
var rfc = CreateKey(final_Key);
// Encrypt the string to an array of bytes.
byte[] encrypted = EncryptStringToBytes(original, rfc[0], rfc[1]);
var base64String = Convert.ToBase64String(encrypted);
m_params = HttpUtility.UrlEncode(base64String, Encoding.UTF8);
// Decrypt the bytes to a string.
string roundtrip = DecryptStringFromBytes(encrypted, rfc[0], rfc[1]);
//Display the original data and the decrypted data.
Console.WriteLine("Original: {0}", original);
Console.WriteLine("Round Trip: {0}", roundtrip);
}
static byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
byte[] encrypted;
// Create an RijndaelManaged object
// with the specified key and IV.
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
rijAlg.Mode = CipherMode.ECB;
// rijAlg.KeySize = 256;
rijAlg.BlockSize = 256;
rijAlg.Padding = PaddingMode.PKCS7;
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
public static string CreateMD5(string input)
{
// Use input string to calculate MD5 hash
using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
{
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes);
// Convert the byte array to hexadecimal string
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
{
sb.Append(hashBytes[i].ToString("X2"));
}
return sb.ToString();
}
}
public static dynamic CreateKey(string password)
{
var salt = new byte[] { 1, 2, 23, 234, 37, 48, 134, 63, 248, 4 };
const int Iterations = 9872;
using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, Iterations))
{
var key = rfc2898DeriveBytes.GetBytes(32);
var IV = rfc2898DeriveBytes.GetBytes(16);
dynamic[] arr = new dynamic[2];
arr[0] = key;
arr[1] = IV;
return arr;
}
}
var附加参数=新对象[]
{
新{”http://google.com/new_success_url"},
新{”http://google.com/new_fail_url"},
新{”http://google.com/new_status_url"},
};
字符串m_params=“”;
//转换为Json对象附加参数
var jsonEncoded=JsonConvert.SerializeObject(附加参数);
尝试
{
字符串original=jsonEncoded;
//创建RijndaelManaged的新实例
//这将生成一个新的密钥和初始化
//载体(IV)。
使用(RijndaelManaged myRijndael=new RijndaelManaged())
{
var final_Key=CreateMD5(payer.m_Key+payer.m_orderid);
var rfc=CreateKey(最终密钥);
//将字符串加密为字节数组。
byte[]encrypted=EncryptStringToBytes(原始,rfc[0],rfc[1]);
var base64String=Convert.ToBase64String(加密);
m_params=HttpUtility.UrlEncode(base64String,Encoding.UTF8);
//将字节解密为字符串。
字符串往返=解密StringFromBytes(加密,rfc[0],rfc[1]);
//显示原始数据和解密数据。
WriteLine(“原件:{0}”,原件);
WriteLine(“往返:{0}”,往返);
}
静态字节[]加密StringToBytes(字符串明文,字节[]密钥,字节[]IV)
{
//检查参数。
如果(plainText==null | | plainText.Length如詹姆斯·K·波尔克总统的评论所述,块大小为256位的Rijndael仅在.NET Framework中受支持,而在.NET Core中不受支持。您没有指定正在运行的版本,但因为在发布的代码中使用了256位的块大小(rijAlg.BlockSize=256;
),我假设您正在运行.NET Framework(否则,您需要应用支持块大小为256位的Rijndael的第三方库,例如BouncyCastle/C#)
两种代码使用不同的填充。mcrypt
默认情况下应用零填充,C代码显式使用PKCS7填充(这也是C的默认值)。因此,C代码提供与PHP代码相同的结果,因此有必要在C代码中切换到零填充(应该注意,与PKCS7填充不同,零填充是不可靠的)
当实例化附加参数时(顺便说一句,它在我的机器上不编译),变量名丢失,因此在序列化中也会丢失。可以使用匿名类型。另外,请注意json\u encode()
转义斜杠(/
)默认情况下,即将其转换为\/
,这必须在C代码中手动完成,例如使用替换(“/”,“\\/”)
。JSON序列化的一种可能实现方式是:
using Newtonsoft.Json;
...
var additionalParams = new
{
success_url = "http://google.com/new_success_url",
fail_url = "http://google.com/new_fail_url",
status_url = "http://google.com/new_status_url"
};
string jsonEncoded = JsonConvert.SerializeObject(additionalParams).Replace("/", "\\/");
在PHP代码中,密钥是使用MD5摘要从密码中派生出来的。默认情况下,以十六进制字符串的形式返回结果,该字符串将16个字节的哈希值转换为32个字节的值,并作为密钥应用,因此使用AES-256。PHP用小写字母表示十六进制数字,也必须在中相应地实现C代码,例如:
using System;
using System.Text;
using System.Security.Cryptography;
...
MD5 md5 = MD5.Create();
string password = "My password"; // test password
byte[] passwordHash = md5.ComputeHash(Encoding.UTF8.GetBytes(password));
string passwordHashHex = BitConverter.ToString(passwordHash).Replace("-", "").ToLower(); // convert byte array to lowercase hex string as in PHP
byte[] key = Encoding.UTF8.GetBytes(passwordHashHex);
如果使用位转换器将字节数组转换为十六进制字符串,请参阅
加密的一种可能实现方式是:
using System;
using System.IO;
using System.Web;
using System.Text;
using System.Security.Cryptography;
...
byte[] encrypted = null;
using (RijndaelManaged rijndael = new RijndaelManaged())
{
rijndael.Key = key;
rijndael.Mode = CipherMode.ECB; // default: CBC
rijndael.BlockSize = 256; // default: 128
rijndael.Padding = PaddingMode.Zeros; // default: PKCS7
ICryptoTransform encryptor = rijndael.CreateEncryptor(rijndael.Key, null);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(jsonEncoded);
}
encrypted = msEncrypt.ToArray();
}
}
}
string base64String = Convert.ToBase64String(encrypted);
string m_params = HttpUtility.UrlEncode(base64String, Encoding.UTF8);
Console.WriteLine(m_params);
其中,此代码和使用的测试密码给出以下结果:
C3pldgsLDSqfG28cbt%2BV0UIBNQT6CWN86IRWG%2bv2blTzR7Lsnra%2b2Ok35Ex9f9UbG%2BJHKGITUQ8KO3DRIRWUQWIRZYZWGBUCHNRTHADF60RGUIBDJZ2KOIHDVZLMSZTBVYIGOFIQBJBHZQ9GGTABUOA5PCMIYUEN%2BQG1MDJUNVt8N0ETXSAD6CFC1%2bguR0wZx%2FZZ2FEZAMSBBRW%3d%
根据以下PHP代码的结果:
$key = md5('My password'); // test password
$arParams = array(
'success_url' => 'http://google.com/new_success_url',
'fail_url' => 'http://google.com/new_fail_url',
'status_url' => 'http://google.com/new_status_url',
);
$m_params = urlencode(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256,$key, json_encode($arParams), MCRYPT_MODE_ECB)));
print($m_params . "\n");
请注意,C#使用小写字母进行url编码,而PHP使用大写字母,表示相同的url编码,请参见。如果C#代码也应使用大写字母进行url编码,则可以使用正则表达式轻松实现,请参见例如
关于安全的几点意见:
PHP代码应用了不安全的ECB模式。出于安全原因,应使用带有IV的模式,例如CBC或GCM。后者提供隐式身份验证加密。IV是为每次加密随机生成的,不是秘密的,是s