公司网站服务器优化百度安装app
1.对称加密算法定义:数据发送方将原始数据和加密密钥经过特殊加密算法处理后,将加密密文发送出去。接收方收到密文后,需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。
2.在对称加密算法中,使用的密钥只有一个,双方都使用这个密钥对数据进行加密和解密,
常用的对称加密算法:DES、3DES(TripleDES)和AES
常用的加密模式是:ECB:电子密码本模式、CBC:加密分组链接模式
常用的填充方式是:NoPadding(不填充)、Zeros填充(0填充)、PKCS5Padding填充
3.注意以下区别
3.1.不同的加密算法,其工作密钥不同且产生密钥工厂的算法名不同
DES有很多同胞兄弟,如DESede(TripleDES)、AES大同小异,
(1)密钥长度不同
DES固定工作密钥(为8个字节共64位)
AES固定工作密钥为16/24/32bytes。
(2)在产生密钥工厂时只要换掉ALGORITHM换成对应的值就行SecretKey secretKey = new SecretKeySpec(key, ALGORITHM),
3.2加密模式不同,初始化的随机也不同
ECB采用分组加密的方式,将明文按8字节(64位)分组分别加密。
CBC的处理方式是先用初始向量IV对第一组加密,再用第一组的密文作为密钥对第二组加密,然后依次完成整个加密操作。如果明文中有两个分组的内容相同,ECB会得到完全一样的密文,但CBC则不会。
DES下的cbc模式下的pkcs5padding可以用初始向量IV加密也能用SecureRandom,但是aes必须用初始向量
在初始化向量参数时AES 为16bytes. DES 为8bytes.
3.3填充方式不同
如果没有指定,默认的方式就是PKCS5Padding
大部分情况下,明文并非刚好64位的倍数。对于最后一个分组,如果长度小于64位,则需要用数据填充至64位。
PKCS7Padding是缺几个字节就补几个字节的0,
PKCS5Padding是缺几个字节就补充几个字节的几,好比缺6个字节,就补充6个字节的6
4.有可能出现的错误
(1)java.security.InvalidKeyException: Wrong key size工作密钥(为8个字节共64位)
(2)javax.crypto.BadPaddingException: Given final block not properly padded
原因是Cipher cipher = Cipher.getInstance("DES");
5.主要步骤如下:
2.在对称加密算法中,使用的密钥只有一个,双方都使用这个密钥对数据进行加密和解密,
常用的对称加密算法:DES、3DES(TripleDES)和AES
常用的加密模式是:ECB:电子密码本模式、CBC:加密分组链接模式
常用的填充方式是:NoPadding(不填充)、Zeros填充(0填充)、PKCS5Padding填充
3.注意以下区别
3.1.不同的加密算法,其工作密钥不同且产生密钥工厂的算法名不同
DES有很多同胞兄弟,如DESede(TripleDES)、AES大同小异,
(1)密钥长度不同
DES固定工作密钥(为8个字节共64位)
AES固定工作密钥为16/24/32bytes。
(2)在产生密钥工厂时只要换掉ALGORITHM换成对应的值就行SecretKey secretKey = new SecretKeySpec(key, ALGORITHM),
3.2加密模式不同,初始化的随机也不同
ECB采用分组加密的方式,将明文按8字节(64位)分组分别加密。
CBC的处理方式是先用初始向量IV对第一组加密,再用第一组的密文作为密钥对第二组加密,然后依次完成整个加密操作。如果明文中有两个分组的内容相同,ECB会得到完全一样的密文,但CBC则不会。
DES下的cbc模式下的pkcs5padding可以用初始向量IV加密也能用SecureRandom,但是aes必须用初始向量
在初始化向量参数时AES 为16bytes. DES 为8bytes.
3.3填充方式不同
如果没有指定,默认的方式就是PKCS5Padding
大部分情况下,明文并非刚好64位的倍数。对于最后一个分组,如果长度小于64位,则需要用数据填充至64位。
PKCS7Padding是缺几个字节就补几个字节的0,
PKCS5Padding是缺几个字节就补充几个字节的几,好比缺6个字节,就补充6个字节的6
4.有可能出现的错误
(1)java.security.InvalidKeyException: Wrong key size工作密钥(为8个字节共64位)
(2)javax.crypto.BadPaddingException: Given final block not properly padded
原因是Cipher cipher = Cipher.getInstance("DES");
等同于Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding")一样,填充方式错误,加密的时候会得到16长度的字节数组。
/*简单Des算法加密解密使用ECB/NoPadding主要参数有:工作密钥(为8个字节共64位)数据(为8个字节共64位)指定工作方式(ECB/NoPadding)且随机数用new SecureRandom()*/
public class DesEcbNopaddingSafety {public static void main(String[] args) {String data = "12345678";String key = "12345678";byte[] encryData = encrydata(data, key);String encryD = new Base64().encodeAsString(encryData);System.out.println("加密后的数据是:" + encryD);byte[] decodeD = new Base64().decode(encryD);byte[] descryData = bytedecryData(decodeD, key);String d = new String(descryData);System.out.println("解密后的数据是:" + d);}private static byte[] bytedecryData(byte[] decodeD, String key) {// TODO Auto-generated method stubbyte[] deData = null;try {SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");DESKeySpec dks = new DESKeySpec(key.getBytes());SecretKey securekey = keyFactory.generateSecret(dks);Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");SecureRandom random = new SecureRandom();cipher.init(Cipher.ENCRYPT_MODE, securekey, random);deData = cipher.doFinal(decodeD);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return deData;}private static byte[] encrydata(String data, String key) {// TODO Auto-generated method stubbyte[] encryData = null;try {// 创建一个密钥工厂SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("DES");// 根据原始密钥数据创建密钥对象DESKeySpec,使用 key 中的前 8 个字节作为 DES 密钥的密钥内容DESKeySpec dks = new DESKeySpec(key.getBytes());// 在用密钥工厂把DESKeySpec变成规范的密钥对象SecretKeySecretKey securekey = keyfactory.generateSecret(dks);// 生成一个可信任的随机数源SecureRandom random = new SecureRandom();// 通过Cipher.getInstance()工厂方法来实例化密码对象。Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");// 用密钥、算法参数和随机源初始化此Cipher密码对象cipher.init(Cipher.DECRYPT_MODE, securekey, random);// 执行加密encryData = cipher.doFinal(data.getBytes());} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return encryData;}
}<pre name="code" class="java">
加密后的数据是:9ejp64Hyi3M=
解密后的数据是:12345678
/*使用DES/CBC/PKCS5Padding加密且随机数用new IvParameterSpec(iv1)*/
public class DesCbcPkcs5Safety {public static void main(String[] args) {String data = "1234578";String key = "12345678";byte[] encryData = encrydata(data, key);String encryD = new Base64().encodeAsString(encryData);System.out.println("加密后的数据是:" + encryD);byte[] decodeD = new Base64().decode(encryD);byte[] descryData = bytedecryData(decodeD, key);String d = new String(descryData);System.out.println("解密后的数据是:" + d);}private static byte[] bytedecryData(byte[] decodeD, String key) {// TODO Auto-generated method stubbyte[] deData = null;try {SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");DESKeySpec dks = new DESKeySpec(key.getBytes());SecretKey securekey = keyFactory.generateSecret(dks);Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");// 这里使用的是向量。采用此代码中的IVParameterSpecIvParameterSpec iv = new IvParameterSpec(iv1);cipher.init(Cipher.DECRYPT_MODE, securekey, iv);deData = cipher.doFinal(decodeD);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return deData;}private static byte[] encrydata(String data, String key) {// TODO Auto-generated method stubbyte[] encryData = null;try {Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("DES");SecretKey securekey = keyfactory.generateSecret(new DESKeySpec(key.getBytes()));// 注意这里使用的是向量IvParameterSpec iv = new IvParameterSpec(iv1);cipher.init(Cipher.ENCRYPT_MODE, securekey, iv);encryData = cipher.doFinal(data.getBytes());} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return encryData;}private static byte[] iv1 = { (byte) 0x12, (byte) 0x34, (byte) 0x56,(byte) 0x78, (byte) 0x90, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF };
}
加密后的数据是:DXCyuKP3IWQ=
解密后的数据是:1234578
5.主要步骤如下:
(1).利用SecretKeyFactory.getInstance("加密算法")创建密钥工厂
(2).用new DESKeySpec(原始密钥)产生密钥对象
(3).用密钥工厂的generateSecret(密钥对象)方法把密钥对象转换成规范的密钥对象
(4).用new SecureRandom()或者用 new IvParameterSpec(向量)生成一个可信任的随机数源
(5).用Cipher.getInstance("加密算法/加密模式/填充模式")产生加密解密对象
(6).用cipher.init(加密解密模型,规范密钥,随机数)初始化加密解密对象
(7).用cipher.doFinal(数据)执行加密解密操作