数据传输的过程中经常遇到加密的场景,今天来先研究一下对称加密算法。
对称加密算法一般来讲,加密密匙和解密的密匙是一致的,解密就是加密的逆运算。
DES加密
目前来看已经不太安全的加密算法,出现的时间比较早。加密的长度一般是56位。下面举个应用的例子:服务端A和客户端B之间互传数据,B加密,A来解密。首先要有个双方都知道的密匙:
KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
keyGenerator.init(56);
SecretKey secretKey =keyGenerator.generateKey();
byte[]bytesKey =secretKey.getEncoded(); // bytesKey就是生成的一个可用的密匙,通过Arrays.toString(bytesKey)获取有效串
A,B本地通过赋值,定义约定好的密匙
byte[] bytesKey = new byte[]{-124, -46, 121, -47, 52, -70, 8, -32, -3, 114, -80, 82, -88, -94, 115, 109}; // 数字就是有效串
B通过以下方式将要传输的数据加密:
// Key转换
DESKeySpec desKeySpec = new DESKeySpec(bytesKey);
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
Key key =factory.generateSecret(desKeySpec);
// 加密
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE,key);
byte[]result =cipher.doFinal(str.getBytes());
// Hex.encodeHexString(result) 得到就是要传输的加密数据字符串
A通过以下方式将收到的数据解密:
// Key转换
DESKeySpec desKeySpec = new DESKeySpec(bytesKey);
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
Key key = factory.generateSecret(desKeySpec);
// 解密
cipher.init(Cipher.DECRYPT_MODE,key);
result =cipher.doFinal(result);
//new String(result,"UTF-8") 得到解密后的数据
3DES(3重DES)
好处:1.密码长度变长 2.迭代次数变多
AES(建议使用,实际使用可以参考DES的场景)
尚未明确已经被破解,用来替代DES,效率更高。(DES -> 3DES -> N?DES, 是否DES用增加迭代次数来保障加密的可靠性效率太低)
// 生成KEY
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
SecretKey secretKey =keyGenerator.generateKey();
byte[]bytesKey = secretKey.getEncoded();
System.out.println("byteKey:" + Arrays.toString(bytesKey));
// KEY转换
Key key =new SecretKeySpec(bytesKey, "AES");
// 加密
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE,key);
byte[]result = cipher.doFinal(str.getBytes());
System.out.println("encrypt:" + Hex.encodeHexString(result));
// 解密
cipher.init(Cipher.DECRYPT_MODE,key);
result =cipher.doFinal(result);
System.out.println("decrypt:" +new String(result));
PBE (基于口令)
1.口令容易破解,所以要加“盐” 2.密匙 = 盐 + 口令
// 生成盐(加同样的盐,能否返回相同的结果?可以)
SecureRandom random = new SecureRandom();
byte[]salt = random.generateSeed(8);
System.out.println("salt:" + Arrays.toString(salt));
// 依据口令生成密匙
String password ="nihao";
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory factory = SecretKeyFactory
.getInstance("PBEWITHMD5andDES");
Key key =factory.generateSecret(pbeKeySpec);
// 加密 迭代100次
PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(salt, 100);
Cipher cipher = Cipher.getInstance("PBEWITHMD5andDES");
cipher.init(Cipher.ENCRYPT_MODE,key, pbeParameterSpec);
byte[]result = cipher.doFinal(str.getBytes());
System.out
.println("jdk pbe encrypt:" + Hex.encodeHexString(result));
// 解密
cipher.init(Cipher.DECRYPT_MODE,key, pbeParameterSpec);
result =cipher.doFinal(result);
System.out.println("jdk pbe decrypt:" +new String(result));