jce中提供了加解密的api:

1、首先应该明白AES是基于数据块的加密方式,也就是说,每次处理的数据是一块(16字节),当数据不是16字节的倍数时填充,这就是所谓的分组密码(区别于基于比特位的流密码),16字节是分组长度

AES支持五种模式:CBC,CFB,ECB,OFB,PCBC,

jce中实现了三种补码方式:NoPadding,PKCS5Padding,ISO10126Padding;不支持SSL3Padding,不支持“NONE”模式。

ECB:是一种基础的加密方式,密文被分割成分组长度相等的块(不足补齐),然后单独一个个加密,一个个输出组成密文。
CBC:是一种循环模式,前一个分组的密文和当前分组的明文异或操作后再加密,这样做的目的是增强破解难度。
CFB/OFB实际上是一种反馈模式,目的也是增强破解的难度。
ECB和CBC的加密结果是不一样的,两者的模式不同,而且CBC会在第一个密码块运算时加入一个初始化向量。

算法/模式/填充                    16字节加密后数据长度         不满16字节加密后长度

AES/CBC/NoPadding                  16                         不支持
AES/CBC/PKCS5Padding             32                         16
AES/CBC/ISO10126Padding        32                          16
AES/CFB/NoPadding                    16                          原始数据长度
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                          原始数据长度
AES/OFB/PKCS5Padding               32                          16
AES/OFB/ISO10126Padding          32                          16
AES/PCBC/NoPadding                   16                          不支持
AES/PCBC/PKCS5Padding             32                          16
AES/PCBC/ISO10126Padding        32                          16
可 以看到,在原始数据长度为16的整数倍时,假如原始数据长度等于16*n,则使用NoPadding时加密后数据长度等于16*n,其它情况下加密数据长 度等于16*(n+1)。在不足16的整数倍的情况下,假如原始数据长度等于16*n+m[其中m小于16],除了NoPadding填充之外的任何方 式,加密数据长度都等于16*(n+1);NoPadding填充情况下,CBC、ECB和PCBC三种模式是不支持的,CFB、OFB两种模式下则加密 数据长度等于原始数据长度。

Demo:

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class AESCoder { private static final Logger log=LoggerFactory.getLogger(AESCoder.class); /**
* 加密
* hexStr和hexKey都须为16进制表示的字符串
* 加密后返回16进制表示的字符串*/
public static String ecbEnc(String hexStr, String hexKey){
String rs=null;
try {
byte[] inBytes = HexUtil.hexToBytes(hexStr);
byte[] keyBytes = HexUtil.hexToBytes(hexKey);
SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");// "算法/模式/补码方式"
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(inBytes);
rs=HexUtil.bytesToHex(encrypted);
} catch (Exception e) {
log.error("加密异常",e);
log.error("输入参数为hexStr:{},hexKey:{}",hexStr,hexKey);
}
return rs;
} /**
* 解密
* hexStr和hexKey都须为16进制
* 加密后返回16进制的字符串*/
public static String ecbDec(String hexStr,String hexKey){
String rs=null;
try {
byte[] outBytes = HexUtil.hexToBytes(hexStr);
byte[] keyBytes = HexUtil.hexToBytes(hexKey);
SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");// "算法/模式/补码方式"
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decBytes = cipher.doFinal(outBytes);
rs=HexUtil.bytesToHex(decBytes);
} catch (Exception e) {
log.error("解密异常",e);
log.error("输入参数为hexStr:{},hexKey:{}",hexStr,hexKey);
}
return rs;
} }
public class HexUtil {

