.NET和PHP加密的区别

7

我有以下生成密钥的C#代码:

    public static byte[] Encrypt(byte[] plainData, string salt)
    {
        DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
        DES.Key = ASCIIEncoding.ASCII.GetBytes(salt);
        DES.IV = ASCIIEncoding.ASCII.GetBytes(salt);
        ICryptoTransform desencrypt = DES.CreateEncryptor();
        byte[] encryptedData = desencrypt.TransformFinalBlock(plainData, 0, plainData.Length);
        return encryptedData;
    }

    private string GetEncryptedKey(string key)
    {
        return BitConverter.ToString(KeyGeneratorForm.Encrypt(ASCIIEncoding.ASCII.GetBytes(key), "abcdefgh")).Replace("-", "");
    }

我正在尝试在PHP中执行相同的操作:
function get_encrypted_key($key){
    $salt = "abcdefgh";
    return bin2hex(mcrypt_encrypt(MCRYPT_DES, $salt, $key, MCRYPT_MODE_CBC, $salt));
}

然而,结果存在一个小的差异,因为最后16个字符总是不同的:
With key "Benjamin Franklin":
C# : 0B3C6E5DF5D747FB3C50DE952FECE3999768F35B890BC391
PHP: 0B3C6E5DF5D747FB3C50DE952FECE3993A881F9AF348C64D

With key "President Franklin D Roosevelt":
C# : C119B50A5A7F8C905A86A43F5694B4D7DD1E8D0577F1CEB32A86FABCEA5711E1
PHP: C119B50A5A7F8C905A86A43F5694B4D7DD1E8D0577F1CEB37ACBE60BB1D21F3F

我也尝试使用以下代码对我的密钥执行填充转换:
function get_encrypted_key($key){
    $salt = "abcdefgh";

    $extra = 8 - (strlen($key) % 8);
    if($extra > 0) {
        for($i = 0; $i < $extra; $i++) {
            $key.= "\0";
        }
    }

    return bin2hex(mcrypt_encrypt(MCRYPT_DES, $salt, $key, MCRYPT_MODE_CBC, $salt));
}

但是我加上填充后得到的结果和没有填充时一样。

如果您知道发生了什么,我很乐意听取您的建议! :)

谢谢


3
可能是由于不同的填充方案导致的结果? - mensi
2
如果你说的“经典”填充代码段是指在mcrypt_encrypt笔记的顶部提到的那个,那么它可以让你从PHP得到与C#相同的结果。请注意,该代码段使用ECB而不是CBC,因此您需要进行调整。 - John Flatness
谢谢你们的评论。我已经详细说明了我用于填充的代码。我会查看约翰的链接。 - Gad
不如全部抛弃,换成一些更好的东西,怎么样? - CodesInChaos
@CodeInChaos,你会在正确答案的基础上增加什么? - Gad
1个回答

4
你提到尝试了一个“经典”的填充代码片段。以下是对mcrypt_encrypt文档中发布的片段的快速调整,它会给出与C#相同的结果。
PKCS #7(C#的SymmetricAlgorithm使用的默认填充方案)使用字节进行填充,其中每个填充字节的值与填充字节的数量相同,而不是使用零字节。
function get_encrypted_key($key)
{
    $salt = 'abcdefgh';
    $block = mcrypt_get_block_size('des', 'cbc');
    $pad = $block - (strlen($key) % $block);
    $key .= str_repeat(chr($pad), $pad);

    return bin2hex(mcrypt_encrypt(MCRYPT_DES, $salt, $key, MCRYPT_MODE_CBC, $salt));
}

测试输出:

php > echo get_encrypted_key('Benjamin Franklin');
0b3c6e5df5d747fb3c50de952fece3999768f35b890bc391
php > echo get_encrypted_key('President Franklin D Roosevelt');
c119b50a5a7f8c905a86a43f5694b4d7dd1e8d0577f1ceb32a86fabcea5711e1

非常感谢,约翰,这太完美了。 - Gad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接