搜索

如何用php实现和c#一致的DES加密解密

发布网友 发布时间:2022-04-23 20:34

我来回答

2个回答

懂视网 时间:2022-04-06 08:38

在php中可以通过Mcrypt系列函数来实现des的加解密,但该扩展中的函数陆续被废弃,所以我们可以使用通用的OPENSSL方式来实现DES的加解密。

推荐:《PHP视频教程》

PHP 中 DES 加解密详解

一、简介

DES 是对称性加密里面常见一种,全称为 Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法。密钥长度是位(bit),超过位数密钥被忽略。所谓对称性加密即加密和解密密钥相同,对称性加密一般会按照固定长度,把待加密字符串分成块,不足一整块或者刚好最后有特殊填充字符。

跨语言做 DES 加密解密经常会出现问题,往往是填充方式不对、编码不一致或者加密解密模式没有对应上造成。常见的填充模式有: pkcs5、pkcs7、iso10126、ansix923、zero。加密模式有:DES-ECB、DES-CBC、DES-CTR、DES-OFB、DES-CFB。

作为一个软件开发者,可以通过工具测试 DES 加密解密,这里推荐一个在线工具:http://tool.chacuo.net/cryptdes

二、实现

PHP 提供了 Mcrypt 系列函数来实现 DES 的加解密,但该扩展中的函数陆续被废弃,自 PHP 7.2.0 起,会移到 PECL。

所以本代码用了更通用的 OPENSSL 方式实现 DES 的加解密,具体的实现和使用代码如下:

<?php
/**
 * openssl 实现的 DES 加密类,支持各种 PHP 版本
 */
class DES
{
 /**
 * @var string $method 加解密方法,可通过 openssl_get_cipher_methods() 获得
 */
 protected $method;
 /**
 * @var string $key 加解密的密钥
 */
 protected $key;
 /**
 * @var string $output 输出格式 无、base、hex
 */
 protected $output;
 /**
 * @var string $iv 加解密的向量
 */
 protected $iv;
 /**
 * @var string $options
 */
 protected $options;
 // output 的类型
 const OUTPUT_NULL = '';
 const OUTPUT_BASE = 'base';
 const OUTPUT_HEX = 'hex';
 /**
 * DES constructor.
 * @param string $key
 * @param string $method
 * ECB DES-ECB、DES-EDE3 (为 ECB 模式时,$iv 为空即可)
 * CBC DES-CBC、DES-EDE3-CBC、DESX-CBC
 * CFB DES-CFB8、DES-EDE3-CFB8
 * CTR
 * OFB
 *
 * @param string $output
 * base、hex
 *
 * @param string $iv
 * @param int $options
 */
 public function __construct($key, $method = 'DES-ECB', $output = '', $iv = '', $options = OPENSSL_RAW_DATA | OPENSSL_NO_PADDING)
 {
 $this->key = $key;
 $this->method = $method;
 $this->output = $output;
 $this->iv = $iv;
 $this->options = $options;
 }
 /**
 * 加密
 *
 * @param $str
 * @return string
 */
 public function encrypt($str)
 {
 $str = $this->pkcsPadding($str, 8);
 $sign = openssl_encrypt($str, $this->method, $this->key, $this->options, $this->iv);
 if ($this->output == self::OUTPUT_BASE) {
  $sign = base_encode($sign);
 } else if ($this->output == self::OUTPUT_HEX) {
  $sign = bin2hex($sign);
 }
 return $sign;
 }
 /**
 * 解密
 *
 * @param $encrypted
 * @return string
 */
 public function decrypt($encrypted)
 {
 if ($this->output == self::OUTPUT_BASE) {
  $encrypted = base_decode($encrypted);
 } else if ($this->output == self::OUTPUT_HEX) {
  $encrypted = hex2bin($encrypted);
 }
 $sign = @openssl_decrypt($encrypted, $this->method, $this->key, $this->options, $this->iv);
 $sign = $this->unPkcsPadding($sign);
 $sign = rtrim($sign);
 return $sign;
 }
 /**
 * 填充
 *
 * @param $str
 * @param $blocksize
 * @return string
 */
 private function pkcsPadding($str, $blocksize)
 {
 $pad = $blocksize - (strlen($str) % $blocksize);
 return $str . str_repeat(chr($pad), $pad);
 }
 /**
 * 去填充
 * 
 * @param $str
 * @return string
 */
 private function unPkcsPadding($str)
 {
 $pad = ord($str{strlen($str) - 1});
 if ($pad > strlen($str)) {
  return false;
 }
 return substr($str, 0, -1 * $pad);
 }
}
$key = 'key123456';
$iv = 'iv123456';
// DES CBC 加解密
$des = new DES($key, 'DES-CBC', DES::OUTPUT_BASE, $iv);
echo $baseSign = $des->encrypt('Hello DES CBC');
echo "
";
echo $des->decrypt($baseSign);
echo "
";
// DES ECB 加解密
$des = new DES($key, 'DES-ECB', DES::OUTPUT_HEX);
echo $baseSign = $des->encrypt('Hello DES ECB');
echo "
";
echo $des->decrypt($baseSign);

三、相关链接

DES 加解密工具:http://tool.chacuo.net/cryptdes

Mcrypt 官方文档:http://php.net/manual/zh/book.mcrypt.php

OPENSSL 加解密函数官方文档:

openssl_encrypt:http://php.net/manual/zh/function.openssl-encrypt.php

openssl_decrypt:http://php.net/manual/zh/function.openssl-decrypt.php

热心网友 时间:2022-04-06 05:46

