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:

  1. import javax.crypto.Cipher;
  2. import javax.crypto.spec.SecretKeySpec;
  3.  
  4. import org.slf4j.Logger;
  5. import org.slf4j.LoggerFactory;
  6.  
  7. public class AESCoder {
  8.  
  9. private static final Logger log=LoggerFactory.getLogger(AESCoder.class);
  10.  
  11. /**
  12. * 加密
  13. * hexStr和hexKey都须为16进制表示的字符串
  14. * 加密后返回16进制表示的字符串*/
  15. public static String ecbEnc(String hexStr, String hexKey){
  16. String rs=null;
  17. try {
  18. byte[] inBytes = HexUtil.hexToBytes(hexStr);
  19. byte[] keyBytes = HexUtil.hexToBytes(hexKey);
  20. SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, "AES");
  21. Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");// "算法/模式/补码方式"
  22. cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
  23. byte[] encrypted = cipher.doFinal(inBytes);
  24. rs=HexUtil.bytesToHex(encrypted);
  25. } catch (Exception e) {
  26. log.error("加密异常",e);
  27. log.error("输入参数为hexStr:{},hexKey:{}",hexStr,hexKey);
  28. }
  29. return rs;
  30. }
  31.  
  32. /**
  33. * 解密
  34. * hexStr和hexKey都须为16进制
  35. * 加密后返回16进制的字符串*/
  36. public static String ecbDec(String hexStr,String hexKey){
  37. String rs=null;
  38. try {
  39. byte[] outBytes = HexUtil.hexToBytes(hexStr);
  40. byte[] keyBytes = HexUtil.hexToBytes(hexKey);
  41. SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, "AES");
  42. Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");// "算法/模式/补码方式"
  43. cipher.init(Cipher.DECRYPT_MODE, skeySpec);
  44. byte[] decBytes = cipher.doFinal(outBytes);
  45. rs=HexUtil.bytesToHex(decBytes);
  46. } catch (Exception e) {
  47. log.error("解密异常",e);
  48. log.error("输入参数为hexStr:{},hexKey:{}",hexStr,hexKey);
  49. }
  50. return rs;
  51. }
  52.  
  53. }
  1. public class HexUtil {
  2.  
  3. /**
  4. * 将普通字符串用16进制描述
  5. * 如"WAZX-B55SY6-S6DT5" 描述为:"57415a582d4235355359362d5336445435"
  6. * */
  7. public static String strToHex(String str){
  8. byte[] bytes = str.getBytes();
  9. return bytesToHex(bytes);
  10. }
  11.  
  12. /**将16进制描述的字符串还原为普通字符串
  13. * 如"57415a582d4235355359362d5336445435" 还原为:"WAZX-B55SY6-S6DT5"
  14. * */
  15. public static String hexToStr(String hex){
  16. byte[] bytes=hexToBytes(hex);
  17. return new String(bytes);
  18. }
  19.  
  20. /**16进制转byte[]*/
  21. public static byte[] hexToBytes(String hex){
  22. int length = hex.length() / 2;
  23. byte[] bytes=new byte[length];
  24. for(int i=0;i<length;i++){
  25. String tempStr=hex.substring(2*i, 2*i+2);//byte:8bit=4bit+4bit=十六进制位+十六进制位
  26. bytes[i]=(byte) Integer.parseInt(tempStr, 16);
  27. }
  28. return bytes;
  29. }
  30.  
  31. /**byte[]转16进制*/
  32. public static String bytesToHex(byte[] bytes){
  33. StringBuilder sb=new StringBuilder();
  34. for(int i=0;i<bytes.length;i++){
  35. int tempI=bytes[i] & 0xFF;//byte:8bit,int:32bit;高位相与.
  36. String str = Integer.toHexString(tempI);
  37. if(str.length()<2){
  38. sb.append(0).append(str);//长度不足两位,补齐:如16进制的d,用0d表示。
  39. }else{
  40. sb.append(str);
  41. }
  42. }
  43. return sb.toString();
  44. }
  45.  
  46. }
  1. public class AESTest {
  2.  
  3. private static String key="2b7e151628aed2a6abf7158809cf4f3c";
  4.  
  5. @Test
  6. public void test_all(){
  7. String enOri="000000000000000WAZX-B55SY6-S6DT5";
  8. String enHex=HexUtil.strToHex(enOri);
  9. String enRS=AESCoder.ecbEnc(enHex,key);
  10. System.out.println("加密结果为:"+enRS);
  11.  
  12. String deHex="7312560ccb30ad9b445ee94b426c8a2bdf75d11ded50f053568ec08bf3f9be04";
  13. String deRS=AESCoder.ecbDec(deHex,key);
  14. String deOri=HexUtil.hexToStr(deRS);
  15. System.out.println("解密结果为:"+deOri);
  16. }
  17.  
  18. @Test
  19. public void test_enc(){
  20. String enStr ="6bc1bee22e409f96e93d7e117393172a";
  21. String enRS=AESCoder.ecbEnc(enStr,key);
  22. System.out.println(enRS);
  23. }
  24.  
  25. @Test
  26. public void test_dec(){
  27. String deStr ="3ad77bb40d7a3660a89ecaf32466ef97";
  28. String enRS=AESCoder.ecbDec(deStr,key);
  29. System.out.println(enRS);
  30.  
  31. }
  32.  
  33. /**
  34. * 和后台联调时使用
  35. * 该函数用于讲16进制数组转成String
  36. * 如密钥key为
  37. * uint8_t key[] =
  38. * {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
  39. * 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}
  40. * 则格式化之后为"2b7e151628aed2a6abf7158809cf4f3c"
  41. * */
  42. public static String convertStr(String hexStr) {
  43. String[] kStrs = hexStr.split(",");
  44. String[] keyStrs = new String[kStrs.length];
  45. for (int i = 0; i < kStrs.length; i++) {
  46. String str = kStrs[i].trim().substring(2);
  47. keyStrs[i] = str;
  48. }
  49. StringBuffer sb = new StringBuffer();
  50. for (String str : keyStrs) {
  51. sb.append(str);
  52. }
  53. return sb.toString().toUpperCase();
  54. }
  55.  
  56. }