    /**
* 将普通字符串用16进制描述
* 如"WAZX-B55SY6-S6DT5" 描述为:"57415a582d4235355359362d5336445435"
* */
public static String strToHex(String str){
byte[] bytes = str.getBytes();
return bytesToHex(bytes);
} /**将16进制描述的字符串还原为普通字符串
* 如"57415a582d4235355359362d5336445435" 还原为:"WAZX-B55SY6-S6DT5"
* */
public static String hexToStr(String hex){
byte[] bytes=hexToBytes(hex);
return new String(bytes);
} /**16进制转byte[]*/
public static byte[] hexToBytes(String hex){
int length = hex.length() / 2;
byte[] bytes=new byte[length];
for(int i=0;i<length;i++){
String tempStr=hex.substring(2*i, 2*i+2);//byte:8bit=4bit+4bit=十六进制位+十六进制位
bytes[i]=(byte) Integer.parseInt(tempStr, 16);
}
return bytes;
} /**byte[]转16进制*/
public static String bytesToHex(byte[] bytes){
StringBuilder sb=new StringBuilder();
for(int i=0;i<bytes.length;i++){
int tempI=bytes[i] & 0xFF;//byte:8bit,int:32bit;高位相与.
String str = Integer.toHexString(tempI);
if(str.length()<2){
sb.append(0).append(str);//长度不足两位,补齐:如16进制的d,用0d表示。
}else{
sb.append(str);
}
}
return sb.toString();
} }
public class AESTest {

    private static String key="2b7e151628aed2a6abf7158809cf4f3c";

    @Test
public void test_all(){
String enOri="000000000000000WAZX-B55SY6-S6DT5";
String enHex=HexUtil.strToHex(enOri);
String enRS=AESCoder.ecbEnc(enHex,key);
System.out.println("加密结果为:"+enRS); String deHex="7312560ccb30ad9b445ee94b426c8a2bdf75d11ded50f053568ec08bf3f9be04";
String deRS=AESCoder.ecbDec(deHex,key);
String deOri=HexUtil.hexToStr(deRS);
System.out.println("解密结果为:"+deOri);
} @Test
public void test_enc(){
String enStr ="6bc1bee22e409f96e93d7e117393172a";
String enRS=AESCoder.ecbEnc(enStr,key);
System.out.println(enRS);
} @Test
public void test_dec(){
String deStr ="3ad77bb40d7a3660a89ecaf32466ef97";
String enRS=AESCoder.ecbDec(deStr,key);
System.out.println(enRS); } /**
* 和后台联调时使用
* 该函数用于讲16进制数组转成String
* 如密钥key为
* uint8_t key[] =
* {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
* 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}
* 则格式化之后为"2b7e151628aed2a6abf7158809cf4f3c"
* */
public static String convertStr(String hexStr) {
String[] kStrs = hexStr.split(",");
String[] keyStrs = new String[kStrs.length];
for (int i = 0; i < kStrs.length; i++) {
String str = kStrs[i].trim().substring(2);
keyStrs[i] = str;
}
StringBuffer sb = new StringBuffer();
for (String str : keyStrs) {
sb.append(str);
}
return sb.toString().toUpperCase();
} }

AESTest运行结果:

加密结果为:7312560ccb30ad9b445ee94b426c8a2bdf75d11ded50f053568ec08bf3f9be04
解密结果为:000000000000000WAZX-B55SY6-S6DT5

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

--------------------------------------------------------------此外,还有另外一个写法-----------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec; public class AESHelper { public static String encrypt(String content, String pwd,String charSet) {
try {
byte[] byteContent = content.getBytes(charSet); KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128, new SecureRandom(pwd.getBytes())); Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES")); byte[] buf = cipher.doFinal(byteContent); //byte[]转16进制
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString(); } catch (Exception e) {
e.printStackTrace();
}
return null;
} /***
*
* @param content 16进制的字符串
* @param pwd
* @param charSet
* @return
*/
public static String decrypt(String content, String pwd,String charSet) {
try {
byte[] byteContent = new byte[content.length() / 2];
if (content.length() < 1){
return null;
}
//将16进制转换为二进制
for (int i = 0; i < content.length() / 2; i++) {
int high = Integer.parseInt(content.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(content.substring(i * 2 + 1, i * 2 + 2), 16);
byteContent[i] = (byte) (high * 16 + low);
} KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128, new SecureRandom(pwd.getBytes())); Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES")); byte[] buf = cipher.doFinal(byteContent);
return new String(buf,charSet); } catch (Exception e) {
e.printStackTrace();
}
return null;
} public static void main(String[] args) {
String layer = AESHelper.encrypt("编程ABCDefgh~!@#$%^&*()|'?>.<;", "123","utf-8");
System.out.println(layer);
String plain = AESHelper.decrypt(layer,"123","utf-8");
System.out.println(plain);
} }

