Java 对称加密
最近在做一个用户 token 功能,学习了加密相关 AES/DES、RSA 等。其中涉及一个对称和非对称加密问题。对称加密虽然没有非对称加密那样安全性高,但好处是加密速度快,但某些场合还是可以选择使用的,例如当下的用户认知机制,它是基于 token 无状态的,每次请求过来都会认证一次,这样就必须要比较高速度的加密解密运算,于是我们选择了 AES 加密方式。
下面是对称加密的工具类,完全可以不依赖其他三方 jar 包。不过有个 base64 方法我封装起来了(下面会补充)。
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom; import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey; import com.ajaxjs.util.Encode; /**
* 对称算法
* @author admin
*
*/
public class SymmetricCipher {
public SymmetricCipher() {}
public SymmetricCipher(String ALGORITHM, int keySize) {
this.ALGORITHM = ALGORITHM;
this.keySize = keySize;
}
/**
* DES = 56 | AES = 128
*/
private int keySize = 128; /**
* 加密算法,可以 DES | AES
*/
private String ALGORITHM = "AES"; /**
* 加密
*
* @param str
* 要加密的内容
* @param key
* 密钥
* @return 加密后的内容
*/
public String encrypt(String str, String key) {
// 这里要设置为utf-8不然内容中如果有中文和英文混合中文就会解密为乱码
return doCipher(true, key, str, str.getBytes(StandardCharsets.UTF_8));
} /**
* 解密
*
* @param str
* 要解密的内容
* @param key
* 密钥
* @return 解密后的内容
*/
public String decrypt(String str, String key) {
return doCipher(false, key, str, Encode.base64DecodeAsByte(str));
} private String doCipher(boolean isENCRYPT_MODE, String key, String str, byte[] bytes) {
Cipher cipher = null; try {
cipher = Cipher.getInstance(ALGORITHM);
cipher.init(isENCRYPT_MODE ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, generateKey(key));
} catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException e) {
e.printStackTrace();
return null;
} byte[] buf;
try {
// 为了防止解密时报javax.crypto.IllegalBlockSizeException: Input length must
// be multiple of 8 when decrypting with padded cipher异常,
// 不能把加密后的字节数组直接转换成字符串
buf = cipher.doFinal(bytes);
} catch (IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
return null;
} return isENCRYPT_MODE ? Encode.base64Encode(buf) : Encode.byte2String(buf);
} /**
* 获得密钥对象
*
* @param key
* 密钥
* @return 密钥对象
*/
private SecretKey generateKey(String key) {
SecureRandom secureRandom;
KeyGenerator kg; try {
secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(key.getBytes());
kg = KeyGenerator.getInstance(ALGORITHM);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
} kg.init(keySize, secureRandom);
return kg.generateKey();// 生成密钥
} final static SymmetricCipher AES = new SymmetricCipher();
final static SymmetricCipher DES = new SymmetricCipher("DES", 56); /**
* AES 加密
*
* @param str
* 要加密的内容
* @param key
* 密钥
* @return 加密后的内容
*/
public static String AES_Encrypt(String str, String key) {
return AES.encrypt(str, key);
} /**
* AES 解密
* @param str
* @param key
* @return
*/
public static String AES_Decrypt(String str, String key) {
return AES.decrypt(str, key);
}
}
使用方法如下
import org.junit.Test;
import static org.junit.Assert.*; import com.ajaxjs.user.password.SymmetricCipher; public class TestPassword {
String input = "cy11Xlbrmzyh:604:301:1353064296";
String key = "37d5aed075525d4fa0fe635231cba447"; @Test
public void testEncryption() {
String EncryptedPassword = SymmetricCipher.AES_Encrypt(input, key);
// System.out.println("EncryptedPassword::" +EncryptedPassword); assertEquals(input, SymmetricCipher.AES_Decrypt(EncryptedPassword, key));
}
}
Base64 编码解码方法
package com.ajaxjs.util; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder; /**
* 字符串的编码、解密
* @author admin
*
*/
public class Encode {
/**
* 字节转编码为 字符串( UTF-8 编码)
*
* @param bytes
* 输入的字节数组
* @return 字符串
*/
public static String byte2String(byte[] bytes) {
return new String(bytes, StandardCharsets.UTF_8);
} /**
* 字符串转为 UTF-8 编码的字符串
*
* @param str
* 输入的字符串
* @return UTF-8 字符串
*/
public static String byte2String(String str) {
return byte2String(str.getBytes());
} /**
* 将 URL 编码的字符还原,默认 UTF-8 编码
*
* @param str
* 已 URL 编码的字符串
* @return 正常的 Java 字符串
*/
public static String urlDecode(String str) {
try {
return URLDecoder.decode(str, StandardCharsets.UTF_8.toString());
} catch (UnsupportedEncodingException e) {
return null;
}
} /**
* 将字符进行 URL 编码,默认 UTF-8 编码
*
* @param str
* 正常的 Java 字符串
*
* @return 已 URL 编码的字符串
*/
public static String urlEncode(String str) {
try {
return URLEncoder.encode(str, StandardCharsets.UTF_8.toString());
} catch (UnsupportedEncodingException e) {
return null;
}
} /**
* url 网址中文乱码处理。
* 如果 Tomcat 过滤器设置了 utf-8 那么这里就不用重复转码了
*
* @param str
* 通常是 url Query String 参数
* @return 中文
*/
public static String urlChinese(String str) {
return byte2String(str.getBytes(StandardCharsets.ISO_8859_1));
} /**
* BASE64 编码
* @param bytes输入的字节数组
* @return 已编码的字符串
*/
public static String base64Encode(byte[] bytes) {
return new BASE64Encoder().encode(bytes);
} /**
* BASE64 编码
*
* @param str
* 待编码的字符串
* @return 已编码的字符串
*/
public static String base64Encode(String str) {
return base64Encode(str.getBytes());
} public static byte[] base64DecodeAsByte(String str) {
BASE64Decoder decoder = new BASE64Decoder(); try {
return decoder.decodeBuffer(str);
} catch (IOException e) {
e.printStackTrace();
return null;
}
} /**
* BASE64 解码 这里需要强制捕获异常。
* 中文乱码:http://s.yanghao.org/program/viewdetail.php?i=54806
*
* @param str
* 已解码的字符串
* @return 已解码的字符串
*/
public static String base64Decode(String str) {
return byte2String(base64DecodeAsByte(str));
}
}
Java 对称加密的更多相关文章
- java对称加密(AES)
java对称加密(AES) 博客分类: Java javaAES对称加密 /** * AESHelper.java * cn.com.songjy.test * * Function: TODO * ...
- PHP、Java对称加密中的AES加密方法
PHP AES加密 <?php ini_set('default_charset','utf-8'); class AES{ public $iv = null; public $key = n ...
- AES —— JAVA中对称加密和解密
package demo.security; import java.io.IOException; import java.io.UnsupportedEncodingException; impo ...
- Java和.NET使用DES对称加密的区别
Java和.NET的系统类库里都有封装DES对称加密的实现方式,但是对外暴露的接口却各不相同,甚至有时会让自己难以解决其中的问题,比如Java加密后的结果在.NET中解密不出来等,由于最近项目有跨Ja ...
- Java安全之对称加密、非对称加密、数字签名
原文地址: http://blog.csdn.net/furongkang/article/details/6882039 Java中加密分为两种方式一个是对称加密,另一个是非对称加密.对称加密是因为 ...
- 对称加密详解,以及JAVA简单实现
(原) 常用的加密有3种 1.正向加密,如MD5,加密后密文固定,目前还没办法破解,但是可以能过数据库撞库有一定概率找到,不过现在一般用这种方式加密都会加上盐值. 2.对称加密,通过一个固定的对称密钥 ...
- Java加密与解密笔记(二) 对称加密
前面的仅仅是做了编码或者摘要,下面看看真正的加密技术. DES public class DESUtil { static final String ALGORITHM = "DES&quo ...
- java的AES对称加密和解密,有偏移量
import java.math.BigDecimal; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; i ...
- java中的数据加密2 对称加密
对称加密 也叫私钥加密. 采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密. 需要对加密和解密使用相同密钥的加密算法.由于其速度快,对 ...
随机推荐
- SSO 单点登录的实现原理
单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任.单点登录在大型网站里使用得 ...
- FIFO设计验证经验谈
概述: FIFO是电路设计中非常重要的一个基本电路.一般的超大规模集成电路中,都会用到FIFO.所以,FIFO是每个SOC设计和验证工程师必须掌握的一种核心电路. FIFO电路又分为异步FIFO和同步 ...
- AMBA总线基础知识简介
AMBA:Advanced Microcontroller Bus Architecture,是ARMA公司的片内互联总线协议. 1995 - AMBA1.0 APB外设总线及ASB系统总线发布. 1 ...
- jdbc封装代码
jdbc封装代码 package jdbcUtil; import java.sql.Connection; import java.sql.DriverManager; import java.sq ...
- MySQL详解--锁,事务(转)
锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是所有数 ...
- Search in Rotated Sorted Array, 查找反转有序序列。利用二分查找的思想。反转序列。
问题描述:一个有序序列经过反转,得到一个新的序列,查找新序列的某个元素.12345->45123. 算法思想:利用二分查找的思想,都是把要找的目标元素限制在一个小范围的有序序列中.这个题和二分查 ...
- LinkedBlockingQueue 与ConcurrentLinkedQueue队列的不同与同
LinkedBlockingQueue 的API中,从队列中获取元素,有以下几个方法: 1.take():原文:Retrieves and removes the head of this queue ...
- BZOJ 1835 [ZJOI2010]base 基站选址:线段树优化dp
传送门 题意 有 $ n $ 个村庄在一排直线上,现在要建造不超过 $ K $ 个通讯基站,基站只能造在村庄处. 第 $ i $ 个村庄距离第 $ 1 $ 个村庄的距离为 $ D_i $ .在此建造基 ...
- java reflect反射---Java高级开发必须懂的
理解反射对学习Java框架有很大的帮助,如Spring框架的核心就是使用Java反射实现的,而且对做一些Java底层的操作会很有帮助. 一.Class类的使用 1.万事万物皆对象,( ...
- centos下使用fdisk扩展分区容量大小
硬盘空间为20G,VMware增加磁盘大小,需要再增加10G空间 扩展完后,重启系统,再次使用fdisk -l查看,会发现硬盘空间变大了: 重新创建分区,调整分区信息 本次实验主要对/dev/sda4 ...