AESTest运行结果:

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

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

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

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

  1. import java.security.SecureRandom;
  2.  
  3. import javax.crypto.Cipher;
  4. import javax.crypto.KeyGenerator;
  5. import javax.crypto.spec.SecretKeySpec;
  6.  
  7. public class AESHelper {
  8.  
  9. public static String encrypt(String content, String pwd,String charSet) {
  10. try {
  11. byte[] byteContent = content.getBytes(charSet);
  12.  
  13. KeyGenerator kgen = KeyGenerator.getInstance("AES");
  14. kgen.init(128, new SecureRandom(pwd.getBytes()));
  15.  
  16. Cipher cipher = Cipher.getInstance("AES");
  17. cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));
  18.  
  19. byte[] buf = cipher.doFinal(byteContent);
  20.  
  21. //byte[]转16进制
  22. StringBuffer sb = new StringBuffer();
  23. for (int i = 0; i < buf.length; i++) {
  24. String hex = Integer.toHexString(buf[i] & 0xFF);
  25. if (hex.length() == 1) {
  26. hex = '0' + hex;
  27. }
  28. sb.append(hex.toUpperCase());
  29. }
  30. return sb.toString();
  31.  
  32. } catch (Exception e) {
  33. e.printStackTrace();
  34. }
  35. return null;
  36. }
  37.  
  38. /***
  39. *
  40. * @param content 16进制的字符串
  41. * @param pwd
  42. * @param charSet
  43. * @return
  44. */
  45. public static String decrypt(String content, String pwd,String charSet) {
  46. try {
  47. byte[] byteContent = new byte[content.length() / 2];
  48. if (content.length() < 1){
  49. return null;
  50. }
  51. //将16进制转换为二进制
  52. for (int i = 0; i < content.length() / 2; i++) {
  53. int high = Integer.parseInt(content.substring(i * 2, i * 2 + 1), 16);
  54. int low = Integer.parseInt(content.substring(i * 2 + 1, i * 2 + 2), 16);
  55. byteContent[i] = (byte) (high * 16 + low);
  56. }
  57.  
  58. KeyGenerator kgen = KeyGenerator.getInstance("AES");
  59. kgen.init(128, new SecureRandom(pwd.getBytes()));
  60.  
  61. Cipher cipher = Cipher.getInstance("AES");
  62. cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));
  63.  
  64. byte[] buf = cipher.doFinal(byteContent);
  65. return new String(buf,charSet);
  66.  
  67. } catch (Exception e) {
  68. e.printStackTrace();
  69. }
  70. return null;
  71. }
  72.  
  73. public static void main(String[] args) {
  74. String layer = AESHelper.encrypt("编程ABCDefgh~!@#$%^&*()|'?>.<;", "123","utf-8");
  75. System.out.println(layer);
  76. String plain = AESHelper.decrypt(layer,"123","utf-8");
  77. System.out.println(plain);
  78. }
  79.  
  80. }

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

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

