# 加解密


# 1、php

<?php
class AES
{
    public static function encrypt($str, $key, $iv)
    {
        $str = $str . str_repeat("\0", 16 - strlen($str) % 16);
        $encrypt = openssl_encrypt($str, 'AES-128-CBC', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);

        return bin2hex($encrypt);
    }

    public static function decrypt($str, $key, $iv)
    {
        $decrypt = openssl_decrypt(hex2bin($str), 'AES-128-CBC', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
        return rtrim($decrypt, "\0");
    }
}

# 2、java

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AES
{
    public static void main(String args[]) throws Exception {
        // app_key
        String cKey = "1234567890123456";
        // 需要加密的字串
        String cSrc = "{\"code\":\"0\",\"error_msg\":\"密码错误\",\"weixiao_openid\":\"12345678\",\"student_num\":\"888888888888\",\"name\":\"洪丹丹测试\",\"sign\":\"5C6E844C23C8F0C15AF382081D0663DC\"}";
        // app_secret 取前16位;
        String cIv = "0123456789123456";
        System.out.println(cSrc);
        // 加密
        long lStart = System.currentTimeMillis();
        String enString = AES.Encrypt(cSrc, cKey, cIv);
        System.out.println("加密后的字串是:" + enString);

        long lUseTime = System.currentTimeMillis() - lStart;
        System.out.println("加密耗时:" + lUseTime + "毫秒");
        // 解密
        lStart = System.currentTimeMillis();
        String DeString = AES.Decrypt(enString, cKey, cIv);
        System.out.println("解密后的字串是:" + DeString);
        lUseTime = System.currentTimeMillis() - lStart;
        System.out.println("解密耗时:" + lUseTime + "毫秒");

    }

    public static String Encrypt(String sSrc, String sKey, String sIv) throws Exception {

        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
        int blockSize = cipher.getBlockSize();

        byte[] dataBytes = sSrc.getBytes();
        int plaintextLength = dataBytes.length;
        if (plaintextLength % blockSize != 0) {
            plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
        }

        byte[] plaintext = new byte[plaintextLength];
        System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);

        SecretKeySpec keyspec = new SecretKeySpec(sKey.getBytes(), "AES");
        IvParameterSpec ivspec = new IvParameterSpec(sIv.getBytes());

        cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
        byte[] encrypted = cipher.doFinal(plaintext);

        return byte2hex(encrypted).toLowerCase();
    }

    public static String Decrypt(String sSrc, String sKey, String sIv) throws Exception {

        byte[] encrypted1      = hex2byte(sSrc);

        Cipher cipher          = Cipher.getInstance("AES/CBC/NoPadding");
        SecretKeySpec keyspec  = new SecretKeySpec(sKey.getBytes(), "AES");
        IvParameterSpec ivspec = new IvParameterSpec(sIv.getBytes());

        cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);

        byte[] original = cipher.doFinal(encrypted1);
        String originalString = new String(original);

        return originalString;
    }

    public static byte[] hex2byte(String strhex) {
        if (strhex == null) {
            return null;
        }
        int l = strhex.length();
        if (l % 2 == 1) {
            return null;
        }
        byte[] b = new byte[l / 2];
        for (int i = 0; i != l / 2; i++) {
            b[i] = (byte) Integer.parseInt(strhex.substring(i * 2, i * 2 + 2),
                    16);
        }

        return b;
    }

    public static String byte2hex(byte[] b) {
        String hs = "";
        String stmp = "";
        for (int n = 0; n < b.length; n++) {
            stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
            if (stmp.length() == 1) {
                hs = hs + "0" + stmp;
            } else {
                hs = hs + stmp;
            }
        }

        return hs.toUpperCase();
    }
}

# 3、python

import hashlib
from Crypto import Random
from Crypto.Cipher import AES
import binascii

