天天看點

AES加密php,java,.net三種語言同步實作加密、解密

因工作需要,在使用aes解密時,因客戶開發語言有多種,現在基本就是java,php,asp.net三種語言是主流,筆者對三種語言也算是研究多年了,有時客戶總是問這問那的,就調試好了三種不同語言的AES加密工具類,這樣也確定客戶加密過來的資料伺服器端可以正常解密。閑話少說了,貼出代碼。:)

1、java版

    package com.totcms.api.util;

    import javax.crypto.Cipher;

    import javax.crypto.KeyGenerator;

    import javax.crypto.SecretKey;

    import javax.crypto.spec.SecretKeySpec;

    import java.io.FileInputStream;

    import java.io.UnsupportedEncodingException;

    import java.security.NoSuchAlgorithmException;

    import java.security.SecureRandom;

    import java.security.interfaces.RSAPrivateKey;

    import java.security.interfaces.RSAPublicKey;

    public class AES {

        //

        private static final String CipherMode = "AES/ECB/PKCS5Padding";

        // private static final String CipherMode = "AES";

        public static SecretKeySpec generateKey(){

            try {

                KeyGenerator kgen = KeyGenerator.getInstance("AES");

                kgen.init(128, new SecureRandom());

                SecretKey secretKey = kgen.generateKey();  

                byte[] enCodeFormat = secretKey.getEncoded();  

                SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");

                return key;

            } catch (NoSuchAlgorithmException e) {

                e.printStackTrace();

            }

            return null;

        }

        public static String generateKeyString(){

            return byte2hex(generateKey().getEncoded());

        }

        public static byte[] encrypt(byte[] content,byte[] key) {

            try {

                Cipher cipher = Cipher.getInstance(CipherMode);

                cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));

                byte[] result = cipher.doFinal(content);

                return result;

            } catch (Exception e) {

                e.printStackTrace();

            }

            return null;

        }

        public static String encrypt(String content,byte[] key) {

            try {

                Cipher cipher = Cipher.getInstance(CipherMode);

                cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));

                byte[] data = cipher.doFinal(content.getBytes("UTF-8"));

                String result = byte2hex(data);

                return result;

            } catch (Exception e) {

                e.printStackTrace();

            }

            return null;

        }

        public static String encrypt(String content,String key) {

            byte[] data = null;

            try {

                data = content.getBytes("UTF-8");

            } catch (Exception e) {

                e.printStackTrace();

            }

            data = encrypt(data,new SecretKeySpec(hex2byte(key), "AES").getEncoded());

            String result = byte2hex(data);

            return result;

        }

        public static byte[] decrypt(byte[] content,byte[] key) {

            try {

                Cipher cipher = Cipher.getInstance(CipherMode);

                cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"));

                byte[] result = cipher.doFinal(content);

                return result;

            } catch (Exception e) {

                e.printStackTrace();

            }

            return null;

        }

        public static String decrypt(String content, String key) {

            byte[] data = null;

            try {

                data = hex2byte(content);

            } catch (Exception e) {

                e.printStackTrace();

            }

            data = decrypt(data, hex2byte(key));

            if (data == null)

                return null;

            String result = null;

            try {

                result = new String(data, "UTF-8");

            } catch (UnsupportedEncodingException e) {

                e.printStackTrace();

            }

            return result;

        }

        public static String decrypt(String content,byte[] key) {

            try {

                Cipher cipher = Cipher.getInstance(CipherMode);

                cipher.init(Cipher.DECRYPT_MODE,new SecretKeySpec(key, "AES"));

                byte[] data = cipher.doFinal(hex2byte(content));

                return new String(data, "UTF-8");

            } catch (Exception e) {

                e.printStackTrace();

            }

            return null;

        }

        public static String byte2hex(byte[] b) { // 一個位元組的數,

            StringBuffer sb = new StringBuffer(b.length * 2);

            String tmp;

            for (int n = 0; n < b.length; n++) {

                // 整數轉成十六進制表示

                tmp = (Integer.toHexString(b[n] & 0XFF));

                if (tmp.length() == 1) {

                    sb.append("0");

                }

                sb.append(tmp);

            }

            return sb.toString().toUpperCase(); // 轉成大寫

        }

        private static byte[] hex2byte(String inputString) {

            if (inputString == null || inputString.length() < 2) {

                return new byte[0];

            }

            inputString = inputString.toLowerCase();

            int l = inputString.length() / 2;

            byte[] result = new byte[l];

            for (int i = 0; i < l; ++i) {

                String tmp = inputString.substring(2 * i, 2 * i + 2);

                result[i] = (byte) (Integer.parseInt(tmp, 16) & 0xFF);

            }

            return result;

        }

        public static void main(String[] args) {

            try{

                // 加載RSA

                //RSAPublicKey publicKey = RSA.loadPublicKey(new FileInputStream("E:\\2016\\9\\19\\cert\\apiclient_cert.p12"));

                //RSAPrivateKey privateKey = RSA.loadPrivateKey(new FileInputStream("E:\\2016\\9\\19\\cert\\apiclient_cert.p12"));

                // 生成AES密鑰

                 String key=AES.generateKeyString();

                 //                String key = "1234567890123456";

                System.out.println("AES-KEY:" + key);

                // 内容

    //            String content = "{\"mobile\":\"18660803982\",\"amount\":\"100\",\"companyId\":\"8\",\"orderNum\":\"123456789\",\"bussissId\":\"18154568754\",\"notifyUrl\":\"\"}";

                String content = "{\"mobile\":\"15005414383\",\"amount\":\"10\",\"companyId\":\"8\",\"orderNum\":\"123456789\",\"notifyUrl\":\"\",\"bussissId\":\"1101\"}";

                // 用RSA公鑰加密AES-KEY

                //String miKey = RSA.encryptByPublicKey(key, publicKey);

                //System.out.println("加密後的AES-KEY:" + miKey);

                //System.out.println("加密後的AES-KEY長度:" + miKey.length());

                // 用RSA私鑰解密AES-KEY

                //String mingKey = RSA.decryptByPrivateKey(miKey, privateKey);

                //System.out.println("解密後的AES-KEY:" + mingKey);

                //System.out.println("解密後的AES-KEY長度:" + mingKey.length());

                // 用AES加密内容

                //String miContent = AES.encrypt(content, mingKey);

                String miContent = AES.encrypt(content, "6369BE91F580F990015D709D4D69FA41");            

                System.out.println("AES加密後的内容:" + miContent);        

                // 用AES解密内容

                String mingContent = AES.decrypt(miContent, "6369BE91F580F990015D709D4D69FA41");

                System.out.println("AES解密後的内容:" + mingContent);        

            }catch (Exception e) {

                e.printStackTrace();

                // TODO: handle exception

            }

        }

    }

