• TripleDES之C#和PHP之间加密解密


    在C#常用加密解密一文中,介绍了几个加密解密方法,其中有个如何使用对称加密算法DES,此次说下DES的升级版,TripleDES。

    DES和TripleDES之间的关系可以参考下面的博文。 
    对称加密DES和TripleDES

    重点内容是,如何分别在C#,PHP中使用TripleDES,然后可以让二者可以解密对方发送的加密内容。

    废话不多说,直接上两端的代码。

    C#代码

    using System;
    using System.Security.Cryptography;
    using System.Text;
    
    namespace TripleDes
    {
        class Program
        {
            static void Main(string[] args)
            {
                //加密的字符串
                string source = "Happy Father's Day!";
    
                //用来加密的key 但是最终用在des加密的key
                //是这个key的 md5 hash
                string sourceKey = "home";
    
                //获取原始key值的 md5 hash
                byte[] keyBytes = GetKeyMd5Hash(sourceKey);
    
                string encryptedStr = DesEncrypt(source, keyBytes);
                Console.WriteLine("encrypted string: "+ encryptedStr);
    
                string decryptedStr = DesDecrypt(encryptedStr, keyBytes);
                Console.WriteLine("Decrypted String: " + decryptedStr);
                Console.ReadKey();
            }
    
            /// <summary>
            /// 获取加密key的 md5 hash,最终DES加密的时候使用这个hash值
            /// </summary>
            /// <param name="key">原始key值</param>
            /// <returns></returns>
            public static byte[] GetKeyMd5Hash(string key)
            {
                MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
                byte[] keyBytes = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
                hashmd5.Clear();
    
                return keyBytes;
            }
    
            /// <summary>
            /// TripleDES 加密
            /// </summary>
            /// <param name="toEncrypt"></param>
            /// <param name="privateKey"></param>
            /// <returns></returns>
            public static string DesEncrypt(string toEncrypt, byte[] privateKey)
            {
                byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
    
                TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider
                {
                    Key = privateKey,
                    Mode = CipherMode.ECB,
                    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>
            /// TripleDES解密
            /// </summary>
            /// <param name="toDecrypt"></param>
            /// <param name="privateKey"></param>
            /// <returns></returns>
            public static string DesDecrypt(string toDecrypt, byte[] privateKey)
            {
                //先base64解密 因为加密的时候最后走了一道base64加密
                byte[] enBytes = Convert.FromBase64String(toDecrypt);
    
                TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider
                {
                    Key = privateKey,
                    Mode = CipherMode.ECB,
                    Padding = PaddingMode.PKCS7
                };
    
                ICryptoTransform cTransform = tdes.CreateDecryptor();
                byte[] resultArray = cTransform.TransformFinalBlock(enBytes, 0, enBytes.Length);
                tdes.Clear();
    
                return Encoding.UTF8.GetString(resultArray);
    
            }
        }
    }
    

    php代码

    <?php
    
    /*
        TripleDES加密
    */
    function DesEncrypt($data)
    {    
        //Pad for PKCS7
        $blockSize = mcrypt_get_block_size('tripledes', 'ecb');
        $len = strlen($data);
        $pad = $blockSize - ($len % $blockSize);
        $data .= str_repeat(chr($pad), $pad);
    
        $key = "home";
        $key = md5($key,TRUE);
        $key .= substr($key,0,8); //comment this if you use 168 bits long key
    
        //Encrypt data
        $encData = mcrypt_encrypt('tripledes', $key, $data, 'ecb'); 
        return base64_encode($encData);
    }
    
     /*
        TripleDES解密
     */
     function DesDecrypt($data)
     {
        $key = "home";
        $key = md5($key, TRUE);
        $key .= substr($key, 0, 8);
    
        //Decrypt data
        $fromBase64Str = base64_decode($data);
        $decData = mcrypt_decrypt('tripledes', $key, $fromBase64Str, 'ecb');
    
        return $decData;
     }
    
     /*
     测试
     */
     $encryptStr = DesEncrypt("Happy Father's Day!");     
        echo "encrypted string: $encryptStr</br>";
     $decryptStr = DesDecrypt($encryptStr);
        echo "decrypted string: $decryptStr";
    ?>

    这样以来,PHP就可以解密C#加密后的内容,同样C#也可以解密PHP加密后的内容。

    虽然都是TripleDES加密算法,但是因为C#,PHP两种语言加密使用的默认mode,padding都不一样,如果直接使用各自语言自带的TripleDES,会导致双方使用同样的密钥,加密同样的内容后,加密结果不一样,进而就不能相互解密了。

    关于各种语言使用的加密模式等内容,可以多多Google。就像RSA加密算法,C#,Java,PHP三者使用的密钥格式都不一样,JAVA惯用ASN,C#惯用XML,而PHP惯用PEM。这样就导致各自不能互通。 
    p.s.还没研究出三者RSA互通的方法。

    参考文章:

    加密算法模式 填充

    PHP padding PKCS7

    How to add/remove PKCS7 padding from an AES encrypted string

    Triple DES with PCSK7 and ECB between PHP and .NET

    今天父亲节,祝老爸节日快乐!

  • 相关阅读:
    http的8种请求方式
    死锁
    进程与线程
    vuex
    路由懒加载
    SPA单页面富应用
    组件中的data为什么必须是函数
    v-for中key的作用
    关于排序的常识总结
    关于树的常见操作-C++面试
  • 原文地址:https://www.cnblogs.com/Alex80/p/7340163.html
Copyright © 2020-2023  润新知