最终写法:

  1. import java.security.Key;
  2. import java.security.SecureRandom;
  3.  
  4. import javax.crypto.Cipher;
  5. import javax.crypto.KeyGenerator;
  6.  
  7. public class AESHelper {
  8.  
  9. public static String encrypt(String content) {
  10. return encrypt(content, null, "utf-8");
  11. }
  12.  
  13. /***
  14. * 加密
  15. *
  16. * @param plain
  17. * @param keySeed
  18. * @param charSet
  19. * @return 输出密文 16进制
  20. */
  21. public static String encrypt(String plain, String keySeed, String charSet) {
  22. try {
  23. byte[] byteContent = plain.getBytes(charSet);
  24. Cipher cipher = Cipher.getInstance("AES");
  25. cipher.init(Cipher.ENCRYPT_MODE, getKey(keySeed));
  26.  
  27. byte[] buf = cipher.doFinal(byteContent);
  28.  
  29. // byte[]转16进制
  30. StringBuffer sb = new StringBuffer();
  31. for (int i = 0; i < buf.length; i++) {
  32. String hex = Integer.toHexString(buf[i] & 0xFF);
  33. if (hex.length() == 1) {
  34. hex = '0' + hex;
  35. }
  36. sb.append(hex.toUpperCase());
  37. }
  38. return sb.toString();
  39.  
  40. } catch (Exception e) {
  41. e.printStackTrace();
  42. }
  43. return null;
  44. }
  45.  
  46. public static String decrypt(String content) {
  47. return decrypt(content, null, "utf-8");
  48. }
  49.  
  50. /***
  51. * 解密 输入16进制的字符串
  52. *
  53. * @param layer
  54. * @param keySeed
  55. * @param charSet
  56. * @return 原文
  57. */
  58. public static String decrypt(String layer, String keySeed, String charSet) {
  59. try {
  60. byte[] byteContent = new byte[layer.length() / 2];
  61. if (layer.length() < 1) {
  62. return null;
  63. }
  64. // 将16进制转换为二进制
  65. for (int i = 0; i < layer.length() / 2; i++) {
  66. int high = Integer.parseInt(layer.substring(i * 2, i * 2 + 1), 16);
  67. int low = Integer.parseInt(layer.substring(i * 2 + 1, i * 2 + 2), 16);
  68. byteContent[i] = (byte) (high * 16 + low);
  69. }
  70.  
  71. Cipher cipher = Cipher.getInstance("AES");
  72. cipher.init(Cipher.DECRYPT_MODE, getKey(keySeed));
  73.  
  74. byte[] buf = cipher.doFinal(byteContent);
  75. return new String(buf, charSet);
  76.  
  77. } catch (Exception e) {
  78. e.printStackTrace();
  79. }
  80. return null;
  81. }
  82.  
  83. public static Key getKey(String keySeed) {
  84. if (keySeed == null) {
  85. keySeed = System.getenv("AES_SYS_KEY");
  86. }
  87. if (keySeed == null) {
  88. keySeed = System.getProperty("AES_SYS_KEY");
  89. }
  90. if (keySeed == null || keySeed.trim().length() == 0) {
  91. keySeed = "abcd1234!@#$";// 默认种子
  92. }
  93. try {
  94. SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
  95. secureRandom.setSeed(keySeed.getBytes());
  96. KeyGenerator generator = KeyGenerator.getInstance("AES");
  97. generator.init(secureRandom);
  98. return generator.generateKey();
  99. } catch (Exception e) {
  100. throw new RuntimeException(e);
  101. }
  102. }
  103.  
  104. public static void main(String[] args) {
  105. if(null==args||args.length==0){
  106. args=new String[1];
  107. args[0]="编程ABCDefgh~!@#$%^&*()|'?>.<;1234567823401";
  108. }
  109. String layer = AESHelper.encrypt(args[0]);
  110. System.out.println("密文:"+layer);
  111. String plain = AESHelper.decrypt(layer);
  112. System.out.println("原文:"+plain);
  113. }
  114.  
  115. }

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. yii 初步安装

    第一步: window下点击>开始 >运行CMD命令. 第二步:进入Yiic文件的目录   (例如在D盘里面 D:/yii/framework) 第三步:D:\yii\framework& ...

  2. 【转】JavaScript获取节点类型、节点名称和节点值

    DOM节点信息包括节点类型(nodeType).节点名称(nodeName)和节点值(nodeValue). 节点类型 DOM节点中,每个节点都拥有不同的类型.W3C规范中常用的 DOM节点类型有以下 ...

  3. jquery+ajax跨域请求webservice

    最近几天在学习webservice...在学习的时候便想到用ajax的方式去请求webservice.. 一直在测试..如果这个被请求的webservice和自己使用的是同一个端口号.则不用考虑那aj ...

  4. GitLab服务器搭建及配置

    一.服务器环境 操作系统:CentOS release 6.5 (Final) GitLab版本: GitLab-shell:2.0.1 Ruby version: ruby 2.1.2p95 (20 ...

  5. URL Scheme APP跳转safari以及跳回APP

    上图 : 在plist文件里面设置. URL identifier 一般为反域名+项目名称 (尽可能保证少重复) URL Schemes是一个数组.一个APP可以添加多个.该参数为跳转时使用的标识. ...

  6. java_SE(Day15)_集合1

    一.集合类概述: 1.为什么出现集合类? 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,Java就提供了集合类. 2.数组和集合类同是容器,有何不同? 数组虽然也可以存储对象 ...

  7. 简谈ashx

    是一般处理程序, 是asp.net web 组件的一种,ashx是其扩展名. 实现IHttpHandler接口,接收并处理http请求.这个接口有一个IsReusable成员,一个待实现的方法Proc ...

  8. ADB命令详解

    一.adb介绍 ADB的全称为Android Debug Bridge,字面意思就是安卓调试桥接,简单点说,它是Android系统提供的一套工具,通过它,我们可以在电脑上建立一个连接到手机的通道,然后 ...

  9. js中十进制数转换为16进制

    使用 Number类的 toString()方法: var num = 255; console.log(num.toString(16));//输出FF

  10. firefox兼容性问题

    //innertext 火狐不同版本不兼容 document.getElementById("user-content").textContent=content; 博主使用的是最 ...