Java使用Cipher类实现加密的过程详解

一、先看一个简单加密,解密实现

1.1 加密

/**
 * content: 加密内容
 * slatKey: 加密的盐,16位字符串
 * vectorKey: 加密的向量,16位字符串
 */
public String encrypt(String content, String slatKey, String vectorKey) throws Exception {
 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
 SecretKey secretKey = new SecretKeySpec(slatKey.getBytes(), "AES");
 IvParameterSpec iv = new IvParameterSpec(vectorKey.getBytes());
 cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
 byte[] encrypted = cipher.doFinal(content.getBytes());
 return Base64.encodeBase64String(encrypted);
}

1.2 解密

/**
 * content: 解密内容(base64编码格式)
 * slatKey: 加密时使用的盐,16位字符串
 * vectorKey: 加密时使用的向量,16位字符串
 */
public String decrypt(String base64Content, String slatKey, String vectorKey) throws Exception {
 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
 SecretKey secretKey = new SecretKeySpec(slatKey.getBytes(), "AES");
 IvParameterSpec iv = new IvParameterSpec(vectorKey.getBytes());
 cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
 byte[] content = Base64.decodeBase64(base64Content);
 byte[] encrypted = cipher.doFinal(content);
 return new String(encrypted);
}

1.3 代码解释

上面简单实现了AES("AES/CBC/PKCS5Padding")的加密和解密。可以看到代码中主要的是cipher对象,并有以下调用

(1)新建Cipher对象时需要传入一个参数"AES/CBC/PKCS5Padding"
(2)cipher对象使用之前还需要初始化,共三个参数("加密模式或者解密模式","密匙","向量")
(3)调用数据转换:cipher.doFinal(content),其中content是一个byte数组

实际上Cipher类实现了多种加密算法,在创建Cipher对象时,传入不同的参数就可以进行不同的加密算法。而这些算法不同的地方只是创建密匙的方法不同而已。

如传入“AES/CBC/NoPadding”可进行AES加密,传入"DESede/CBC/NoPadding"可进行DES3加密。具体的后面会介绍到。

要参考Java自带的加密算法,可以参考JDK文档的附录:https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html

二、Java的Cipher类

2.1 Cipher类提供了加密和解密的功能。

该项目使用Cipher类完成aes,des,des3和rsa加密.

获取Cipher类的对象:Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); 参数按"算法/模式/填充模式",有以下的参数

* AES/CBC/NoPadding (128)
* AES/CBC/PKCS5Padding (128)
* AES/ECB/NoPadding (128)
* AES/ECB/PKCS5Padding (128)
* DES/CBC/NoPadding (56)
* DES/CBC/PKCS5Padding (56)
* DES/ECB/NoPadding (56)
* DES/ECB/PKCS5Padding (56)
* DESede/CBC/NoPadding (168)
* DESede/CBC/PKCS5Padding (168)
* DESede/ECB/NoPadding (168)
* DESede/ECB/PKCS5Padding (168)
* RSA/ECB/PKCS1Padding (1024, 2048)
* RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)
* RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)

(1)加密算法有:AES,DES,DESede(DES3)和RSA 四种
(2) 模式有CBC(有向量模式)和ECB(无向量模式),向量模式可以简单理解为偏移量,使用CBC模式需要定义一个IvParameterSpec对象
(3) 填充模式:
* NoPadding: 加密内容不足8位用0补足8位, Cipher类不提供补位功能,需自己实现代码给加密内容添加0, 如{65,65,65,0,0,0,0,0}
* PKCS5Padding: 加密内容不足8位用余位数补足8位, 如{65,65,65,5,5,5,5,5}或{97,97,97,97,97,97,2,2}; 刚好8位补8位8

2.2 Cipher对象需要初始化

init(int opmode, Key key, AlgorithmParameterSpec params)
(1)opmode :Cipher.ENCRYPT_MODE(加密模式)和 Cipher.DECRYPT_MODE(解密模式)
(2)key :密匙,使用传入的盐构造出一个密匙,可以使用SecretKeySpec、KeyGenerator和KeyPairGenerator创建密匙,其中
* SecretKeySpec和KeyGenerator支持AES,DES,DESede三种加密算法创建密匙
* KeyPairGenerator支持RSA加密算法创建密匙
(3)params :使用CBC模式时必须传入该参数,该项目使用IvParameterSpec创建iv 对象

