Java 安全编程:DES 加密解密

DES 加密是最常用的对称加密算法之一。

所谓“对称加密”指的就是从明文加密到密文和从密文解密到明文用的都是相同的一套密钥与之相对应的就是“非对称加密”。

其它常见的对称加密算法还有 IDEA、RC2、RC4、SKIPJACK、RC5、AES 等。

DES 加密可以给字节数组加密,也可以给文件加密。

当然在加解密之前我们需要获取密钥,获取密钥可以通过我们给定的字节数组或者生成一个随机的密钥。密钥其实就是一个 8 个长度的字节数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 生成一个随机的 DES 密钥
* @throws Exception
*/
public static Key randomKey() throws Exception{
KeyGenerator generator = KeyGenerator.getInstance("DES");
SecretKey key = generator.generateKey();
byte[] arrKey = key.getEncoded();
System.out.println(Arrays.toString(arrKey));
System.out.println("密钥 Base64 转码:" + Base64.encodeBase64String(arrKey));
System.out.println("密钥 16 进制显示:" + Hex.encodeHexString(arrKey));
return key;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 根据 byte 数组获得密钥对象
* @param arrKey
* @return
* @throws Exception
*/
public static Key getKey(byte[] arrKey) throws Exception {
// 实例化 DES 密钥材料
DESKeySpec spec = new DESKeySpec(arrKey);
// 实例化 DES 密钥工厂
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
return factory.generateSecret(spec);
}

从 DESKeySpec 类的构造函数中可以看出,只能传入一个 8 位的字节数组实例化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public DESKeySpec(byte abyte0[])
throws InvalidKeyException
{
this(abyte0, 0);
}

public DESKeySpec(byte abyte0[], int i)
throws InvalidKeyException
{
if(abyte0.length - i < 8)
{
throw new InvalidKeyException("Wrong key size");
} else
{
a = new byte[8];
System.arraycopy(abyte0, i, a, 0, 8);
return;
}
}

获得密钥后我们就可以进行字节数组和文件的加解密工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 加密字节数组形式的数据
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] encryptByteArr(byte[] data, Key key) throws Exception {
// using DES in ECB mode
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
// 用密匙初始化 Cipher 对象
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(data);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 解密字节数组形式的密文
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] decryptByteArr(byte[] data, Key key) throws Exception {
// using DES in ECB mode
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
// 用密匙初始化 Cipher 对象
cipher.init(Cipher.DECRYPT_MODE, key);
return cipher.doFinal(data);
}
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
/**
* DES 加密文件
* @param file 明文文件
* @param dest 加密后的密文文件
* @param key 密钥
* @throws NoSuchAlgorithmException
* @throws NoSuchPaddingException
* @throws InvalidKeyException
* @throws IOException
*/
public static void encryptFile(File file, File dest, Key key)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException {
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key);
InputStream is = new FileInputStream(file);
OutputStream out = new FileOutputStream(dest);
CipherInputStream cis = new CipherInputStream(is, cipher);
byte[] buffer = new byte[1024];
int r;
while ((r = cis.read(buffer)) > 0) {
out.write(buffer, 0, r);
}
cis.close();
is.close();
out.close();
}
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
/**
* DES 解密文件
* @param file 需要解密的密文文件
* @param dest 解密出的明文文件
* @param key 密钥
* @throws NoSuchAlgorithmException
* @throws NoSuchPaddingException
* @throws InvalidKeyException
* @throws IOException
*/
public static void decryptFile(File file, File dest, Key key)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
IOException {
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, key);
InputStream is = new FileInputStream(file);
OutputStream out = new FileOutputStream(dest);
CipherInputStream cis = new CipherInputStream(is, cipher);
byte[] buffer = new byte[1024];
int r;
while ((r = cis.read(buffer)) > 0) {
out.write(buffer, 0, r);
}
cis.close();
is.close();
out.close();
}