什么是AES?
密碼學(xué)中的高級(jí)加密標(biāo)準(zhǔn)(Advanced Encryption Standard女揭,AES)吧兔,又稱高級(jí)加密標(biāo)準(zhǔn)Rijndael加密法袍嬉,
是美國(guó)聯(lián)邦政府采用的一種區(qū)塊加密標(biāo)準(zhǔn)伺通。這個(gè)標(biāo)準(zhǔn)用來(lái)替代原先的DES罐监,已經(jīng)被多方分析且廣為全世界
所使用。經(jīng)過(guò)五年的甄選流程沟堡,高級(jí)加密標(biāo)準(zhǔn)由美國(guó)國(guó)家標(biāo)準(zhǔn)與技術(shù)研究院 (NIST)于2001年11月26日
發(fā)布于FIPS PUB197吆你,并在2002年5月26日成為有效的標(biāo)準(zhǔn)妇多。2006年燕侠,高級(jí)加密標(biāo)準(zhǔn)已然成為對(duì)稱密鑰加密
中最流行的算法之一绢彤。該算法為比利時(shí)密碼學(xué)家Joan Daemen和VincentRijmen所設(shè)計(jì),結(jié)合兩位作者的名
字械巡,以Rijndael之命名之饶氏,投稿高級(jí)加密標(biāo)準(zhǔn)的甄選流程。(Rijdael的發(fā)音近于 "Rhinedoll"古程。)
AES加密模式和填充方式
算法/模式/填充 16字節(jié)加密后數(shù)據(jù)長(zhǎng)度 不滿16字節(jié)加密后長(zhǎng)度
AES/CBC/NoPadding 16 不支持
AES/CBC/PKCS5Padding 32 16
AES/CBC/ISO10126Padding 32 16
AES/CFB/NoPadding 16 原始數(shù)據(jù)長(zhǎng)度
AES/CFB/PKCS5Padding 32 16
AES/CFB/ISO10126Padding 32 16
AES/ECB/NoPadding 16 不支持
AES/ECB/PKCS5Padding 32 16
AES/ECB/ISO10126Padding 32 16
AES/OFB/NoPadding 16 原始數(shù)據(jù)長(zhǎng)度
AES/OFB/PKCS5Padding 32 16
AES/OFB/ISO10126Padding 32 16
AES/PCBC/NoPadding 16 不支持
AES/PCBC/PKCS5Padding 32 16
AES/PCBC/ISO10126Padding 32 16
如何實(shí)現(xiàn)加密解密
Java端代碼:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* @author Jacker
*/
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;
public class Encryption
{
public static void main(String args[]) throws Exception {
System.out.println(encrypt());
System.out.println(desEncrypt());
}
public static String encrypt() throws Exception {
try {
String data = "Test String";
String key = "1234567812345678";
String iv = "1234567812345678";
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
int blockSize = cipher.getBlockSize();
byte[] dataBytes = data.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(key.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
byte[] encrypted = cipher.doFinal(plaintext);
return new sun.misc.BASE64Encoder().encode(encrypted);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static String desEncrypt() throws Exception {
try
{
String data = "2fbwW9+8vPId2/foafZq6Q==";
String key = "1234567812345678";
String iv = "1234567812345678";
byte[] encrypted1 = new BASE64Decoder().decodeBuffer(data);
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
byte[] original = cipher.doFinal(encrypted1);
String originalString = new String(original);
return originalString;
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
PHP端代碼
<?php
$privateKey = "1234567812345678";
$iv = "1234567812345678";
$data = "Test String";
//加密
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $privateKey, $data, MCRYPT_MODE_CBC, $iv);
echo(base64_encode($encrypted));
echo '<br/>';
//解密
$encryptedData = base64_decode("2fbwW9+8vPId2/foafZq6Q==");
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $privateKey, $encryptedData, MCRYPT_MODE_CBC, $iv);
echo($decrypted);
?>
C#端代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
namespace pda_demo
{
class Program
{
static void Main(string[] args)
{
String encryptData = Program.Encrypt("Test String", "1234567812345678", "1234567812345678");
Console.WriteLine(encryptData);
String decryptData = Program.Decrypt("2fbwW9+8vPId2/foafZq6Q==", "1234567812345678", "1234567812345678");
Console.WriteLine(decryptData);
Console.Read();
}
public static string Encrypt(string toEncrypt, string key, string iv)
{
byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
byte[] ivArray = UTF8Encoding.UTF8.GetBytes(iv);
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
RijndaelManaged rDel = new RijndaelManaged();
rDel.Key = keyArray;
rDel.IV = ivArray;
rDel.Mode = CipherMode.CBC;
rDel.Padding = PaddingMode.Zeros;
ICryptoTransform cTransform = rDel.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
public static string Decrypt(string toDecrypt, string key, string iv)
{
byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
byte[] ivArray = UTF8Encoding.UTF8.GetBytes(iv);
byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);
RijndaelManaged rDel = new RijndaelManaged();
rDel.Key = keyArray;
rDel.IV = ivArray;
rDel.Mode = CipherMode.CBC;
rDel.Padding = PaddingMode.Zeros;
ICryptoTransform cTransform = rDel.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return UTF8Encoding.UTF8.GetString(resultArray);
}
}
}
JavaScript
需要引入 crypto-js庫(kù)用來(lái)加密
function Encrypt(data) {
let key = CryptoJS.enc.Latin1.parse('123456789') // key
let iv = CryptoJS.enc.Latin1.parse('123456789') // iv
let encrypted = CryptoJS.AES.encrypt(data, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.ZeroPadding
})
return encodeURIComponent(CryptoJS.enc.Base64.stringify(encrypted.ciphertext))
}
function Decrypt(encrypted) {
let decrypted = CryptoJS.AES.decrypt(encrypted, key, {
iv: iv,
padding: CryptoJS.pad.ZeroPadding
})
return decrypted.toString(CryptoJS.enc.Utf8)
}
const data= Encrypt("123456789") // 加密后的123456789
console.log(data)
const str = Decrypt(data)
console.log(str)