最近在做一个用户 token 功能,学习了加密相关 AES/DES、RSA 等。其中涉及一个对称和非对称加密问题。对称加密虽然没有非对称加密那样安全性高,但好处是加密速度快,但某些场合还是可以选择使用的,例如当下的用户认知机制,它是基于 token 无状态的,每次请求过来都会认证一次,这样就必须要比较高速度的加密解密运算,于是我们选择了 AES 加密方式。

下面是对称加密的工具类,完全可以不依赖其他三方 jar 包。不过有个 base64 方法我封装起来了(下面会补充)。

  1. import java.nio.charset.StandardCharsets;
  2. import java.security.InvalidKeyException;
  3. import java.security.NoSuchAlgorithmException;
  4. import java.security.SecureRandom;
  5.  
  6. import javax.crypto.BadPaddingException;
  7. import javax.crypto.Cipher;
  8. import javax.crypto.IllegalBlockSizeException;
  9. import javax.crypto.KeyGenerator;
  10. import javax.crypto.NoSuchPaddingException;
  11. import javax.crypto.SecretKey;
  12.  
  13. import com.ajaxjs.util.Encode;
  14.  
  15. /**
  16. * 对称算法
  17. * @author admin
  18. *
  19. */
  20. public class SymmetricCipher {
  21. public SymmetricCipher() {}
  22. public SymmetricCipher(String ALGORITHM, int keySize) {
  23. this.ALGORITHM = ALGORITHM;
  24. this.keySize = keySize;
  25. }
  26. /**
  27. * DES = 56 | AES = 128
  28. */
  29. private int keySize = 128;
  30.  
  31. /**
  32. * 加密算法,可以 DES | AES
  33. */
  34. private String ALGORITHM = "AES";
  35.  
  36. /**
  37. * 加密
  38. *
  39. * @param str
  40. * 要加密的内容
  41. * @param key
  42. * 密钥
  43. * @return 加密后的内容
  44. */
  45. public String encrypt(String str, String key) {
  46. // 这里要设置为utf-8不然内容中如果有中文和英文混合中文就会解密为乱码
  47. return doCipher(true, key, str, str.getBytes(StandardCharsets.UTF_8));
  48. }
  49.  
  50. /**
  51. * 解密
  52. *
  53. * @param str
  54. * 要解密的内容
  55. * @param key
  56. * 密钥
  57. * @return 解密后的内容
  58. */
  59. public String decrypt(String str, String key) {
  60. return doCipher(false, key, str, Encode.base64DecodeAsByte(str));
  61. }
  62.  
  63. private String doCipher(boolean isENCRYPT_MODE, String key, String str, byte[] bytes) {
  64. Cipher cipher = null;
  65.  
  66. try {
  67. cipher = Cipher.getInstance(ALGORITHM);
  68. cipher.init(isENCRYPT_MODE ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, generateKey(key));
  69. } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException e) {
  70. e.printStackTrace();
  71. return null;
  72. }
  73.  
  74. byte[] buf;
  75. try {
  76. // 为了防止解密时报javax.crypto.IllegalBlockSizeException: Input length must
  77. // be multiple of 8 when decrypting with padded cipher异常,
  78. // 不能把加密后的字节数组直接转换成字符串
  79. buf = cipher.doFinal(bytes);
  80. } catch (IllegalBlockSizeException | BadPaddingException e) {
  81. e.printStackTrace();
  82. return null;
  83. }
  84.  
  85. return isENCRYPT_MODE ? Encode.base64Encode(buf) : Encode.byte2String(buf);
  86. }
  87.  
  88. /**
  89. * 获得密钥对象
  90. *
  91. * @param key
  92. * 密钥
  93. * @return 密钥对象
  94. */
  95. private SecretKey generateKey(String key) {
  96. SecureRandom secureRandom;
  97. KeyGenerator kg;
  98.  
  99. try {
  100. secureRandom = SecureRandom.getInstance("SHA1PRNG");
  101. secureRandom.setSeed(key.getBytes());
  102. kg = KeyGenerator.getInstance(ALGORITHM);
  103. } catch (NoSuchAlgorithmException e) {
  104. e.printStackTrace();
  105. return null;
  106. }
  107.  
  108. kg.init(keySize, secureRandom);
  109. return kg.generateKey();// 生成密钥
  110. }
  111.  
  112. final static SymmetricCipher AES = new SymmetricCipher();
  113. final static SymmetricCipher DES = new SymmetricCipher("DES", 56);
  114.  
  115. /**
  116. * AES 加密
  117. *
  118. * @param str
  119. * 要加密的内容
  120. * @param key
  121. * 密钥
  122. * @return 加密后的内容
  123. */
  124. public static String AES_Encrypt(String str, String key) {
  125. return AES.encrypt(str, key);
  126. }
  127.  
  128. /**
  129. * AES 解密
  130. * @param str
  131. * @param key
  132. * @return
  133. */
  134. public static String AES_Decrypt(String str, String key) {
  135. return AES.decrypt(str, key);
  136. }
  137. }

