一、对称加密(DES加密)
一、DES简介
DES是一种对称加密(Data Encryption Standard)算法。于1977年得到美国政府的正式许可,是一种用56位密钥来加密64位数据的方法。一般密码长度
为8个字节,其中56位加密密钥,每个第8位都用作奇偶校验。
DES算法一般有两个关键点,第一个是加密算法,第二个是数据补位。
二、加密算法类型
1、电子密文方式(ECB)
ECB模式是分组密码的基本工作方式。在该模式下,每个加密区块按顺序进行独立加密,得到独立的密文区块,每个加密区块的结果都不会被其
他区块影响,用此方式,可用平行处理实施加速加、解密运算,且在网络传输时任何一一个区块出现错误,也不存在影响到其他区块传输的结果,这是
该模式的好处。
ECB模式的不足是易使明文的数据模式暴露。在计算机系统里,很多数据均存在固有模式,这主要是由数据结构与数据冗余导致的。若无任何措
施,针对在需加密的文件里出现多回的明文,这部分明文如果刚好是加密区块的大小,则可能会得到一样的密文,且密文内容如果受到剪贴、代替
也很难被发现。
2、密文分组链接方式(CBC)
第一个加密区块先与初始向量做异或运算,再进行加密。其他每个加密区块在加密之前,必须与前一个加密区块的密文做一次异或运算,再进行
加密。每个区块的加密结果都会被前面全部区块内容的影响,因此尽管在明文里出现多次一样的明文,也会得到不一样的密文。
还有,密文内容如果遇到剪贴、替换,或于网络传输时出现错误,则它后面的密文会被破坏,不能顺利解密还原,这是这一模式的优点也是缺点。
其次,一定得选取1个初始向量来加密第1个区块,且加密作业时不能用平行处理加速加密运算,不过解密运算,做异或的加密区块结果已经有了,
则还可用平行处理加速。
3、密文反馈方式(CFB)
可把区块加密算法作流密码加密器用,流密码加密器可由实际需要,每回加密区块的大小能自行确定每个区块的明文与之前区块加密后的密文
异或后,变成密文。因此, 每一一个区块的加密结果也受之前所有区块内容的影响,也会使在明文中出现多回一样的明文都得到不一样的密文。在
这个模式下,和CBC模式相同,为了加密第1个区块,一定得选1个初始向量,且其必须只有一个、每次加密时肯定不一样,也很难用平行处理加快
加密作业。
4、输出反馈模式(OFB)
OFB与CFB大致相同,唯一的差 异是每个区块的明文与之前区块加密后的密文做异或后产生密文。之前区块加密后的密文是独立产生的,每个
区块的加密结果不会被前面全部区块内容影响,若存在区块在传输中丢失或出现错误,不至于不能完全解密,但也会使在明文中出现多回的明文,
都得到同样的密文,也易遭遇剪接攻击。而在此模式下,为了加密第1个区块,一定得 设置1个初始向量,要不然很难用平行处理加快加密作业。
容易看出,以上4种操作模式有不同的优点和缺点。在ECB与OFB中改变- -个明文块会使有关的密文块发生改变,但其他密文块不变。有些情况
下这可能是-一个好的特性。另-方面,在CBC与CFB中改变一个明文块,那么对应的密文块及它后面的全部密文块会改变,此特性代表CBC与
CFB模式适合于鉴别。更明确地说,这些模式能用来产生消息鉴别码,将其附在明文块序列的后面可保护消息的完整性。
三、数据补位
1、NoPadding
API或算法本身不对数据进行处理,加密数据由加密双方约定填补算法。例如若对字符串数据进行加解密,可以补充\0或者空格,然后trim
2、PKCS5Padding
加密前:数据字节长度对8取余,余数为m,若m>0,则补足8-m个字节,字节数值为8-m,即差几个字节就补几个字节,字节数值即为补充的字节数,若为0则补充8个字节的8
解密后:取最后一个字节,值为m,则从数据尾部删除m个字节,剩余数据即为加密前的原文
因为DES是一种block cipher,一个block要8个字节,所以要加密的东西要分成8字节的整数倍,不足的就填充。
PKCS5Padding这种填充,填的字节代表所填字节的总数:
比如差三个字节的话填为 @@@@@333 差7个字节就填为 @7777777 没有差就填 88888888
四、代码示例
package com.js.port.rainy.commons.util; import org.apache.tomcat.util.codec.binary.Base64; import org.bouncycastle.jce.provider.BouncyCastleProvider; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import java.security.Key; import java.security.Security; public class DESUtils { private static final String src = "待加密的数据"; public static void main(String[] args) { System.out.println("des jdk加密模式"); jdkDES(); System.out.println("-------------------------"); System.out.println("des bc加密模式"); bcDES(); } /** * jdk加密模式(des) * */ public static void jdkDES() { try { //生成KEY KeyGenerator keyGenerator = KeyGenerator.getInstance("DES"); keyGenerator.getProvider(); keyGenerator.init(56); SecretKey secretKey = keyGenerator.generateKey(); byte[] bytesKey = secretKey.getEncoded(); //key转换 DESKeySpec desKeySpec = new DESKeySpec(bytesKey); SecretKeyFactory factory = SecretKeyFactory.getInstance("DES"); Key convertSecretKey = factory.generateSecret(desKeySpec); //加密 加密方式/工作模式/填充方式 Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); //方式/秘钥 cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey); byte[] result = cipher.doFinal(src.getBytes()); System.out.println("jdk des加密后的数据:"+ Base64.encodeBase64String(result)); //解密 方式/秘钥 cipher.init(Cipher.DECRYPT_MODE,convertSecretKey); result = cipher.doFinal(result); System.out.println("jdk des解密后的数据:" + new String(result)); } catch (Exception e) { System.out.println("error:"+e.getMessage()); } } /** * bc加密模式(des) * */ public static void bcDES() { try { Security.addProvider(new BouncyCastleProvider()); //生成KEY KeyGenerator keyGenerator = KeyGenerator.getInstance("DES","BC"); keyGenerator.getProvider(); keyGenerator.init(56); SecretKey secretKey = keyGenerator.generateKey(); byte[] bytesKey = secretKey.getEncoded(); //key转换 DESKeySpec desKeySpec = new DESKeySpec(bytesKey); SecretKeyFactory factory = SecretKeyFactory.getInstance("DES"); Key convertSecretKey = factory.generateSecret(desKeySpec); //加密 加密方式/工作模式/填充方式 Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); //方式/秘钥 cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey); byte[] result = cipher.doFinal(src.getBytes()); System.out.println("bc des加密后的数据:"+ Base64.encodeBase64String(result)); //解密 方式/秘钥 cipher.init(Cipher.DECRYPT_MODE,convertSecretKey); result = cipher.doFinal(result); System.out.println("bc des解密后的数据:" + new String(result)); } catch (Exception e) { System.out.println("error:"+e.getMessage()); } } }
输出结果:
pom引用
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.70</version> </dependency>