数据加密标准(DES,Data Encryption Standard,简写DES)是一种采用块密码加密的对称密钥算法,加密分组长度为64位,其中8、16、24、32、40、48、56、64 等8位是校验位,其余56位作为秘钥。
DES加密解密需要一个秘钥,使用这个秘钥加密的数据只能使用这个秘钥解密,这样,如果两个客户端在传输数据前先使用DES进行加密,那么就算传输密文被窃取,不知道秘钥就没办法解密,这就保证了数据的安全性。
DES是比较的老的加密算法,现已被证实可被破解,能不用就不用吧,可使用AES加密算法代替:AES对称加密算法实现:Java,C#,Golang,Python。
下面使用介绍各语言中的DES加密解密实现:
声明
1、加密解密过程分别使用比较多的ECB和CBC两种方式来实现,ECB性能更快,但是安全性没有CBC好,所以目前CBC用的比较多
2、加密解密填充方式采用PKCS7,或者PKCS5,这两者在这里的加密解密过程中的结果可以认为是一样的
3、CBC模式需要秘钥及初始向量,而ECB模式只需要秘钥即可,所以为了方便,下面封装的方法或者函数将通过判断是否存在初始向量来决定是使用CBC模式还是使用ECB模式
Java
Java中默认采用ECB模式,可以先做一个封装:
import java.security.Key; import javax.crypto.Cipher; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import javax.crypto.spec.IvParameterSpec; public class DesUtil { /** * DES加密 * * @param value * 待机加密明文 * @param secretKey * 秘钥 * @param iv * 初始向量,如果未空,则将采用ECB模式,否则采用CBC模式 * * @return 密文 */ public static String desEncrypt(String value, String secretKey, String iv) throws Exception { if (value == null || value.length() == 0) return ""; Cipher cipher = initCipher(Cipher.ENCRYPT_MODE, secretKey, iv); byte[] bytes = cipher.doFinal(value.getBytes("utf-8")); // 使用hex格式数据输出 StringBuffer result = new StringBuffer(); for (int i = 0; i < bytes.length; i++) { result.append(String.format("%02x", bytes[i])); } return result.toString(); } /** * DES解密 * * @param value * 密文 * @param secretKey * 秘钥 * @param iv * 初始向量,如果未空,则将采用ECB模式,否则采用CBC模式 * * @return 解密后的明文 */ public static String desDecrypt(String value, String secretKey, String iv) throws Exception { if (value == null || value.length() == 0) return ""; // 转换hex格式数据未byte数组 int length = value.length(); byte[] buffer = new byte[length / 2]; for (int i = 0; i < buffer.length; i++) { buffer[i] = (byte) Integer.parseInt( value.substring(i * 2, i * 2 + 2), 16); } Cipher cipher = initCipher(Cipher.DECRYPT_MODE, secretKey, iv); buffer = cipher.doFinal(buffer); return new String(buffer, "utf-8"); } private static Cipher initCipher(int mode, String secretKey, String iv) throws Exception { try { // 获取秘钥数组 byte[] secretBytes = secretKey.getBytes("utf-8"); byte[] keyBytes = new byte[8]; System.arraycopy(secretBytes, 0, keyBytes, 0, Math.min(secretBytes.length, keyBytes.length)); DESKeySpec dks = new DESKeySpec(keyBytes); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); Key key = keyFactory.generateSecret(dks); if (iv == null || iv.length() == 0) { Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");// 采用ECB方式 cipher.init(mode, key); return cipher; } else { // 初始向量数组 byte[] ivBytes = iv.getBytes("utf-8"); byte[] ivKeyBytes = new byte[8]; System.arraycopy(ivBytes, 0, ivKeyBytes, 0, Math.min(ivBytes.length, ivKeyBytes.length)); IvParameterSpec ivp = new IvParameterSpec(ivKeyBytes); Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");// 采用CBC方式 cipher.init(mode, key, ivp); return cipher; } } catch (Exception e) { e.printStackTrace(); throw e; } } }