高级加密标准(Advanced Encryption Standard,简写AES),是一种用来替代DES的对称加密算法,相比DES,AES安全性更高,加密速度更快,因此被广泛使用。

  理论上看,AES可被破解,但是就目前的硬件性能来看,目前AES还是安全的,在开发工程中,如果要使用对称加密算法,应该首选AES。

  下面使用介绍各语言中的DES加密解密实现:

    

    1、加密解密过程分别使用比较多的ECB和CBC两种方式来实现,ECB性能更快,但是安全性没有CBC好,所以目前CBC用的比较多
2、加密解密填充方式采用PKCS7,或者PKCS5,这两者在这里的加密解密过程中的结果可以认为是一样的
3、CBC模式需要秘钥及初始向量,而ECB模式只需要秘钥即可,所以为了方便,下面封装的方法或者函数将通过判断是否存在初始向量来决定是使用CBC模式还是使用ECB模式

  Java

  首先,做一个封装:  

  

    import java.security.Key;

    import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec; public class AesUtil { /**
* DES加密
*
* @param value
* 待机加密明文
* @param secretKey
* 秘钥
* @param iv
* 初始向量,如果未空,则将采用ECB模式,否则采用CBC模式
*
* @return 密文
*/
public static String aesEncrypt(String value, String secretKey, String iv)
throws Exception {
if (value == null || value.length() == 0)
return ""; Cipher cipher = initCipher(Cipher.ENCRYPT_MODE, secretKey, iv);
byte[] buffer = cipher.doFinal(value.getBytes("utf-8"));
// 使用hex格式数据输出
StringBuffer result = new StringBuffer();
for (int i = 0; i < buffer.length; i++) {
result.append(String.format("%02x", buffer[i]));
}
return result.toString(); } /**
* DES解密
*
* @param value
* 密文
* @param secretKey
* 秘钥
* @param iv
* 初始向量,如果未空,则将采用ECB模式,否则采用CBC模式
*
* @return 解密后的明文
*/
public static String aesDecrypt(String value, String secretKey, String iv)
throws Exception {
if (value == null || value.length() == 0)
return ""; // 转换hex格式数据未byte数组
int length = value.length();
byte[] buffer = new byte[length / 2];
for (int i = 0; i < buffer.length; i++) {
buffer[i] = (byte) Integer.parseInt(
value.substring(i * 2, i * 2 + 2), 16);
} Cipher cipher = initCipher(Cipher.DECRYPT_MODE, secretKey, iv);
buffer = cipher.doFinal(buffer);
return new String(buffer, "utf-8");
} private static Cipher initCipher(int mode, String secretKey, String iv)
throws Exception { try {
// 获取秘钥数组
byte[] secretBytes = secretKey.getBytes("utf-8");
byte[] keyBytes = new byte[16];
System.arraycopy(secretBytes, 0, keyBytes, 0,
Math.min(secretBytes.length, keyBytes.length));
Key key = new SecretKeySpec(keyBytes, "AES"); if (iv == null || iv.length() == 0) {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");// 采用ECB方式
cipher.init(mode, key);
return cipher;
} else {
// 初始向量数组
byte[] ivBytes = iv.getBytes("utf-8");
byte[] ivKeyBytes = new byte[16];
System.arraycopy(ivBytes, 0, ivKeyBytes, 0,
Math.min(ivBytes.length, ivKeyBytes.length)); IvParameterSpec ivp = new IvParameterSpec(ivKeyBytes);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");// 采用CBC方式
cipher.init(mode, key, ivp);
return cipher;
}
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
}

AesUtil

  然后测试调用:  

    public static void main(String[] args) {
String text = "上山打老虎";
String key = "123456";
String iv = "abcdefg";
try {
String encryptText1 = AesUtil.aesEncrypt(text, key, iv);
System.out.printf("【%s】经过【AES-CBC】加密后:%s\n", text, encryptText1); String decryptText1 = AesUtil.aesDecrypt(encryptText1, key, iv);
System.out.printf("【%s】经过【AES-CBC】解密后:%s\n", encryptText1,
decryptText1); String encryptText2 = AesUtil.aesEncrypt(text, key, null);
System.out.printf("【%s】经过【AES-ECB】加密后:%s\n", text, encryptText2); String decryptText2 = AesUtil.aesDecrypt(encryptText2, key, null);
System.out.printf("【%s】经过【AES-ECB】解密后:%s\n", encryptText2,
decryptText2); } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

  执行结果:

  

  C#

  同样先做一个封装类:  

  

    using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text; namespace ConsoleApp1
{
public class AesHelper
{
#region AES
/// <summary>
/// 创建算法操作对象
/// </summary>
/// <param name="secretKey"></param>
/// <param name="iv"></param>
/// <returns></returns>
private static RijndaelManaged CreateRijndaelManaged(string secretKey, string iv)
{
RijndaelManaged rijndaelManaged = new RijndaelManaged();
rijndaelManaged.Padding = PaddingMode.PKCS7;
rijndaelManaged.KeySize = 128;
rijndaelManaged.BlockSize = 128; rijndaelManaged.Mode = CipherMode.CBC; byte[] secretBytes = Encoding.UTF8.GetBytes(secretKey);
byte[] keyBytes = new byte[16];
Array.Copy(secretBytes, keyBytes, Math.Min(secretBytes.Length, keyBytes.Length));
rijndaelManaged.Key = keyBytes; if (string.IsNullOrEmpty(iv))
{
rijndaelManaged.Mode = CipherMode.ECB;
}
else
{
rijndaelManaged.Mode = CipherMode.CBC; byte[] array = Encoding.UTF8.GetBytes(iv);
byte[] ivBytes = new byte[keyBytes.Length];
Array.Copy(array, ivBytes, Math.Min(array.Length, ivBytes.Length));
rijndaelManaged.IV = ivBytes;
}
return rijndaelManaged;
}
/// <summary>
/// Aes加密
/// </summary>
/// <param name="value"></param>
/// <param name="secretKey"></param>
/// <param name="iv"></param>
/// <returns></returns>
public static string AesEncrypt(string value, string secretKey, string iv)
{
if (string.IsNullOrEmpty(value)) return string.Empty; using (RijndaelManaged rijndaelManaged = CreateRijndaelManaged(secretKey, iv))
{
using (ICryptoTransform iCryptoTransform = rijndaelManaged.CreateEncryptor())
{
byte[] buffer = Encoding.UTF8.GetBytes(value);
buffer = iCryptoTransform.TransformFinalBlock(buffer, 0, buffer.Length);
//使用hex格式输出数据
StringBuilder result = new StringBuilder();
foreach (byte b in buffer)
{
result.AppendFormat("{0:x2}", b);
}
return result.ToString();
//或者使用下面的输出
//return BitConverter.ToString(buffer).Replace("-", "").ToLower();
}
}
}
/// <summary>
/// Aes解密
/// </summary>
/// <param name="value"></param>
/// <param name="secretKey"></param>
/// <param name="iv"></param>
/// <returns></returns>
public static string AesDecrypt(string value, string secretKey, string iv)
{
if (string.IsNullOrEmpty(value)) return string.Empty; using (RijndaelManaged rijndaelManaged = CreateRijndaelManaged(secretKey, iv))
{
using (ICryptoTransform iCryptoTransform = rijndaelManaged.CreateDecryptor())
{
//转换hex格式数据为byte数组
byte[] buffer = new byte[value.Length / 2];
for (var i = 0; i < buffer.Length; i++)
{
buffer[i] = (byte)Convert.ToInt32(value.Substring(i * 2, 2), 16);
}
buffer = iCryptoTransform.TransformFinalBlock(buffer, 0, buffer.Length);
return Encoding.UTF8.GetString(buffer);
}
}
}
#endregion
}
}

AesHelper

  测试代码:  

    static void Main(string[] args)
{
string text = "上山打老虎";
string key = "123456";
string iv = "abcdefg"; string encryptText1 = AesHelper.AesEncrypt(text, key, iv);
Console.WriteLine($"【{text}】经过【AES-CBC】加密后:{encryptText1}"); string decryptText1 = AesHelper.AesDecrypt(encryptText1, key, iv);
Console.WriteLine($"【{encryptText1}】经过【AES-CBC】解密后:{decryptText1}"); string encryptText2 = AesHelper.AesEncrypt(text, key, null);
Console.WriteLine($"【{text}】经过【AES-ECB】加密后:{encryptText2}"); string decryptText2 = AesHelper.AesDecrypt(encryptText2, key, null);
Console.WriteLine($"【{encryptText2}】经过【AES-ECB】解密后:{decryptText2}");
}

  执行结果:

  

  Golang

  加密解密函数如下:

  

package main

import (
"bytes"
"crypto/aes"
"crypto/cipher"
"fmt"
"strconv"
) //AES加密
//iv为空则采用ECB模式,否则采用CBC模式
func AesEncrypt(value, secretKey, iv string) (string, error) {
if value == "" {
return "", nil
} //根据秘钥生成16位的秘钥切片
keyBytes := make([]byte, aes.BlockSize)
copy(keyBytes, []byte(secretKey))
//获取block
block, err := aes.NewCipher(keyBytes)
if err != nil {
return "", err
} blocksize := block.BlockSize()
valueBytes := []byte(value) //填充
fillsize := blocksize - len(valueBytes)%blocksize
repeat := bytes.Repeat([]byte{byte(fillsize)}, fillsize)
valueBytes = append(valueBytes, repeat...) result := make([]byte, len(valueBytes)) //加密
if iv == "" {
temp := result
for len(valueBytes) > 0 {
block.Encrypt(temp, valueBytes[:blocksize])
valueBytes = valueBytes[blocksize:]
temp = temp[blocksize:]
}
} else {
//向量切片
ivBytes := make([]byte, aes.BlockSize)
copy(ivBytes, []byte(iv)) encrypter := cipher.NewCBCEncrypter(block, ivBytes)
encrypter.CryptBlocks(result, valueBytes)
} //以hex格式数值输出
encryptText := fmt.Sprintf("%x", result)
return encryptText, nil
} //AES解密
//iv为空则采用ECB模式,否则采用CBC模式
func AesDecrypt(value, secretKey, iv string) (string, error) {
if value == "" {
return "", nil
} //根据秘钥生成8位的秘钥切片
keyBytes := make([]byte, aes.BlockSize)
copy(keyBytes, []byte(secretKey))
//获取block
block, err := aes.NewCipher(keyBytes)
if err != nil {
return "", err
} //将hex格式数据转换为byte切片
valueBytes := []byte(value)
var encryptedData = make([]byte, len(valueBytes)/2)
for i := 0; i < len(encryptedData); i++ {
b, err := strconv.ParseInt(value[i*2:i*2+2], 16, 10)
if err != nil {
return "", err
}
encryptedData[i] = byte(b)
} result := make([]byte, len(encryptedData)) if iv == "" {
blocksize := block.BlockSize()
temp := result
for len(encryptedData) > 0 {
block.Decrypt(temp, encryptedData[:blocksize])
encryptedData = encryptedData[blocksize:]
temp = temp[blocksize:]
}
} else {
//向量切片
ivBytes := make([]byte, aes.BlockSize)
copy(ivBytes, []byte(iv)) //解密
blockMode := cipher.NewCBCDecrypter(block, ivBytes)
blockMode.CryptBlocks(result, encryptedData)
} //取消填充
unpadding := int(result[len(result)-1])
result = result[:(len(result) - unpadding)]
return string(result), nil
}

aesutil

  单元测试:  

package main

import (
"fmt"
"testing"
) func TestAes(t *testing.T) {
text := "上山打老虎"
key := "123456"
iv := "abcdefg" encryptText1, _ := AesEncrypt(text, key, iv)
fmt.Printf("【%s】经过【AES-CBC】加密后:%s\n", text, encryptText1) decryptText1, _ := AesDecrypt(encryptText1, key, iv)
fmt.Printf("【%s】经过【AES-CBC】解密后:%s\n", encryptText1, decryptText1) encryptText2, _ := AesEncrypt(text, key, "")
fmt.Printf("【%s】经过【AES-ECB】加密后:%s\n", text, encryptText2) decryptText2, _ := AesDecrypt(encryptText2, key, "")
fmt.Printf("【%s】经过【AES-ECB】解密后:%s\n", encryptText2, decryptText2)
}

  测试结果:

  

  Python

  python的AES加密相对简单,同样的,需要安装pycrypto,可以使用pip安装:pip install pycryptodome(如果安装不了,先卸载旧版本再安装:pip uninstall pycrypto)。

  直接上代码:  

# 需要安装pycrypto,可以使用pip安装:pip install pycryptodome
from Crypto.Cipher import AES BLOCK_SIZE = 16 def init_cipher(secret_key, iv_key):
secret_bytes = secret_key.encode(encoding='utf-8')
key_bytes = []
if len(secret_bytes) >= BLOCK_SIZE:
key_bytes = secret_bytes[:BLOCK_SIZE]
else:
key_bytes.extend(secret_bytes)
key_bytes.extend([0 for x in range(0, BLOCK_SIZE - len(secret_bytes))]) if iv_key is None or len(iv_key) == 0:
cipher = AES.new(bytes(key_bytes), AES.MODE_ECB)
return cipher
else:
iv_bytes = iv_key.encode(encoding='utf-8')
iv_key_bytes = []
if len(iv_bytes) >= BLOCK_SIZE:
iv_key_bytes = iv_bytes[:BLOCK_SIZE]
else:
iv_key_bytes.extend(iv_bytes)
iv_key_bytes.extend([0 for x in range(0, BLOCK_SIZE - len(iv_bytes))]) cipher = AES.new(bytes(key_bytes), AES.MODE_CBC, bytes(iv_key_bytes))
return cipher def aes_encrypt(value, secret_key, iv_key):
cipher = init_cipher(secret_key, iv_key) buffer = value.encode(encoding="utf-8")
bufferList = list(buffer) # 数据进行 PKCS5Padding 的填充
padding = BLOCK_SIZE - len(bufferList) % BLOCK_SIZE
bufferList.extend([padding for x in range(0, padding)]) buffer = cipher.encrypt(bytes(bufferList))
return buffer.hex() # 使用hex格式输出 def aes_decrypt(value, secret_key, iv_key):
cipher = init_cipher(secret_key, iv_key)
buffer = bytes.fromhex(value) # 读取hex格式数据
buffer = cipher.decrypt(buffer)
result = buffer.decode("utf-8") # 去掉 PKCS5Padding 的填充
return result[:-ord(result[len(result) - 1:])] text = "上山打老虎"
key = "123456"
iv = "abcdefg" encryptText1 = aes_encrypt(text, key, iv)
print("【", text, "】经过【AES-CBC】加密后:", encryptText1) decryptText1 = aes_decrypt(encryptText1, key, iv)
print("【", encryptText1, "】经过【AES-CBC】解密后:", decryptText1) encryptText2 = aes_encrypt(text, key, None)
print("【", text, "】经过【AES-ECB】加密后:", encryptText2) decryptText2 = aes_decrypt(encryptText2, key, None)
print("【", encryptText2, "】经过【AES-ECB】解密后:", decryptText2)

  执行结果:

  

AES对称加密算法实现:Java,C#,Golang,Python的更多相关文章

  1. Java 加密 AES 对称加密算法

    版权声明:本文为博主原创文章,未经博主允许不得转载. [AES] 一种对称加密算法,DES的取代者. 加密相关文章见:Java 加密解密 对称加密算法 非对称加密算法 MD5 BASE64 AES R ...

  2. JAVA中AES对称加密和解密以及与Python兼容

    引言:本文主要解决Java中用AES加密及解密,同时可通过Python脚本对Java加密后的字符进行解密的操作. 由于近期工作中用到需要使用Java对一串密钥进行加密,并且后台通过Python语言读取 ...

  3. Java实现AES对称加密算法

    Java代码实现 import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.KeyGener ...

  4. AES对称加密算法原理

    原著:James McCaffrey 翻译:小刀人 原文出处:MSDN Magazine November 2003 (Encrypt It) 本文的代码下载:msdnmag200311AES.exe ...

  5. AES对称加密算法原理(转载)

    出处:http://www.2cto.com/Article/201112/113465.html 原著:James McCaffrey 翻译:小刀人 原文出处:MSDN Magazine Novem ...

  6. AES对称加密算法

    package cn.jsonlu.passguard.utils; import org.apache.commons.codec.binary.Base64; import javax.crypt ...

  7. DES对称加密算法实现:Java,C#,Golang,Python

    数据加密标准(DES,Data Encryption Standard,简写DES)是一种采用块密码加密的对称密钥算法,加密分组长度为64位,其中8.16.24.32.40.48.56.64 等8位是 ...

  8. Java 加密解密 对称加密算法 非对称加密算法 MD5 BASE64 AES RSA

    版权声明:本文为博主原创文章,未经博主允许不得转载. [前言] 本文简单的介绍了加密技术相关概念,最后总结了java中现有的加密技术以及使用方法和例子 [最简单的加密] 1.简单的概念 明文:加密前的 ...

  9. 常用加密算法的Java实现总结(二) ——对称加密算法DES、3DES和AES

    1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发 ...

随机推荐

  1. 如何设置eclipse下查看java源码

    windows--preferences--java--installed jres --选中jre6--点击右边的edit--选中jre6/lib/rt.jar --点击右边的 source att ...

  2. Java常用类,这一次帮你总结好!

    常用类 常用类概述: 内部类 Object类 包装类 数学类 时间类 字符串 String Builder和StringBuffer DecimalFormat 一.内部类 概念:在一个类内部再定义一 ...

  3. Python用matplotlib绘图网格线的设置

    一.X轴网格线的设置 import matplotlib.pyplot as plt import numpy as np from pylab import mpl mpl.rcParams['fo ...

  4. Python测试框架pytest入门基础

    Pytest简介 Pytest is a mature full-featured Python testing tool that helps you write better programs.T ...

  5. 我的邮箱客户端程序Popmail

    05年的时候写了一个邮箱客户端程序.当时主要目的是研究POP3和SMTP协议,同时锻炼自己的网络编程能力.当然了,如果自己写的邮箱客户端能够满足自身的日常工作需要,而不是频繁的登录不同的网页邮箱,那就 ...

  6. pycharm字体放大的设置

    一.pycharm字体放大的设置 File -> setting -> Keymap ->在搜寻框中输入:increase -> Increase Font Size(双击) ...

  7. GAN 简介

    GAN 原理: ​GAN 的主要灵感来源于博弈论中零和博弈的思想,应用到深度学习神经网络上来说,就是通过生成网络 G(Generator)和判别网络 D(Discriminator)不断博弈,进而使 ...

  8. GoLang设计模式18 - 适配器模式

    说明 适配器模式是一种结构型设计模式.我们用常用的两种笔记本电脑来说明一下这种设计模式. 我们常用的笔记本无非是这两大类: Macbook Pro Windows Laptop 当前这两类笔记本常见的 ...

  9. visual studio c++项目文件分类混乱整理

    演示环境: win10 + vs2015 (下面简称VS)+ visual assist (下面简称VA) 1.混乱 装了VA的VS,有个快捷键,可快速切换 .h 文件和 .cpp(.cc, .cxx ...

  10. 【LeetCode】939. Minimum Area Rectangle 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 确定对角线,找另外两点(4sum) 字典保存出现的x ...