2.3 加密或解密

byte[] b = cipher.doFinal(content);
返回结果为byte数组,如果直接使用 new String(b) 封装成字符串,则会出现乱码

三、创建密匙

  创建密匙主要使用SecretKeySpec、KeyGenerator和KeyPairGenerator三个类来创建密匙。

3.1 SecretKeySpec类

SecretKeySpec类支持创建密匙的加密算法(ASE,DES,DES3)

SecretKey secretKey = new SecretKeySpec(slatKey.getBytes(), "AES");

但需要主要的是不同的加密算法的byte数组的长度是不同的,创建密匙前最好先检测下byte数组的长度。各加密算法的密匙长度如下

加密算法 密匙长度 向量长度
AES 16 16
DES 8 8
DES3 24 8

3.2KeyGenerator类

KeyGenerator类支持创建密匙的加密算法(ASE,DES,DES3)

/**
 * 获取加密的密匙,传入的slatKey可以是任意长度的,作为SecureRandom的随机种子,
 * 而在KeyGenerator初始化时设置密匙的长度128bit(16位byte)
 */
 private static Key getSlatKey(String slatKey) throws Exception {
 KeyGenerator kgen = KeyGenerator.getInstance("AES");
 SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
 random.setSeed(slatKey.getBytes());
 kgen.init(128, random);
 Key key = kgen.generateKey();
 return key;
 }

KeyGenerator对象在初始化需要传入一个随机源。一般使用的都是SecureRandom类来创建随机源,此时传入的盐只作为SecureRandom类的随机种子,种子相同,产生的随机数也相同;盐的长度不再受限制了,但KeyGenerator对象则必须指定长度。

3.3KeyPairGenerator类

RSA加密算法使用的密匙是包含公匙和私匙两种,一般情况下,有使用公匙加密,则用私匙解密;使用私匙加密,则使用公匙解密。可以使用KeyPairGenerator类来创建RSA加密算法的密匙

KeyPairGenerator类支持创建密匙的加密算法(RSA)

/**
 * 根据slatKey获取公匙,传入的slatKey作为SecureRandom的随机种子
 * 若使用new SecureRandom()创建公匙,则需要记录下私匙,解密时使用
 */
 private static byte[] getPublicKey(String slatKey) throws Exception {
 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
 SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
 random.setSeed(slatKey.getBytes());
 keyPairGenerator.initialize(1024, random);//or 2048
 KeyPair keyPair = keyPairGenerator.generateKeyPair();
 return keyPair.getPublic().getEncoded();
 }

 /**
 * 根据slatKey获取私匙,传入的slatKey作为SecureRandom的随机种子
 */
 private static byte[] getPrivateKey(String slatKey) throws Exception {
 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
 SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
 random.setSeed(slatKey.getBytes());
 keyPairGenerator.initialize(1024, random);// or 2048
 KeyPair keyPair = keyPairGenerator.generateKeyPair();
 return keyPair.getPrivate().getEncoded();
 }

同上,传入的盐只作为SecureRandom类的随机种子,盐相同,产生的keyPair的公匙和私匙也是同一对。
也可以不设置SecureRandom类的随机种子,直接使用new SecureRandom()创建一个新对象,此时就必须记录下公匙和私匙,在解密时使用。

四、对加密结果进行一层包装

4.1 针对1.3返回结果返回字符串乱码的问题,一般对byte数组进行处理

有两种处理方式:转换为base64的字符串或转换为16进制的字符串

4.2 转换为base64

使用apache下的Base64类进行封装即可,Base64.encodeBase64String(result); 结果形如 qPba5V+b0Ox3Um...
jar包下载:https://mvnrepository.com/artifact/commons-codec/commons-codec

4.3 转换为16进制

编码实现,即编码实现将2进制转换为16进制

/**
 * 16进制工具类
 */
public class HexUtil {
 private static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

