◆JAVA加密解密-DES
DES算法提供CBC, OFB, CFB, ECB四种模式,MAC是基于ECB实现的。
一、数据补位
DES数据加解密就是将数据按照8个字节一段进行DES加密或解密得到一段8个字节的密文或者明文,最后一段不足8个字节,按照需求补足8个字节(通常补00或者FF,根据实际要求不同)进行计算,之后按照顺序将计算所得的数据连在一起即可。
这里有个问题就是为什么要进行数据补位?主要原因是DES算法加解密时要求数据必须为8个字节。
二、ECB模式
DES ECB(电子密本方式)其实非常简单,就是将数据按照8个字节一段进行DES加密或解密得到一段8个字节的密文或者明文,最后一段不足8个字节,按照需求补足8个字节进行计算,之后按照顺序将计算所得的数据连在一起即可,各段数据之间互不影响。
三、CBC模式
DES CBC(密文分组链接方式)有点麻烦,它的实现机制使加密的各段数据之间有了联系。其实现的机理如下:
加密步骤如下:
1)首先将数据按照8个字节一组进行分组得到D1D2......Dn(若数据不是8的整数倍,用指定的PADDING数据补位)
2)第一组数据D1与初始化向量I异或后的结果进行DES加密得到第一组密文C1(初始化向量I为全零)
3)第二组数据D2与第一组的加密结果C1异或以后的结果进行DES加密,得到第二组密文C2
4)之后的数据以此类推,得到Cn
5)按顺序连为C1C2C3......Cn即为加密结果。
解密是加密的逆过程,步骤如下:
1)首先将数据按照8个字节一组进行分组得到C1C2C3......Cn
2)将第一组数据进行解密后与初始化向量I进行异或得到第一组明文D1(注意:一定是先解密再异或)
3)将第二组数据C2进行解密后与第一组密文数据进行异或得到第二组数据D2
4)之后依此类推,得到Dn
5)按顺序连为D1D2D3......Dn即为解密结果。
这里注意一点,解密的结果并不一定是我们原来的加密数据,可能还含有你补得位,一定要把补位去掉才是你的原来的数据。
1 **
2 * DES算法
3 */
4 public class DES {
5 /**
6 *
7 * @return DES算法密钥
8 */
9 public static byte[] generateKey() {
10 try {
11
12 // DES算法要求有一个可信任的随机数源
13 SecureRandom sr = new SecureRandom();
14
15 // 生成一个DES算法的KeyGenerator对象
16 KeyGenerator kg = KeyGenerator.getInstance("DES");
17 kg.init(sr);
18
19 // 生成密钥
20 SecretKey secretKey = kg.generateKey();
21
22 // 获取密钥数据
23 byte[] key = secretKey.getEncoded();
24
25 return key;
26 } catch (NoSuchAlgorithmException e) {
27 System.err.println("DES算法,生成密钥出错!");
28 e.printStackTrace();
29 }
30
31 return null;
32 }
33
34 /**
35 * 加密函数
36 *
37 * @param data
38 * 加密数据
39 * @param key
40 * 密钥
41 * @return 返回加密后的数据
42 */
43 public static byte[] encrypt(byte[] data, byte[] key) {
44
45 try {
46
47 // DES算法要求有一个可信任的随机数源
48 SecureRandom sr = new SecureRandom();
49
50 // 从原始密钥数据创建DESKeySpec对象
51 DESKeySpec dks = new DESKeySpec(key);
52
53 // 创建一个密匙工厂,然后用它把DESKeySpec转换成
54 // 一个SecretKey对象
55 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
56 SecretKey secretKey = keyFactory.generateSecret(dks);
57
58 // using DES in ECB mode
59 Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
60
61 // 用密匙初始化Cipher对象
62 cipher.init(Cipher.ENCRYPT_MODE, secretKey, sr);
63
64 // 执行加密操作
65 byte encryptedData[] = cipher.doFinal(data);
66
67 return encryptedData;
68 } catch (Exception e) {
69 System.err.println("DES算法,加密数据出错!");
70 e.printStackTrace();
71 }
72
73 return null;
74 }
75
76 /**
77 * 解密函数
78 *
79 * @param data
80 * 解密数据
81 * @param key
82 * 密钥
83 * @return 返回解密后的数据
84 */
85 public static byte[] decrypt(byte[] data, byte[] key) {
86 try {
87 // DES算法要求有一个可信任的随机数源
88 SecureRandom sr = new SecureRandom();
89
90 // byte rawKeyData[] = /* 用某种方法获取原始密匙数据 */;
91
92 // 从原始密匙数据创建一个DESKeySpec对象
93 DESKeySpec dks = new DESKeySpec(key);
94
95 // 创建一个密匙工厂,然后用它把DESKeySpec对象转换成
96 // 一个SecretKey对象
97 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
98 SecretKey secretKey = keyFactory.generateSecret(dks);
99
100 // using DES in ECB mode
101 Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
102
103 // 用密匙初始化Cipher对象
104 cipher.init(Cipher.DECRYPT_MODE, secretKey, sr);
105
106 // 正式执行解密操作
107 byte decryptedData[] = cipher.doFinal(data);
108
109 return decryptedData;
110 } catch (Exception e) {
111 System.err.println("DES算法,解密出错。");
112 e.printStackTrace();
113 }
114
115 return null;
116 }
117
118 /**
119 * 加密函数
120 *
121 * @param data
122 * 加密数据
123 * @param key
124 * 密钥
125 * @return 返回加密后的数据
126 */
127 public static byte[] CBCEncrypt(byte[] data, byte[] key, byte[] iv) {
128
129 try {
130 // 从原始密钥数据创建DESKeySpec对象
131 DESKeySpec dks = new DESKeySpec(key);
132
133 // 创建一个密匙工厂,然后用它把DESKeySpec转换成
134 // 一个SecretKey对象
135 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
136 SecretKey secretKey = keyFactory.generateSecret(dks);
137
138 // Cipher对象实际完成加密操作
139 Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
140 // 若采用NoPadding模式,data长度必须是8的倍数
141 // Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");
142
143 // 用密匙初始化Cipher对象
144 IvParameterSpec param = new IvParameterSpec(iv);
145 cipher.init(Cipher.ENCRYPT_MODE, secretKey, param);
146
147 // 执行加密操作
148 byte encryptedData[] = cipher.doFinal(data);
149
150 return encryptedData;
151 } catch (Exception e) {
152 System.err.println("DES算法,加密数据出错!");
153 e.printStackTrace();
154 }
155
156 return null;
157 }
158
159 /**
160 * 解密函数
161 *
162 * @param data
163 * 解密数据
164 * @param key
165 * 密钥
166 * @return 返回解密后的数据
167 */
168 public static byte[] CBCDecrypt(byte[] data, byte[] key, byte[] iv) {
169 try {
170 // 从原始密匙数据创建一个DESKeySpec对象
171 DESKeySpec dks = new DESKeySpec(key);
172
173 // 创建一个密匙工厂,然后用它把DESKeySpec对象转换成
174 // 一个SecretKey对象
175 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
176 SecretKey secretKey = keyFactory.generateSecret(dks);
177
178 // using DES in CBC mode
179 Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
180 // 若采用NoPadding模式,data长度必须是8的倍数
181 // Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");
182
183 // 用密匙初始化Cipher对象
184 IvParameterSpec param = new IvParameterSpec(iv);
185 cipher.init(Cipher.DECRYPT_MODE, secretKey, param);
186
187 // 正式执行解密操作
188 byte decryptedData[] = cipher.doFinal(data);
189
190 return decryptedData;
191 } catch (Exception e) {
192 System.err.println("DES算法,解密出错。");
193 e.printStackTrace();
194 }
195
196 return null;
197 }
198
199 public static void main(String[] args) {
200 try {
201 byte[] key = "11111111".getBytes();
202 byte[] iv = "22222222".getBytes();
203 byte[] data = DES.encrypt("ebc mode test".getBytes(), key);
204 System.out.print("EBC mode:");
205 System.out.println(new String(DES.decrypt(data, key)));
206 System.out.print("CBC mode:");
207 data = DES.CBCEncrypt("cbc mode test".getBytes(), key, iv);
208 System.out.println(new String(DES.CBCDecrypt(data, key, iv)));
209
210 } catch (Exception e) {
211 e.printStackTrace();
212 }
213 }
214 }
DES的几种填补方式
DES是对64位数据的加密算法,如数据位数不足64位的倍数,需要填充,补充到64位的倍数。
NoPadding
API或算法本身不对数据进行处理,加密数据由加密双方约定填补算法。例如若对字符串数据进行加解密,可以补充\0或者空格,然后trim
PKCS5Padding
加密前:数据字节长度对8取余,余数为m,若m>0,则补足8-m个字节,字节数值为8-m,即差几个字节就补几个字节,字节数值即为补充的字节数,若为0则补充8个字节的8
解密后:取最后一个字节,值为m,则从数据尾部删除m个字节,剩余数据即为加密前的原文
因为DES是一种block cipher,一个block要8个字节,所以要加密的东西要分成8字节的整数倍,不足的就填充。
PKCS5Padding这种填充,填的字节代表所填字节的总数:
◆JAVA加密解密-DES的更多相关文章
- JAVA加密解密DES对称加密算法
下面用DES对称加密算法(设定一个密钥,然后对所有的数据进行加密)来简单举个例子. 首先,生成一个密钥KEY. 我把它保存到key.txt中.这个文件就象是一把钥匙.谁拥有它,谁就能解开我们的类文件. ...
- Java加密解密相关
关于解释加密解密中的填充方案: http://laokaddk.blog.51cto.com/368606/461279/ 关于对称加密中的反馈模式: http://blog.csdn.net/aaa ...
- Java加密解密字符串
http://www.cnblogs.com/vwpolo/archive/2012/07/18/2597232.html Java加密解密字符串 旧文重发:http://www.blogjava ...
- Java加密解密大全
ChinaSEI系列讲义(By 郭克华) Java加密解密方法大全 如果有文字等小错,请多包涵.在不盈利的情况下,欢迎免费传播. 版权所有.郭克华 本讲义经 ...
- ◆JAVA加密解密-3DES
从数据安全谈起 当你使用网银时,是否担心你的银行卡会被盗用? 当你和朋友用QQ进行聊天时,是否担心你的隐私会被泄露? 作为开发者,编写安全的代码比编写优雅的代码更重要,因为 ...
- java加密解密的学习
注:此文章只是对如何学习java加密解密技术做一个讲解.并不涉及具体的知识介绍,如果有需要请留言,有时间我补冲长.个人觉着学习一个学习方法比学习一个知识点更有价值的多. 首先,对于加密解密知识体系没有 ...
- java加密解密
java加密解密 public class MD5Util { /** * @param args */ public static void main(String[] args) { System ...
- password学4——Java 加密解密之消息摘要算法(MD5 SHA MAC)
Java 加密解密之消息摘要算法(MD5 SHA MAC) 消息摘要 消息摘要(Message Digest)又称为数字摘要(Digital Digest). 它是一个唯一相应一个消息或文本的固定长度 ...
- java加密解密算法位运算
一.实例说明 本实例通过位运算的异或运算符 “ ^ ” 把字符串与一个指定的值进行异或运算,从而改变每个字符串中字符的值,这样就可以得到一个加密后的字符串.当把加密后的字符串作为程序输入内容,异或运算 ...
随机推荐
- .net core使用rabbitmq消息队列 (二)
之前有写过.net core集成使用rabbitmq的博文,见.net core使用rabbitmq消息队列,但是里面的使用很简单,而且还有几个bug,想改下,但是后来想了想,还是算了,之前使用的是. ...
- Ubuntu18.04升级内核后修改grub文件启动顺序
采坑:之前线上的服务器内核是4.15.0,后面有的服务跑不起来,说是要升级内核,于是就升级了,然后改了/etc/default/grub的启动顺序,改错了就启动不起来了,哈哈.后面多次尝试还是改成功了 ...
- CSS过渡、CSS动画
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <script s ...
- java 使用 ArrayList 排序【包括数字和字符串】
1.数字排序 /** * 数字排序 */ @Test public void t2() { List<Integer> list = new ArrayList<>(); li ...
- 微服务架构攀登之路(五)之Go-micro入门
一.go-micro入门 1. go-micro 简介 Go Micro 是一个插件化的基础框架,基于此可以构建微服务,Micro 的设计哲学是可插拔的插件化架构 在架构之外,它默认实现了 consu ...
- SpringBoot学习笔记五之管理员后台维护
注:图片如果损坏,点击文章链接:https://www.toutiao.com/i6803544440112677379/ 首先完成分页 引入PageHelper(之前已经添加过了) 在spring- ...
- MapReduce和Hive学习文档链接学习顺序
1.<CentOS6.5下安装Hadoop-2.7.3(图解教程)> https://www.toutiao.com/i6627365258090512909/ 2.<CentOS6 ...
- SYCOJ4972的幂次方
题目- 2的幂次方 (shiyancang.cn) 递归题 #include<bits/stdc++.h> using namespace std; int k; void f(int n ...
- 自动化集成:Pipeline整合Docker+K8S
前言:该系列文章,围绕持续集成:Jenkins+Docker+K8S相关组件,实现自动化管理源码编译.打包.镜像构建.部署等操作:本篇文章主要描述流水线集成K8S用法. 一.背景描述 分布式服务的部署 ...
- Rust 实现一个简单的区块链
一.背景 近期用 Rust 实现了 Jeiwan/blockchain_go,与原项目相比没有加入新的功能,只是换了一个编程语言实现了一遍,源码放在 Github 上. 开发这个项目,花费了好几个周末 ...