PHP实现和c#一致的DES加密解密,可以从网上搜到一大堆,但是测试后发现都没法用。以下正确代码是我经过苦苦才找到的。希望大家在系统整合时能用的上。

注意:key的长度为8位以内。

[csharp] view plain copy print?
//C# 版DES 加解密算法  
using System;     
using System.Data;     
using System.Configuration;     
using System.Web;     
using System.Web.Security;     
using System.Web.UI;     
using System.Web.UI.WebControls;     
using System.Web.UI.WebControls.WebParts;     
using System.Web.UI.HtmlControls;     
using System.Data.SqlClient;     
using System.Security.Cryptography;     
using System.IO;     
using System.Text;     
public class Des{     
    //加解密密钥  
    private static  string skey = "12345678";  
    //初始化向量  
    private static byte[] DESIV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };   
   
                #region DESEnCode DES加密     
                public static string DESEnCode(string pToEncrypt, string sKey)     
                {     
                    pToEncrypt = HttpContext.Current.Server.UrlEncode(pToEncrypt);     
                    DESCryptoServiceProvider des = new DESCryptoServiceProvider();     
                    byte[] inputByteArray = Encoding.GetEncoding("UTF-8").GetBytes(pToEncrypt);     
                 
                    //建立加密对象的密钥和偏移量      
                    //原文使用ASCIIEncoding.ASCII方法的GetBytes方法      
                    //使得输入密码必须输入英文文本      
                    des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);     
                    des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);     
                    MemoryStream ms = new MemoryStream();     
                    CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);     
                 
                    cs.Write(inputByteArray, 0, inputByteArray.Length);     
                    cs.FlushFinalBlock();     
                 
                    StringBuilder ret = new StringBuilder();     
                    foreach (byte b in ms.ToArray())     
                    {     
                        ret.AppendFormat("{0:X2}", b);     
                    }     
                    ret.ToString();     
                    return ret.ToString();     
                }    
                #endregion    
                /// <summary>  
                ///   
                /// </summary>  
                /// <param name="pToDecrypt"> 待解密的字符串</param>  
                /// <param name="sKey"> 解密密钥,要求为8字节,和加密密钥相同</param>  
                /// <returns>解密成功返回解密后的字符串,失败返源串</returns>  
                #region DESDeCode DES解密  
                public static string DESDeCode(string pToDecrypt, string sKey)  
                {  
                    //    HttpContext.Current.Response.Write(pToDecrypt + "<br>" + sKey);     
                    //    HttpContext.Current.Response.End();     
                    DESCryptoServiceProvider des = new DESCryptoServiceProvider();  
               
                    byte[] inputByteArray = new byte[pToDecrypt.Length / 2];  
                    for (int x = 0; x < pToDecrypt.Length / 2; x++)  
                    {  
                        int i = (Convert.ToInt32(pToDecrypt.Substring(x * 2, 2), 16));  
                        inputByteArray[x] = (byte)i;  
                    }  
               
                    des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);  
                    des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);  
                    MemoryStream ms = new MemoryStream();  
                    CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);  
                    cs.Write(inputByteArray, 0, inputByteArray.Length);  
                    cs.FlushFinalBlock();  
               
                    StringBuilder ret = new StringBuilder();  
               
                    return HttpContext.Current.Server.UrlDecode(System.Text.Encoding.Default.GetString(ms.ToArray()));  
                }  
    #endregion   
}

[php] view plain copy print?
<?php  
class DES  
{  
    var $key;  
    var $iv; //偏移量  
      
    function DES( $key, $iv=0 ) {  
    //key长度8例如:1234abcd  
        $this->key = $key;  
        if( $iv == 0 ) {  
            $this->iv = $key; //默认以$key 作为 iv  
        } else {  
            $this->iv = $iv; //mcrypt_create_iv ( mcrypt_get_block_size (MCRYPT_DES, MCRYPT_MODE_CBC), MCRYPT_DEV_RANDOM );  
        }  
    }  
      
    function encrypt($str) {  
    //加密,返回大写十六进制字符串  
        $size = mcrypt_get_block_size ( MCRYPT_DES, MCRYPT_MODE_CBC );  
        $str = $this->pkcs5Pad ( $str, $size );  
        return strtoupper( bin2hex( mcrypt_cbc(MCRYPT_DES, $this->key, $str, MCRYPT_ENCRYPT, $this->iv ) ) );  
    }  
      
    function decrypt($str) {  
    //解密  
        $strBin = $this->hex2bin( strtolower( $str ) );  
        $str = mcrypt_cbc( MCRYPT_DES, $this->key, $strBin, MCRYPT_DECRYPT, $this->iv );  
        $str = $this->pkcs5Unpad( $str );  
        return $str;  
    }  
      
    function hex2bin($hexData) {  
        $binData = "";  
        for($i = 0; $i < strlen ( $hexData ); $i += 2) {  
            $binData .= chr ( hexdec ( substr ( $hexData, $i, 2 ) ) );  
        }  
        return $binData;  
    }  
  
    function pkcs5Pad($text, $blocksize) {  
        $pad = $blocksize - (strlen ( $text ) % $blocksize);  
        return $text . str_repeat ( chr ( $pad ), $pad );  
    }  
      
    function pkcs5Unpad($text) {  
        $pad = ord ( $text {strlen ( $text ) - 1} );  
        if ($pad > strlen ( $text ))  
            return false;  
        if (strspn ( $text, chr ( $pad ), strlen ( $text ) - $pad ) != $pad)  
            return false;  
        return substr ( $text, 0, - 1 * $pad );  
    }  
      
}  
?>

声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。
E-MAIL:11247931@qq.com
Top