PHP 加密与 C# 加密兼容

本文关键字:加密 PHP | 更新日期: 2023-09-27 18:34:09

我有这个C#加密代码:

 public class Cryptor_Engine
{
    /// <summary>
    /// Encrypt a string using dual encryption method. Return a encrypted cipher Text
    /// </summary>
    /// <param name="toEncrypt">string to be encrypted</param>
    /// <param name="useHashing">use hashing? send to for extra secirity</param>
    /// <returns></returns>
    public static string Encrypt(string toEncrypt, string key, bool useHashing)
    {
        byte[] keyArray;
        byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
        System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader();
        if (useHashing)
        {
            MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
            keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
            hashmd5.Clear();
        }
        else
            keyArray = UTF8Encoding.UTF8.GetBytes(key);
        TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
        tdes.Key = keyArray;
        tdes.Mode = CipherMode.ECB;
        tdes.Padding = PaddingMode.PKCS7;
        ICryptoTransform cTransform = tdes.CreateEncryptor();
        byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
        tdes.Clear();
        return Convert.ToBase64String(resultArray, 0, resultArray.Length);
    }
    /// <summary>
    /// DeCrypt a string using dual encryption method. Return a DeCrypted clear string
    /// </summary>
    /// <param name="cipherString">encrypted string</param>
    /// <param name="useHashing">Did you use hashing to encrypt this data? pass true is yes</param>
    /// <returns></returns>
    public static string Decrypt(string cipherString, string key, bool useHashing)
    {
        byte[] keyArray;
        byte[] toEncryptArray = Convert.FromBase64String(cipherString);
        System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader();
        //Get your key from config file to open the lock!
        //string key = (string)settingsReader.GetValue("SecurityKey", typeof(String));
        if (useHashing)
        {
            MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
            keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
            hashmd5.Clear();
        }
        else
            keyArray = UTF8Encoding.UTF8.GetBytes(key);
        TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
        tdes.Key = keyArray;
        tdes.Mode = CipherMode.ECB;
        tdes.Padding = PaddingMode.PKCS7;
        ICryptoTransform cTransform = tdes.CreateDecryptor();
        byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
        tdes.Clear();
        return UTF8Encoding.UTF8.GetString(resultArray);
    }
}

上面的代码根据提供的密钥加密和解密文本。 我需要一个兼容的 PHP 代码,它会给我与上述算法相同的密钥?是否可以同时使用 php 和 c# 来拥有类似的加密文本?

PHP 加密与 C# 加密兼容

加密

首先,如果$useHashing为真,我们需要在$key上运行 MD5 算法

function encrypt($toEncrypt, $key, $useHashing) {
    if ($useHashing) {
        $key = md5($key);
    }

接下来,我们需要使用 PKCS7 算法填充它。对于 PKCS7,字符串的最后一个字节指定填充长度,因此我们需要计算出需要多少填充,然后添加它。

    $blockSize = mcrypt_get_block_size(MCRYPT_3DES, MCRYPT_MODE_ECB);
    $len = strlen($toEncrypt);
    $pad = $blockSize - ($len % $blockSize);
    $toEncrypt .= str_repeat(chr($pad), $pad);

接下来,我们使用 Mcrypt 扩展进行加密。

    $encrypted = mcrypt_encrypt(MCRYPT_3DES, $key, $toEncrypt, MCRYPT_MODE_ECB);

最后,将加密字符串编码为 Base64。

    return base64_encode($encrypted);

所以完整的函数看起来像:

function encrypt($toEncrypt, $key, $useHashing) {
    if ($useHashing) {
        $key = md5($key);
    }
    $blockSize = mcrypt_get_block_size(MCRYPT_3DES, MCRYPT_MODE_ECB);
    $len = strlen($toEncrypt);
    $pad = $blockSize - ($len % $blockSize);
    $toEncrypt .= str_repeat(chr($pad), $pad);
    $encrypted = mcrypt_encrypt(MCRYPT_3DES, $key, $toEncrypt, MCRYPT_MODE_ECB);
    return base64_encode($encrypted);
}

解密

首先,您收到加密的密码作为 Base64,因此您需要对其进行解码。

function decrypt($cipherString, $key, $useHashing) {
    $decoded = base64_decode($cipherString);
    ...

然后,如果useHashing为 true,我们需要在密钥上运行 md5 算法。

    if ($useHashing) {
        $key = md5($key);
    }

现在我们有了密钥和解码的字符串,我们实际上可以解密数据。

    $decrypted = mcrypt_decrypt(MCRYPT_3DES, $key, $decoded, MCRYPT_MODE_ECB);

$decrypted包含解密的字符串,带有填充。要删除填充,我们需要找到最后一个字节的整数值:

    $len = strlen($decrypted);
    $pad = ord($decrypted[$len-1]);

现在$pad是一个整数,它指定填充的大小,因此只需返回填充之前字符串的一部分。

    return substr($decrypted, 0, $len - $pad);
因此,综

上所述,我们有:

function decrypt($cipherString, $key, $useHashing) {
    $decoded = base64_decode($cipherString);
    if ($useHashing) {
        $key = md5($key);
    }
    $decrypted = mcrypt_encrypt(MCRYPT_3DES, $key, $decoded, MCRYPT_MODE_ECB);
    $len = strlen($decrypted);
    $pad = ord($decrypted[$len-1]);
    return substr($decrypted, 0, $len - $pad);
}

安全

如果可能的话,您应该考虑使用 AES,而不是 3DES 和比 ECB 更安全的密码模式。