据说要加上要两句话,不然,跨操作系统加解密可能有问题:

SecureRandom secureRandom=SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(pwd.getBytes());

最终写法:

import java.security.Key;
import java.security.SecureRandom; import javax.crypto.Cipher;
import javax.crypto.KeyGenerator; public class AESHelper { public static String encrypt(String content) {
return encrypt(content, null, "utf-8");
} /***
* 加密
*
* @param plain
* @param keySeed
* @param charSet
* @return 输出密文 16进制
*/
public static String encrypt(String plain, String keySeed, String charSet) {
try {
byte[] byteContent = plain.getBytes(charSet);
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, getKey(keySeed)); byte[] buf = cipher.doFinal(byteContent); // byte[]转16进制
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString(); } catch (Exception e) {
e.printStackTrace();
}
return null;
} public static String decrypt(String content) {
return decrypt(content, null, "utf-8");
} /***
* 解密 输入16进制的字符串
*
* @param layer
* @param keySeed
* @param charSet
* @return 原文
*/
public static String decrypt(String layer, String keySeed, String charSet) {
try {
byte[] byteContent = new byte[layer.length() / 2];
if (layer.length() < 1) {
return null;
}
// 将16进制转换为二进制
for (int i = 0; i < layer.length() / 2; i++) {
int high = Integer.parseInt(layer.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(layer.substring(i * 2 + 1, i * 2 + 2), 16);
byteContent[i] = (byte) (high * 16 + low);
} Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, getKey(keySeed)); byte[] buf = cipher.doFinal(byteContent);
return new String(buf, charSet); } catch (Exception e) {
e.printStackTrace();
}
return null;
} public static Key getKey(String keySeed) {
if (keySeed == null) {
keySeed = System.getenv("AES_SYS_KEY");
}
if (keySeed == null) {
keySeed = System.getProperty("AES_SYS_KEY");
}
if (keySeed == null || keySeed.trim().length() == 0) {
keySeed = "abcd1234!@#$";// 默认种子
}
try {
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(keySeed.getBytes());
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(secureRandom);
return generator.generateKey();
} catch (Exception e) {
throw new RuntimeException(e);
}
} public static void main(String[] args) {
if(null==args||args.length==0){
args=new String[1];
args[0]="编程ABCDefgh~!@#$%^&*()|'?>.<;1234567823401";
}
String layer = AESHelper.encrypt(args[0]);
System.out.println("密文:"+layer);
String plain = AESHelper.decrypt(layer);
System.out.println("原文:"+plain);
} }

linux 运行该方法:

  

[zhangbin@WEB01 test]$ java AESHelper "jwe223489430214aefhasduf3423"
密文:49336565BD95CB2E70297F4F89DEE2D37EA6A7C14A320194848CF17E930B1DB5
原文:jwe223489430214aefhasduf3423