使用方法如下

  1. import org.junit.Test;
  2. import static org.junit.Assert.*;
  3.  
  4. import com.ajaxjs.user.password.SymmetricCipher;
  5.  
  6. public class TestPassword {
  7. String input = "cy11Xlbrmzyh:604:301:1353064296";
  8. String key = "37d5aed075525d4fa0fe635231cba447";
  9.  
  10. @Test
  11. public void testEncryption() {
  12. String EncryptedPassword = SymmetricCipher.AES_Encrypt(input, key);
  13. // System.out.println("EncryptedPassword::" +EncryptedPassword);
  14.  
  15. assertEquals(input, SymmetricCipher.AES_Decrypt(EncryptedPassword, key));
  16. }
  17. }

Base64 编码解码方法

  1. package com.ajaxjs.util;
  2.  
  3. import java.io.IOException;
  4. import java.io.UnsupportedEncodingException;
  5. import java.net.URLDecoder;
  6. import java.net.URLEncoder;
  7. import java.nio.charset.StandardCharsets;
  8.  
  9. import sun.misc.BASE64Decoder;
  10. import sun.misc.BASE64Encoder;
  11.  
  12. /**
  13. * 字符串的编码、解密
  14. * @author admin
  15. *
  16. */
  17. public class Encode {
  18. /**
  19. * 字节转编码为 字符串( UTF-8 编码)
  20. *
  21. * @param bytes
  22. * 输入的字节数组
  23. * @return 字符串
  24. */
  25. public static String byte2String(byte[] bytes) {
  26. return new String(bytes, StandardCharsets.UTF_8);
  27. }
  28.  
  29. /**
  30. * 字符串转为 UTF-8 编码的字符串
  31. *
  32. * @param str
  33. * 输入的字符串
  34. * @return UTF-8 字符串
  35. */
  36. public static String byte2String(String str) {
  37. return byte2String(str.getBytes());
  38. }
  39.  
  40. /**
  41. * 将 URL 编码的字符还原,默认 UTF-8 编码
  42. *
  43. * @param str
  44. * 已 URL 编码的字符串
  45. * @return 正常的 Java 字符串
  46. */
  47. public static String urlDecode(String str) {
  48. try {
  49. return URLDecoder.decode(str, StandardCharsets.UTF_8.toString());
  50. } catch (UnsupportedEncodingException e) {
  51. return null;
  52. }
  53. }
  54.  
  55. /**
  56. * 将字符进行 URL 编码,默认 UTF-8 编码
  57. *
  58. * @param str
  59. * 正常的 Java 字符串
  60. *
  61. * @return 已 URL 编码的字符串
  62. */
  63. public static String urlEncode(String str) {
  64. try {
  65. return URLEncoder.encode(str, StandardCharsets.UTF_8.toString());
  66. } catch (UnsupportedEncodingException e) {
  67. return null;
  68. }
  69. }
  70.  
  71. /**
  72. * url 网址中文乱码处理。
  73. * 如果 Tomcat 过滤器设置了 utf-8 那么这里就不用重复转码了
  74. *
  75. * @param str
  76. * 通常是 url Query String 参数
  77. * @return 中文
  78. */
  79. public static String urlChinese(String str) {
  80. return byte2String(str.getBytes(StandardCharsets.ISO_8859_1));
  81. }
  82.  
  83. /**
  84. * BASE64 编码
  85. * @param bytes输入的字节数组
  86. * @return 已编码的字符串
  87. */
  88. public static String base64Encode(byte[] bytes) {
  89. return new BASE64Encoder().encode(bytes);
  90. }
  91.  
  92. /**
  93. * BASE64 编码
  94. *
  95. * @param str
  96. * 待编码的字符串
  97. * @return 已编码的字符串
  98. */
  99. public static String base64Encode(String str) {
  100. return base64Encode(str.getBytes());
  101. }
  102.  
  103. public static byte[] base64DecodeAsByte(String str) {
  104. BASE64Decoder decoder = new BASE64Decoder();
  105.  
  106. try {
  107. return decoder.decodeBuffer(str);
  108. } catch (IOException e) {
  109. e.printStackTrace();
  110. return null;
  111. }
  112. }
  113.  
  114. /**
  115. * BASE64 解码 这里需要强制捕获异常。
  116. * 中文乱码:http://s.yanghao.org/program/viewdetail.php?i=54806
  117. *
  118. * @param str
  119. * 已解码的字符串
  120. * @return 已解码的字符串
  121. */
  122. public static String base64Decode(String str) {
  123. return byte2String(base64DecodeAsByte(str));
  124. }
  125. }
 java学习群669823128

