DES算法
-
概要
-
DES是有IBM公司研制的一种对称加密算法,美国国家标准局于1977年公布把它作为非机要部门使用的数据加密标准。
- DES是一个分组加密算法,就是将明文分组进行加密,每次按顺序取明文一部分,一个典型的DES以64位为分组,加密解密用算法相同。它的密钥长度为56位,因为每组第8位是用来做奇偶校验,密钥可以是任意56位的数,保密性依赖于密钥。
-
加密步骤
-
首先生成一套加密密钥,我们提供一个64位的秘钥,然后通过等分、移位、选取、迭代形成一套16个加密密钥,分别供每一轮运算使用。
-
假设目前取到一个64位分组,我们称之为M,M经过一个初始置换IP,置换成m0,。将m0明文分为左半部分和右半部分,各32位长。
-
然后进行16轮完全相同的运算,在每一轮运算中数据与相应的秘钥结合。
-
经过16轮之后,左、右半部分合在一起经过一个末置换(数据整理),这样就完成了加密过程。
-
-
代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 1package Singleton;
2
3import javax.crypto.*;
4import javax.crypto.spec.SecretKeySpec;
5import java.security.InvalidKeyException;
6import java.security.Key;
7import java.security.NoSuchAlgorithmException;
8
9public class DESDemo {
10 public static void main(String[] args) {
11
12 /**
13 * 1.明文
14 * 2.提供原始秘钥 长度64位,8个字节
15 */
16 String clearText ="hello";
17 String originKey ="12345678";
18 try {
19 String cipherText = desEncrpt(clearText,originKey);
20 System.out.println(cipherText);
21 } catch (NoSuchPaddingException e) {
22 e.printStackTrace();
23 } catch (NoSuchAlgorithmException e) {
24 e.printStackTrace();
25 } catch (InvalidKeyException e) {
26 e.printStackTrace();
27 } catch (BadPaddingException e) {
28 e.printStackTrace();
29 } catch (IllegalBlockSizeException e) {
30 e.printStackTrace();
31 }
32 }
33
34 /**
35 * 用DES算法进行加密
36 * ciper
37 * @param clearText
38 * @param originKey
39 * 就是通过对比特为进行数学运算
40 * @return
41 */
42
43 private static String desEncrpt(String clearText, String originKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
44 //获取加密类对象
45 Cipher cipher =Cipher.getInstance("DES");
46 SecretKey key =getKey(originKey);
47 //对加密类对象进行初始化
48 //mode:加密/解密
49 //key:对原始秘钥处理之后的秘钥
50 cipher.init(Cipher.ENCRYPT_MODE,key);
51 //使用加密工具类对象对明文进行加密 变成密文
52 byte[] doFinal= cipher.doFinal(clearText.getBytes());//默认GBK进行编码
53 return new String(doFinal);//默认GBK解码 //如果之前使用了其他编码方式,传入后已之前为主。
54 }
55
56 private static SecretKey getKey(String originKey) {
57 SecretKeySpec key= new SecretKeySpec(originKey.getBytes(),"DES");
58 return key;
59 }
60}
61
62
1
2 1 * 上述代码会出现乱码问题,
2
1
2
3 1?茽%q%?
2
3
乱码出现的原因
要找的编码表就是base64。
注:GBK、UTF-8、base64这些都是编码表
-
base64编码
-
加密后的结果是字节数组,这些被加密后的字节在码表(如GBK、UTF-8码表)上找不到对应内容,会出现乱码。当乱码字符串再次转换为字节数组时,长度会变化,导致解密失败,所以转换后的数据是不安全的。
-
使用Base64对字节数组进行编码,任何字节都能映射成对应的Base64字符,之后都能恢复到字节数组,利用数据的保存与传输,所以是安全的。
-
改进后代吗
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 1import javax.crypto.*;
2import javax.crypto.spec.SecretKeySpec;
3import java.security.InvalidKeyException;
4import java.security.Key;
5import java.security.NoSuchAlgorithmException;
6
7public class DESDemo {
8 public static void main(String[] args) {
9
10 /**
11 * 1.明文
12 * 2.提供原始秘钥 长度64位,8个字节
13 */
14 String clearText ="hello";
15 String originKey ="12345678";
16 try {
17 String cipherText = desEncrpt(clearText,originKey);
18 System.out.println(cipherText);
19 } catch (NoSuchPaddingException e) {
20 e.printStackTrace();
21 } catch (NoSuchAlgorithmException e) {
22 e.printStackTrace();
23 } catch (InvalidKeyException e) {
24 e.printStackTrace();
25 } catch (BadPaddingException e) {
26 e.printStackTrace();
27 } catch (IllegalBlockSizeException e) {
28 e.printStackTrace();
29 }
30 }
31
32 /**
33 * 用DES算法进行加密
34 * ciper
35 * @param clearText
36 * @param originKey
37 * 就是通过对比特为进行数学运算
38 * @return
39 */
40
41 private static String desEncrpt(String clearText, String originKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
42 //获取加密类对象
43 Cipher cipher =Cipher.getInstance("DES");
44 SecretKey key =getKey(originKey);
45 //对加密类对象进行初始化
46 //mode:加密/解密
47 //key:对原始秘钥处理之后的秘钥
48 cipher.init(Cipher.ENCRYPT_MODE,key);
49 //使用加密工具类对象对明文进行加密 变成密文
50 byte[] doFinal= cipher.doFinal(clearText.getBytes());
51 byte[] encode =Base64.encode(doFinal);
52 return new String(encode);
53 }
54
55 private static SecretKey getKey(String originKey) {
56 SecretKeySpec key= new SecretKeySpec(originKey.getBytes(),"DES");
57 return key;
58 }
59}
60
61
-
默认规定,给出的秘钥必须要有8个字节,64位,这样程序员每次必须要提供八个字符的字符串,如果超过或者不够,要报错。现在有需求,不论originKey多长,我们都要形成一个8个字节长度的原始秘钥,不够自动填,超过自动截取。
1
2
3
4
5
6
7
8
9
10
11
12
13 1 private static SecretKey getKey(String originKey) {
2 //不够 初始值为0
3 byte[]buffer =new byte[8];
4 //获取用户提供的原始密钥字节数组
5 byte[] originBytes =originKey.getBytes();
6 for(int i=0;i<8&&i<originBytes.length;i++){
7 buffer[i]=originBytes[i];
8 }
9 SecretKeySpec key= new SecretKeySpec(buffer,"DES");
10 return key;
11 }
12
13
-
解密
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85 1import javax.crypto.*;
2import javax.crypto.spec.SecretKeySpec;
3import java.security.InvalidKeyException;
4import java.security.Key;
5import java.security.NoSuchAlgorithmException;
6
7public class DesDemo {
8 public static void main(String[] args) {
9
10 /**
11 * 1.明文
12 * 2.提供原始秘钥 长度64位,8个字节
13 */
14 String clearText ="hello";
15 String originKey ="12345678";
16 try {
17 String cipherText = desEncrpt(clearText,originKey);
18 System.out.println(cipherText);
19 String clearText2 =desDecrpt(cipherText,originKey);
20 System.out.println(clearText2);
21 } catch (NoSuchPaddingException e) {
22 e.printStackTrace();
23 } catch (NoSuchAlgorithmException e) {
24 e.printStackTrace();
25 } catch (InvalidKeyException e) {
26 e.printStackTrace();
27 } catch (BadPaddingException e) {
28 e.printStackTrace();
29 } catch (IllegalBlockSizeException e) {
30 e.printStackTrace();
31 }
32 }
33
34 private static String desDecrpt(String cipherText, String originKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
35 //获取加密类对象
36 Cipher cipher =Cipher.getInstance("DES");
37 SecretKey key =getKey(originKey);
38 //对加密类对象进行初始化
39 //mode:加密/解密
40 //key:对原始秘钥处理之后的秘钥
41 cipher.init(Cipher.DECRYPT_MODE,key);
42 byte[] decodebytes =Base64.decode(cipherText);
43 //使用加密工具类对象对明文进行解密 变成明文
44 byte[] doFinal= cipher.doFinal(decodebytes);
45 // String encodetext =Base64.encode(doFinal);
46 return new String(doFinal);
47 }
48
49 /**
50 * 用DES算法进行加密
51 * ciper
52 * @param clearText
53 * @param originKey
54 * 就是通过对比特为进行数学运算
55 * @return
56 */
57
58 private static String desEncrpt(String clearText, String originKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
59 //获取加密类对象
60 Cipher cipher =Cipher.getInstance("DES");
61 SecretKey key =getKey(originKey);
62 //对加密类对象进行初始化
63 //mode:加密/解密
64 //key:对原始秘钥处理之后的秘钥
65 cipher.init(Cipher.ENCRYPT_MODE,key);
66 //使用加密工具类对象对明文进行加密 变成密文
67 byte[] doFinal= cipher.doFinal(clearText.getBytes());
68 String encodetext =Base64.encode(doFinal);
69 return new String(encodetext);
70 }
71
72 private static SecretKey getKey(String originKey) {
73 //不够 初始值为0
74 byte[]buffer =new byte[8];
75 //获取用户提供的原始密钥字节数组
76 byte[] originBytes =originKey.getBytes();
77 for(int i=0;i<8&&i<originBytes.length;i++){
78 buffer[i]=originBytes[i];
79 }
80 SecretKeySpec key= new SecretKeySpec(buffer,"DES");
81 return key;
82 }
83}
84
85
-
思路:加密后的密文在GBK中有可能找不到,缺漏导致乱码,然后借助base64进行编码,在解密的时候,先通过base64解码,解码为GBK编码,最后结果返回。
1
2
3 1GBK->base64 ->base64->GBK
2
3