 /**
 * 十六进制转化为二进制
 */
 public static byte[] hexStrToByteArray(String hexString) {
 if (hexString == null) {
 return null;
 }
 if (hexString.length() == 0) {
 return new byte[0];
 }
 byte[] byteArray = new byte[hexString.length() / 2];
 for (int i = 0; i < byteArray.length; i++) {
 String subStr = hexString.substring(2 * i, 2 * i + 2);
 byteArray[i] = ((byte) Integer.parseInt(subStr, 16));
 }
 return byteArray;
 }

 /**
 * 二进制转化为十六进制
 */
 public static String byteArrayToHexStr(byte[] byteArray) {
 if (byteArray == null) {
 return null;
 }
 char[] hexChars = new char[byteArray.length * 2];
 for (int j = 0; j < byteArray.length; j++) {
 int v = byteArray[j] & 0xFF;
 hexChars[j * 2] = HEX_CHARS[v >>> 4];
 hexChars[j * 2 + 1] = HEX_CHARS[v & 0x0F];
 }
 return new String(hexChars);
 }
}

结果形如 04A2784A45234B.....

五、Java加密的代码

代码我上传到github上了,欢迎下载~~

https://github.com/caizhaokai/Java_Cipher_Encrypt

到此这篇关于Java使用Cipher类实现加密的过程详解的文章就介绍到这了,更多相关Java使用Cipher类加密内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Cipher 在 NTFS 卷上显示或改变文件的加密

    Cipher 在 NTFS 卷上显示或改变文件的加密.如果在不含带参数的情况下使用,则 cipher 将显示当前文件夹及其所含文件的加密状态. 语法 cipher [{/e|/d}] [/s:dir] [/a] [/i] [/f] [/q] [/h] [/k] [/u[/n]] [PathName [...]] | [/r:PathNameWithoutExtension] | [/w:PathName] 参数 /e  加密指定的文件夹.文件夹做过标记后,使得以后添加到该文件夹的文件也被加密. 

  • 详解Android数据存储之SQLCipher数据库加密

    前言: 最近研究了Android Sqlite数据库以及ContentProvider程序间数据共享,我们清晰的知道Sqlite数据库默认存放位置data/data/pakage/database目录下,对于已经ROOT的手机来说的没有任何安全性可以,一旦被利用将会导致数据库数据的泄漏,所以我们该如何避免这种事情的发生呢?我们尝试这对数据库进行加密. 选择加密方案: 1.)第一种方案 我们可以对数据的数据库名,表名,列名就行md5,对存储的数据进行加密,例如进行aes加密(Android数据加密

  • 详解ios中的SQL数据库文件加密 (使用sqlcipher)

    今天本想写一片 GAE+goAgent+SwitchySharp 的指南的!但是突然翻出了前段时间写的关于iOS中的SQL数据库文件加密的代码,于是乎决定今天就先讲讲这个!- 那么goAgent将放在周末,后续的文章中除了文件加密,还有传输数据加密,感兴趣的童鞋 敬请留意. 言归正传,sql的文件加密,我们首先要用到一个库,它就是大名鼎鼎的Sqlcipher,  奉上连接:http://sqlcipher.NET,在ios里 我们需要看的文档是这一篇http://sqlcipher.Net/io

  • Java使用Cipher类实现加密的过程详解

    一.先看一个简单加密,解密实现 1.1 加密 /** * content: 加密内容 * slatKey: 加密的盐,16位字符串 * vectorKey: 加密的向量,16位字符串 */ public String encrypt(String content, String slatKey, String vectorKey) throws Exception { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

  • Java语言class类用法及泛化(详解)

    这篇文章主要介绍了Java语言class类用法及泛化(详解),大家都知道Java程序在运行过程中,对所有的对象进行类型标识,也就是RTTI.这项信息记录了每个对象所属的类.虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类.Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建,具体内容介绍如下: 说白了就是: Class类也是类的一种,只是名字和class关键字高度相似.Java是大小写敏感的语言. Class类的对象内容是你创

  • Golang实现AES对称加密的过程详解

    AES加密 AES对称加密简介 AES是一个对称密码,旨在取代DES成为广泛使用的标准.是美国联邦政府采用的一种区块加密标准. AES对称加密过程 加密解密算法的输入是一个128位分组.这些分组被描述成4×4的字节方阵,这个分组被复制到数组中,并在加密和解密的每一阶段都被修改.在字节方阵中,每一格都是一个字,包含了4字节.在矩阵中字是按列排序的. 加密由N轮构成,轮数依赖于密钥长度:16字节密钥对应10轮,24字节密钥对应12轮,32字节对应14轮. AES加密模式 1.电码本模式(Electr

  • Java面试题之MD5加密的安全性详解

    目录 1.彩虹表 什么是彩虹表 2.解决方案 3.实现代码 总结 MD5 是 Message Digest Algorithm 的缩写,译为信息摘要算法,它是 Java 语言中使用很广泛的一种加密算法.MD5 可以将任意字符串,通过不可逆的字符串变换算法,生成一个唯一的 MD5 信息摘要,这个信息摘要也就是我们通常所说的 MD5 字符串.那么问题来了,MD5 加密安全吗? 这道题看似简单,其实是一道送命题,很多人尤其是一些新入门的同学会觉得,安全啊,MD5 首先是加密的字符串,其次是不可逆的,所

  • Java中BigDecimal类的add()的使用详解

    Java中的BigDecimal类的使用: 使用Java中的BigDecimal可以进行精确的计算,但是在使用BigDecimal时我们需要注意它的add()方法,使用它自身的add( )方法并不会改变它原始的值,因为初始化BigDecimal是创建一个了个对象,使用add()方法时也等于是创建了一个对象,若要保存这个对象需要再创建一个对象. 句法: public BigDecimal add(BigDecimal val); public BigDecimal add(BigDecimal v

  • Java 用Prometheus搭建实时监控系统过程详解

    上帝之火 本系列讲述的是开源实时监控告警解决方案Prometheus,这个单词很牛逼.每次我都能联想到带来上帝之火的希腊之神,普罗米修斯.而这个开源的logo也是火,个人挺喜欢这个logo的设计. 本系列着重介绍Prometheus以及如何用它和其周边的生态来搭建一套属于自己的实时监控告警平台. 本系列受众对象为初次接触Prometheus的用户,大神勿喷,偏重于操作和实战,但是重要的概念也会精炼出提及下.系列主要分为以下几块 Prometheus各个概念介绍和搭建,如何抓取数据(本次分享内容)

  • java使用xfire搭建webservice服务的过程详解

    前言 以前用的都是 apache 的cxf来搞webservice,今天做项目发现这个项目用的是 xfire,于是搭一个,写个demo用一下,在此记录一下过程. 搭建过程 本文使用的是maven形式的web工程.不知道如何搭建web工程的看上一篇博文. 引入xfire的依赖 <dependency> <groupId>org.codehaus.xfire</groupId> <artifactId>xfire-all</artifactId> &

  • java.lang.Void类的解析与使用详解

    今天在查看源码的时候发现了 java.lang.Void 的类.这个有什么作用呢? 先通过源码查看下 package java.lang; /** * The {@code Void} class is an uninstantiable placeholder class to hold a * reference to the {@code Class} object representing the Java keyword * void. * * @author unascribed *

  • 使用Java的Graphics类进行绘图的方法详解

    Graphics类提供基本绘图方法,Graphics2D类提供更强大的绘图能力.本节讲解Graphics类,下节讲解Graphics2D. Graphics类提供基本的几何图形绘制方法,主要有:画线段.画矩形.画圆.画带颜色的图形.画椭圆.画圆弧.画多边形等. 1. 画线 在窗口画一条线段,可以使用Graphics类的drawLine()方法: drawLine(int x1,int y1,int x2,int y2) 例如,以下代码在点(3,3)与点(50,50)之间画线段,在点(100,10

  • python暴力解压rar加密文件过程详解

    第一次使用csdn写文章,写得不好还请见谅.(运行环境:python3.6) 下了一个带密码的压缩包文件,作为一个刚学python的新手,想着能不能用python暴力破解它,于是在网上搜了很多资料,看着似乎并不是很麻烦,也想试着自己写一个可以暴力破解的程序,在写的过程中却遇到了各种各样的问题,希望大手们能带带我.遇到的问题如下: zipfile和zipfile2似乎都不支持AES解密(https://bugs.python.org/issue9170) 在用rarfile暴力破解时即使密码错误也

随机推荐