php(openssl)与C#(VB.NET)加解密

vb.net中有个3DES的加解密示例,用其加密在php中不知如何解密,看了网上很多代码,主要还是编码的问题,将vb.net的代码转为C#的代码如下:

 using System;
 using System.Security.Cryptography;
 public sealed class My3Des
 {
        private TripleDESCryptoServiceProvider TripleDes = new TripleDESCryptoServiceProvider();
        //---指定密钥的哈希创建指定长度的字节数组
        private byte[] TruncateHash(string key, int length)
        {
            // byte[] functionReturnValue = 0;
            SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
            // Hash the key.
            byte[] keyBytes = System.Text.Encoding.Unicode.GetBytes(key);
            byte[] hash = sha1.ComputeHash(keyBytes);

            // Truncate or pad the hash.
             Array.Resize(ref hash,length);
            return hash;
        }

        //添加用来初始化 3DES 加密服务提供程序的构造函数。
        //key 参数控制 EncryptData 和 DecryptData 方法。
        public My3Des(string key)
        {
            // Initialize the crypto provider.
            TripleDes.Key = TruncateHash(key, TripleDes.KeySize / 8);
            TripleDes.IV = TruncateHash("", TripleDes.BlockSize / 8);
        }
        //添加加密字符串的公共方法
        public string EncryptData(string plaintext)
        {
            
            byte[] plaintextBytes = System.Text.Encoding.Unicode.GetBytes(plaintext);
            
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            
            CryptoStream encStream = new CryptoStream(ms, TripleDes.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write);
            
            encStream.Write(plaintextBytes, 0, plaintextBytes.Length);
            encStream.FlushFinalBlock();
            
            return Convert.ToBase64String(ms.ToArray());
           
        }
        //添加解密字符串的公共方法
        public string DecryptData(string encryptedtext)
        {
           
            byte[] encryptedBytes = Convert.FromBase64String(encryptedtext);
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            CryptoStream decStream = new CryptoStream(ms, TripleDes.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Write);
            decStream.Write(encryptedBytes, 0, encryptedBytes.Length);
            decStream.FlushFinalBlock();
            
            return System.Text.Encoding.Unicode.GetString(ms.ToArray());

        }
    }

在php中使用opensll来解密时,发现无法解密,如果把C#中的编码改为ASCII或UTF8则可以正常解码,而Unicode却出现问题,增加 编码转化UTF-8到UCS-2还是不行,将UCS-2变为UCS-2LE问题解决。C#unicode默认使用little-Endian字节顺序的UTF-16的格式编码,在windows里PHP对应的unicode的编码是UCS-2LE。

class Encrypt
{
//加密秘钥,
    private $_key;
    private $_iv;
    public function __construct($key)
    {	
	   $this->_key = $this->pad(SHA1($this->Ucs2Code($key),true),24);
	   $this->_iv = substr(SHA1($this->Ucs2Code(""),true),0,8);
    }
    /**
     * 对字符串进行3DES加密
     * @param string 要加密的字符串
     */
    public function encrypt3DES($str)
    {
		$data = $this->Ucs2Code($str);
		$encrypted_openssl = openssl_encrypt($data, 'des-ede3-cbc', $this->_key, OPENSSL_RAW_DATA, $this->_iv);
		return $encrypted_openssl;
    }

    /**
     * 对加密的字符串进行3DES解密
     * @param string 要解密的字符串
     */
    public function decrypt3DES($str)
    {
        $data	= base64_decode($str,true);
		$decrypt_openssl = openssl_decrypt($data,'des-ede3-cbc',$this->_key,OPENSSL_RAW_DATA, $this->_iv);
        $decrypt_openssl = mb_convert_encoding("decrypt_openssl","UTF-8","UCS-2LE");
		return $decrypt_openssl;
	}
	
	private function pad($str,$length)
	{  
		if (strlen($str) < $length) {
			$message_padded = str_pad($str,$length, "\0");
		}
		else {
			$message_padded = substr($str,0,$length);
		}
		return $message_padded;
	}

	
	public function Ucs2Code($str,$encode="UTF-8"){
		$jumpbit=strtoupper($encode)=='GB2312'?2:3;//跳转位数
		$strlen=strlen($str);//字符串长度
		$pos=0;//位置
		$buffer=array();
		for($pos=0;$pos<$strlen;){
			if(ord(substr($str,$pos,1))>=0xa1){//0xa1(161)汉字编码开始
				$tmpChar=substr($str,$pos,$jumpbit);
				$pos+=$jumpbit;
			}else{
				$tmpChar=substr($str,$pos,1);
				++$pos;
			}
			//$buffer[]=bin2hex(iconv("UTF-8","UCS-2",$tmpChar));
			$buffer[]=iconv($encode,"UCS-2LE",$tmpChar);
		}

		return join("",$buffer);
	}
}

如果密码相同想得到不同的加密字符,可在原密码前随机加2个字符,解密的时候将前两位去掉。

PHP:

function GetRndChar($n) {
    $charid = strtoupper(md5(uniqid(mt_rand(), true)));
    return substr($charid, 0, $n);
}

c#

//--随机生成数字和字母的字符串
private string GetRndChar(int n)
{
       return System.Guid.NewGuid().ToString().Substring(0, n);
}

 

你可能感兴趣的:(C#,php)