2、asp.net版

    using System;

    using System.Collections.Generic;

    using System.ComponentModel;

    using System.Data;

    using System.Drawing;

    using System.Linq;

    using System.Text;

    using System.Windows.Forms;

    using System.IO;

    using System.Net;

    using System.Web;

    using System.Text.RegularExpressions;

    using System.Security.Cryptography;  

    namespace PostDemo

    {

      public partial class Form1 : Form

      {

        public Form1()

        {

          InitializeComponent();

        }

        public static string AESEncrypts(String Data, String Key)

        {

          // 256-AES key      

          byte[] keyArray = HexStringToBytes(Key);//UTF8Encoding.ASCII.GetBytes(Key);

          byte[] toEncryptArray = UTF8Encoding.ASCII.GetBytes(Data);

          RijndaelManaged rDel = new RijndaelManaged();

          rDel.Key = keyArray;

          rDel.Mode = CipherMode.ECB;

          rDel.Padding = PaddingMode.PKCS7;

          ICryptoTransform cTransform = rDel.CreateEncryptor();

          byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0,

                  toEncryptArray.Length);

          return BytesToHexString(resultArray);

        }

        /// <summary>

        /// Byte array to convert 16 hex string

        /// </summary>

        /// <param name="bytes">byte array</param>

        /// <returns>16 hex string</returns>

        public static string BytesToHexString(byte[] bytes)

        {

          StringBuilder returnStr = new StringBuilder();

          if (bytes != null || bytes.Length == 0)

          {

            for (int i = 0; i < bytes.Length; i++)

            {

              returnStr.Append(bytes[i].ToString("X2"));

            }

          }

          return returnStr.ToString();

        }

        /// <summary>

        /// 16 hex string converted to byte array

        /// </summary>

        /// <param name="hexString">16 hex string</param>

        /// <returns>byte array</returns>

        public static byte[] HexStringToBytes(String hexString)

        {

          if (hexString == null || hexString.Equals(""))

          {

            return null;

          }

          int length = hexString.Length / 2;

          if (hexString.Length % 2 != 0)

          {

            return null;

          }

          byte[] d = new byte[length];

          for (int i = 0; i < length; i++)

          {

            d[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);

          }

          return d;

        }

        private void button2_Click(object sender, EventArgs e)

        {

          String Content = tbContent.Text;//要加密的字元串

          //接口密鑰,替換成您的密鑰(32位)

          String k = "6D6A39C7078F6783E561B0D1A9EB2E68";

          String s = AESEncrypts(Content, k);

          tbLog.AppendText("encript:"+s);

        }  

      }

    }