java加密算法之AES小记的更多相关文章

  1. JAVA加密算法系列-AES

    package ***; import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; ...

  2. Atitit.加密算法 des  aes 各个语言不同的原理与解决方案java php c#

    Atitit.加密算法 des  aes 各个语言不同的原理与解决方案java php c# 1. 加密算法的参数::算法/模式/填充 1 2. 标准加密api使用流程1 2.1. Md5——16bi ...

  3. Atitit.加密算法ati Aes的框架设计

    Atitit.加密算法ati Aes的框架设计 版本进化 c:\1t\aesC47.java c:\1t\aes.java 增加了public static byte[] encrypt(byte[] ...

  4. Atitit.加密算法ati Aes的框架设计v2.2

    Atitit.加密算法ati Aes的框架设计v2.2 版本进化1 V2.2   add def decode key api1 v1版本1 Aes的历史2 Atitit.加密算法 des  aes  ...

  5. java加密算法入门(二)-对称加密详解

    1.简单介绍 什么是对称加密算法? 对称加密算法即,加密和解密使用相同密钥的算法. 优缺点: 优点:算法公开.计算量小.加密速度快.加密效率高. 缺点: (1)交易双方都使用同样钥匙,安全性得不到保证 ...

  6. Java加密算法

    密码的常用术语: 1.密码体制:由明文空间.密文空间.密钥空间.加密算法和解密算法5部分组成. 2.密码协议:也称为安全协议,是指以密码学为基础的消息交换的通信协议,目的是在网络环境中提供安全的服务. ...

  7. java C# objective-c AES对称加解密

    /** * AES加解密 */ public class AESHelper { final static String AES_KEY = "43hr8fhu34b58123"; ...

  8. Java中的AES加解密工具类:AESUtils

    本人手写已测试,大家可以参考使用 package com.mirana.frame.utils.encrypt; import com.mirana.frame.constants.SysConsta ...

  9. Java加密算法 RSA

    Java加密算法 RSA 2015-06-06 08:44 511人阅读 评论(0) 收藏 举报  分类: JAVA(57)  公钥加密也称为非对称加密.速度慢.加密和解密的钥匙不相同,某一个人持有私 ...

随机推荐

  1. myeclipse里的调试快捷键

    好多时候在调试代码时,有的时候只会用F5,其他的快捷键却一概不知.今天百度查了一下其他快捷键调试的作用,总结如下 F5 (setp into ): 跳入当前执行的方法中 F6 (step over): ...

  2. Flex 利用Space控制进行组件的右对齐

    Spacer 控件可帮助您布置父容器中的子项.虽然 Spacer 控件不会绘制任何内容,但它会在父容器中为其本身分配空间. 在以下示例中,使用灵活的 Spacer 控件将 Button 控件推到右侧, ...

  3. 2016.12.01 搭建dendroid备忘

    在2014年的时候看了freebuf的那篇,感觉很6,2014年搭了就一遍成功了,事过两年,物是人非啊,2016搞了云,没事测试,搞了一遍死活不成功,第二天测试成功,过程逗比坎坷,没什么难的 //环境 ...

  4. windows server2008 kettle部署

    kettle部署需要有jdk环境,所以需要配置环境变量. 1.首先配置jdk,将jdk压缩包解压到c盘下 增加系统变量:JAVA_HOME:c:\jdk 在path后追加: %JAVA_HOME%\b ...

  5. Codeforces Round #169 (Div. 2)

    A. Lunch Rush 模拟. B. Little Girl and Game 因为可以打乱顺序,所以只关心每种数字打奇偶性. 若一开始就是回文,即奇数字母为0或1种,则先手获胜. 若奇数字母大于 ...

  6. PHP Date()函数详细参数

    在页面的最前页加上 date_default_timezone_set(PRC); /*把时间调到北京时间,php5默认为格林威治标准时间*/ date () a: "am"或是& ...

  7. Java操作redis简单示例

    第一:安装Redis    首先我们要安装Redis,就像我们操作数据库一样,在操作之前肯定要先创建好数据库的环境.    Redis的下载可以百度一下,或者打开下面的下载链接:    https:/ ...

  8. javascript知识点之DOM与window对象

    在学习javascript过程中只是一知半解好多,碰到自己不知道属性方法,到最后都不知道自己学到了什么 js代码为什么这样写 为什么你知道这方法或属性可以这样用. DOM和window对象 DOM基本 ...

  9. unity行为树制作AI简单例子(1)

    用行为树来制作AI是非常方便的,今天就给大家简单介绍一下行为树的强大之处. 所用插件 Behavior Designer v1.421 最开始 我使用过Rain插件,不过用过Behavior Desi ...

  10. u-boot-2010.09移植(B)

    前面我们的u-boot只是在内存中运行,要想在nandflash中运行,以达到开机自启的目的,还需作如下修改 一.添加DM9000网卡支持 1.修改board/fl2440/fl2440.c中的boa ...