php中的c#MCRYPT_RIJNDAEL_256加密解密类
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了php中的c#MCRYPT_RIJNDAEL_256加密解密类,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5839字,纯文字阅读大概需要9分钟。
内容图文
![php中的c#MCRYPT_RIJNDAEL_256加密解密类](/upload/InfoBanner/zyjiaocheng/686/99809c3d6b7e4fb3ab995523e3acfbd2.jpg)
我正在尝试将c#应用程序转换为php,但我停留在C#提供基于RIJNDAEL算法进行加密和解密的Security类的地方.我正在尝试转换成PHP.
注意:我使用的是php 7.2,因此该版本不建议使用mcrypt.
C#代码
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace pharmarackencryption
{
class Program
{
private const string initVector = "aw90rela942f65u2";
// This constant is used to determine the keysize of the encryption algorithm.
private const int keysize = 256;
public static string Encrypt(string plainText, string passPhrase = "testing")
{
byte[] initVectorBytes = Encoding.UTF8.GetBytes(initVector);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null);
byte[] keyBytes = password.GetBytes(keysize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
memoryStream.Close();
cryptoStream.Close();
return Convert.ToBase64String(cipherTextBytes);
}
public static string Decrypt(string cipherText, string passPhrase = "testing")
{
byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null);
byte[] keyBytes = password.GetBytes(keysize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}
static void Main(string[] args)
{
Program p = new Program();
string enc_password = Encrypt("437217");
string dec_password = Decrypt("C9xJGa03dRQx9ePm0nLnHg==");
Console.WriteLine(enc_password);
Console.WriteLine(dec_password);
}
}
}
加密:C9xJGa03dRQx9ePm0nLnHg ==
我在php中找到了一些类似的代码
PHP代码:
<?php
// key/iv in ASCII binary data, $str base64
function decrypt_stuff($key, $str, $iv) {
// $plaintext_dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($str), MCRYPT_MODE_CBC, $iv);
$plaintext_dec = openssl_decrypt(base64_decode($str), "aes-256-cbc", $key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
return $plaintext_dec;
}
// key/iv in ascii binary data, $str ascii
function encrypt_stuff($key, $str, $iv) {
// $ciphertext = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $str, MCRYPT_MODE_CBC, $iv));
if (($l = (strlen($str) & 15)) > 0) { $str .= str_repeat(chr(0), 16 - $l); }
$ciphertext = base64_encode(openssl_encrypt($str, "aes-256-cbc", $key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv));
return $ciphertext;
}
echo encrypt_stuff("testing","437217","aw90rela942f65u2");
//Result : LTbhEHjFgfa5PDJQXJEdKQ==
两者都是一样的,但结果仍然不同
解决方法:
您的PHP代码产生不同的结果,因为您没有使用相同的密钥.在C#代码中,您正在使用PasswordDeriveBytes创建密钥,这是Microsoft PBKDF1的实现.
PHP不支持PBKDF1,但是我们可以编写一个与C#兼容的函数.下面的代码是由Maarten Bodewes的出色answer启发而来的,已翻译为PHP.
function passwordDeriveBytes($password, $salt, $iterations = 100, $len = 32) {
$key = $password . $salt;
for($i = 0; $i < $iterations; $i++) {
$key = sha1($key, true);
}
if (strlen($key) < $len) {
$hx = passwordDeriveBytes($password, $salt, $iterations - 1, 20);
$counter = 0;
while (strlen($key) < $len) {
$counter += 1;
$key .= sha1($counter . $hx, true);
}
}
return substr($key, 0, $len);
}
另外,您还需要bese64手动编码和填充数据.您正在执行零字节填充,但是在C#代码中,您正在使用PKCS7(默认和首选)填充.最好让openssl填充并编码数据.
function encrypt_stuff($key, $str, $iv) {
return openssl_encrypt($str, "aes-256-cbc", $key, 0, $iv);
}
function decrypt_stuff($key, $str, $iv) {
return openssl_decrypt($str, "aes-256-cbc", $key, 0, $iv);
}
使用从passwordDeriveBytes派生的密钥,此PHP代码产生与C#代码相同的结果.
$key = passwordDeriveBytes("testing", null);
$enc = encrypt_stuff($key,"437217","aw90rela942f65u2");
echo $enc;
//C9xJGa03dRQx9ePm0nLnHg==
但是,由于以下原因,我不建议使用此代码.
>最好将PBKDF2用作密钥.您可以在C#中使用Rfc2898DeriveBytes:
Rfc2898DeriveBytes kdf = new Rfc2898DeriveBytes(password, salt, iterations);
byte[] key = kdf.GetBytes(32);
和hash_pbkdf2在PHP中:
$key = hash_pbkdf2("sha1", $password, $salt, $iterations, 32, true);
salt的长度至少应为8个字节,并且迭代次数应至少为10,000.
>您不使用盐.您应该为每个密码使用随机盐,这会使您的密钥更坚固.
>您正在使用静态IV. IV应该是唯一且不可预测的.您可以使用RNGCryptoServiceProvider创建随机IV:
byte[] iv = new byte[16];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(iv);
$iv = openssl_random_pseudo_bytes(16);
您也可以对盐使用此代码.
>您没有使用经过身份验证的加密.如果您使用的是PHP 7,则可以使用GCM,但不幸的是.NET不提供任何AEAD算法.但是,如果选择使用经过身份验证的加密,则可以使用bouncycastle.
但是您的加密代码每次使用都会产生不同的结果,因为您应该使用随机IV.如果您具有IV,则可以正确解密密文.静脉注射不一定要保密.您可以将其存储在密文旁边.
如果您将mcrypt与MCRYPT_RIJNDAEL_256一起使用,则仍可以使您的PHP代码与C#兼容,因为RijndaelManaged支持256位块大小.
symmetricKey.BlockSize = 256;
但是,您不应使用mcrypt,因为它并未维护,并且在PHP 7中已弃用.
内容总结
以上是互联网集市为您收集整理的php中的c#MCRYPT_RIJNDAEL_256加密解密类全部内容,希望文章能够帮你解决php中的c#MCRYPT_RIJNDAEL_256加密解密类所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。