Java 对称加密的更多相关文章

  1. java对称加密(AES)

    java对称加密(AES) 博客分类: Java javaAES对称加密  /** * AESHelper.java * cn.com.songjy.test * * Function: TODO * ...

  2. PHP、Java对称加密中的AES加密方法

    PHP AES加密 <?php ini_set('default_charset','utf-8'); class AES{ public $iv = null; public $key = n ...

  3. AES —— JAVA中对称加密和解密

    package demo.security; import java.io.IOException; import java.io.UnsupportedEncodingException; impo ...

  4. Java和.NET使用DES对称加密的区别

    Java和.NET的系统类库里都有封装DES对称加密的实现方式,但是对外暴露的接口却各不相同,甚至有时会让自己难以解决其中的问题,比如Java加密后的结果在.NET中解密不出来等,由于最近项目有跨Ja ...

  5. Java安全之对称加密、非对称加密、数字签名

    原文地址: http://blog.csdn.net/furongkang/article/details/6882039 Java中加密分为两种方式一个是对称加密,另一个是非对称加密.对称加密是因为 ...

  6. 对称加密详解,以及JAVA简单实现

    (原) 常用的加密有3种 1.正向加密,如MD5,加密后密文固定,目前还没办法破解,但是可以能过数据库撞库有一定概率找到,不过现在一般用这种方式加密都会加上盐值. 2.对称加密,通过一个固定的对称密钥 ...

  7. Java加密与解密笔记(二) 对称加密

    前面的仅仅是做了编码或者摘要,下面看看真正的加密技术. DES public class DESUtil { static final String ALGORITHM = "DES&quo ...

  8. java的AES对称加密和解密,有偏移量

    import java.math.BigDecimal; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; i ...

  9. java中的数据加密2 对称加密

    对称加密 也叫私钥加密.   采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密. 需要对加密和解密使用相同密钥的加密算法.由于其速度快,对 ...

随机推荐

  1. LeetCode:比较含退格字符串【844】

    LeetCode:比较含退格字符串[844] 题目描述 给定 S 和 T 两个字符串,当它们分别被输入到空白的文本编辑器后,判断二者是否相等,并返回结果. # 代表退格字符. 示例 1: 输入:S = ...

  2. Kattis - fence2【二分法】

    Kattis - fence2[二分法] 题意 有一个农夫需要建造一个 N - 1 米长的篱笆,需要 N 根柱子,然后有 K 根 柱子 需要将这 K 根柱子 切成 N 段 然后 要尽量保证这 N 段柱 ...

  3. Codeforces Round #397 by Kaspersky Lab and Barcelona Bootcamp (Div. 1 + Div. 2 combined) A - Neverending competitions

    地址:http://codeforces.com/contest/765/problem/A 题目: A. Neverending competitions time limit per test 2 ...

  4. Unity,如何阻塞当前函数一段时间

    public class Example : MonoBehaviour { IEnumerator Example() { print(Time.time); ); print(Time.time) ...

  5. Python面试题之Super函数

    这是个高大上的函数,在python装13手册里面介绍过多使用可显得自己是高手 23333. 但其实他还是很重要的. 简单说, super函数是调用下一个父类(超类)并返回该父类实例的方法. 这里的下一 ...

  6. Sybase:SAP IQ学习笔记

    Sybase:SAP IQ学习笔记 -- 启动IQ管理 >> start_iq -n utility_db -n utility_db >> dbisql -c "u ...

  7. Percona-Server-5.7.16 启动错误

    基于:percona-server-5.7.16 启动报错:  [root@monitor mysql]# ./bin/mysqld_safe --defaults-file=/data/config ...

  8. java中最常用jar包的用途

    jar包用途 axis.jarSOAP引擎包commons-discovery-0.2.jar用来发现.查找和实现可插入式接口,提供一些一般类实例化.单件的生命周期管理的常用方法.jaxrpc.jar ...

  9. 记一次网卡报错ERROR,some other host already uses address

    提示IP地址冲突,但是此IP确实没有被其他Server占用 解决如下: 编辑此文件 搜索arping 将下面几行注释掉 保存退出 激活网卡 此时IP地址已生效 下面是我的系统版本 (一般应该不会出现这 ...

  10. 利用MacBookPro入侵无线网络

    目前无线网络的加密方式主要有WEP,WPA/WPA2.这是最常看到的加密方式,最近由于需要,专门去研究了一下如何入侵无线网络. 1.入侵WEP加密的无线网络 WEP加密方式现在已经很不安全了,因为只要 ...