3、php版

    <?php

    class CryptAES

    {

        protected $cipher = MCRYPT_RIJNDAEL_128;

        protected $mode = MCRYPT_MODE_ECB;

        protected $pad_method = NULL;

        protected $secret_key = '';

        protected $iv = '';

        public function set_cipher($cipher)

        {

            $this->cipher = $cipher;

        }

        public function set_mode($mode)

        {

            $this->mode = $mode;

        }

        public function set_iv($iv)

        {

            $this->iv = $iv;

        }

        public function set_key($key)

        {

            $this->secret_key = $key;

        }

        public function require_pkcs5()

        {

            $this->pad_method = 'pkcs5';

        }

        protected function pad_or_unpad($str, $ext)

        {

            if ( is_null($this->pad_method) )

            {

                return $str;

            }

            else

            {

                $func_name = __CLASS__ . '::' . $this->pad_method . '_' . $ext . 'pad';

                if ( is_callable($func_name) )

                {

                    $size = mcrypt_get_block_size($this->cipher, $this->mode);

                    return call_user_func($func_name, $str, $size);

                }

            }

            return $str;

        }

        protected function pad($str)

        {

            return $this->pad_or_unpad($str, '');

        }

        protected function unpad($str)

        {

            return $this->pad_or_unpad($str, 'un');

        }

        public function encrypt($str)

        {

            $str = $this->pad($str);

            $td = mcrypt_module_open($this->cipher, '', $this->mode, '');

            if ( empty($this->iv) )

            {

                $iv = @mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);

            }

            else

            {

                $iv = $this->iv;

            }

            mcrypt_generic_init($td, hex2bin($this->secret_key), $iv);

            $cyper_text = mcrypt_generic($td, $str);

            $rt = strtoupper(bin2hex($cyper_text));

            mcrypt_generic_deinit($td);

            mcrypt_module_close($td);

            return $rt;

        }

        public function decrypt($str){

            $td = mcrypt_module_open($this->cipher, '', $this->mode, '');

            if ( empty($this->iv) )

            {

                $iv = @mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);

            }

            else

            {

                $iv = $this->iv;

            }

            mcrypt_generic_init($td, $this->secret_key, $iv);

            //$decrypted_text = mdecrypt_generic($td, self::hex2bin($str));

            $decrypted_text = mdecrypt_generic($td, base64_decode($str));

            $rt = $decrypted_text;

            mcrypt_generic_deinit($td);

            mcrypt_module_close($td);

            return $this->unpad($rt);

        }

        public static function hex2bin($hexdata) {

            $bindata = '';

            $length = strlen($hexdata);

            for ($i=0; $i< $length; $i += 2)

            {

                $bindata .= chr(hexdec(substr($hexdata, $i, 2)));

            }

            return $bindata;

        }

        public static function pkcs5_pad($text, $blocksize)

        {

            $pad = $blocksize - (strlen($text) % $blocksize);

            return $text . str_repeat(chr($pad), $pad);

        }

        public static function pkcs5_unpad($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);

        }

    }

    //密鑰

    $keyStr = '6D6A39C7078F6783E561B0D1A9EB2E68';

    //加密的字元串

    $plainText = 'test';

    $aes = new CryptAES();

    $aes->set_key($keyStr);

    $aes->require_pkcs5();

    $encText = $aes->encrypt($plainText);

    echo $encText;

    ?>

上面三種語言,使用相當的密鑰(key),對同樣字元串加密後的結果是一樣的。加密過程通過上面代碼也好了解,将先key轉成16進制傳遞給加密函數對内容加密,然後将加密後的結果轉成16進制字元串傳回結果(要注意大小寫,這裡我統一傳回大寫的結果)。