class AESCipher(object):

    def __init__(self):
        self.bs = 16
        self.iv = '0123456789123456'
        self.key = '1234567890123456'

    def encrypt(self, raw):
        raw = self._pad(raw)
        cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
        return binascii.hexlify(cipher.encrypt(raw))

    def decrypt(self, enc):
        enc = binascii.unhexlify(enc)
        cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
        return cipher.decrypt(enc).decode('utf-8').rstrip("\0")

    def _pad(self, s):
        return s + (self.bs - len(s) % self.bs) * '\0'


crypt = AESCipher()

print crypt.encrypt('12345')
print crypt.decrypt('90b2c15e84cb78e5161f42867807c4bc')

# 4、csharp

using System;
using System.IO;
using System.Text;
using System.Linq;
using System.Security.Cryptography;

class AESCipher
{

    public static void Main()
    {
        string aesKey = "1234567890123456";
        string aesIv  = "0123456789123456";

        Console.WriteLine(Encrypt("12345", aesKey, aesIv));
        Console.WriteLine(Decrypt("90B2C15E84CB78E5161F42867807C4BC", aesKey, aesIv));
    }

    static string Encrypt(string plainText, string key, string iv)
    {
        string cipherText;

        var rijndael = new RijndaelManaged()
        {
            Key = Encoding.UTF8.GetBytes(key),
            IV = Encoding.UTF8.GetBytes(iv),
            Mode = CipherMode.CBC,
            BlockSize = 128,
            Padding = PaddingMode.Zeros,
        };
        ICryptoTransform encryptor = rijndael.CreateEncryptor(rijndael.Key, rijndael.IV);

        using (var memoryStream = new MemoryStream())
        {
            using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
            {
                using (var streamWriter = new StreamWriter(cryptoStream))
                {
                    streamWriter.Write(plainText);
                    streamWriter.Flush();
                }
                cipherText = BitConverter.ToString(memoryStream.ToArray()).Replace("-", string.Empty);
            }
        }
        return cipherText;
    }

    static string Decrypt(string cipherText, string key, string iv)
    {
        string plainText;

        var rijndael = new RijndaelManaged()
        {
            Key = Encoding.UTF8.GetBytes(key),
            IV = Encoding.UTF8.GetBytes(iv),
            Mode = CipherMode.CBC,
            BlockSize = 128,
            Padding = PaddingMode.Zeros,
        };
        ICryptoTransform decryptor = rijndael.CreateDecryptor(rijndael.Key, rijndael.IV);

        using (var memoryStream = new MemoryStream(StringToByteArray(cipherText)))
        {
            using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
            {
                using (var streamReader = new StreamReader(cryptoStream))
                {
                    plainText = streamReader.ReadToEnd().Replace("\0", string.Empty);
                }
            }
        }
        return plainText;
    }

    public static byte[] StringToByteArray(string hex) {
        return Enumerable.Range(0, hex.Length)
                         .Where(x => x % 2 == 0)
                         .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
                         .ToArray();
    }
}

# 5、golang

    //AesEncrypt 加密函数
func AesEncrypt(text []byte, key, iv []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		fmt.Println(err)
	}
	// 填充
	blockSize := block.BlockSize()
	paddText := ZeroPadding(text)
	blockMode := cipher.NewCBCEncrypter(block, iv[:blockSize])

	// 加密
	result := make([]byte, len(paddText))
	blockMode.CryptBlocks(result, paddText)
	// 返回密文
	return result, nil
}

// AesDecrypt 解密函数
func AesDecrypt(encrypter []byte, key, iv []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		fmt.Println(err)
	}
	blockSize := block.BlockSize()
	blockMode := cipher.NewCBCDecrypter(block, iv[:blockSize])
	result := make([]byte, len(encrypter))
	blockMode.CryptBlocks(result, encrypter)
	// 去除填充
	result = NullUnPadding(result)
	return result, nil
}

func ZeroPadding(in []byte) []byte {
	length := len(in)
	if length%16 == 0 {
		return in
	} else {
		blockCount := length / 16
		out := make([]byte, (blockCount+1)*16)
		var i int
		for i = 0; i < length; i++ {
			out[i] = in[i]
		}
		return out
	}
}

func NullUnPadding(in []byte) []byte {
	return bytes.TrimRight(in, string([]byte{0}))
}