慕课网学习笔记
参考:Java加密算法
对称加密算法
加密密钥和解密密钥相同,加密运算和解密运算互为逆运算。是一种初等的加密算法。主要的算法有DES(3DES)、AES、PBE、IDEA。
对称加密算法 —— DES
数据加密标准(Data Encryption Standard),IBM提交的算法。
package des;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class JavaDES {
private static String src = "面向对象编程,object-oriented!@#*5"; // 需要加密的原始字符串
public static void main(String[] args) throws Exception {
System.out.println("原始字符串:\n" + src);
jdkDES();
bouncyCastleDES();
}
/** jdk实现DES加密 */
public static void jdkDES() throws Exception{
//1.生成key
KeyGenerator keyGenerator = KeyGenerator.getInstance("des");//密钥生成器
keyGenerator.init(56);//指定密钥长度为56位
SecretKey secretKey = keyGenerator.generateKey();//用密钥生成器生成密钥
byte[] byteKeys = secretKey.getEncoded();//得到密钥的byte数组
//2.key转换
DESKeySpec desKeySpec = new DESKeySpec(byteKeys);
SecretKeyFactory factory = SecretKeyFactory.getInstance("des");//秘密密钥工厂
SecretKey convertSecretKey = factory.generateSecret(desKeySpec);
//3.加密
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");//见上图的工作模式和填充模式
cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);//加密模式
byte[]result = cipher.doFinal(src.getBytes());
System.out.println("jdk DES加密:\n" + Hex.encodeHexString(result));
//4.解密
cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);//解密模式
result = cipher.doFinal(result);
System.out.println("jdk DES解密:\n" + new String(result));
}
/** Bouncy Castle实现DES加密 */
public static void bouncyCastleDES() throws Exception{
Security.addProvider(new BouncyCastleProvider());//增加provider
//1.生成key
KeyGenerator keyGenerator = KeyGenerator.getInstance("des","BC");//密钥生成器,指定为bouncyCastle默认是sun的JCE
keyGenerator.init(56);//指定key长度为56位
keyGenerator.getProvider();
SecretKey secretKey = keyGenerator.generateKey();//用密钥生成器生成密钥
byte[] byteKeys = secretKey.getEncoded();//得到密钥的byte数组
//2.key转换
DESKeySpec desKeySpec = new DESKeySpec(byteKeys);
SecretKeyFactory factory = SecretKeyFactory.getInstance("des");//密钥工厂
SecretKey convertSecretKey = factory.generateSecret(desKeySpec);
//3.加密
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);//加密模式
byte[]result = cipher.doFinal(src.getBytes());
System.out.println("bc DES加密:\n" + Hex.encodeHexString(result));
//4.解密
cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);//解密模式
result = cipher.doFinal(result);
System.out.println("bc DES解密:\n" + new String(result));
}
}
运行结果:
在使用bc进行DES加解密的时候除了需要使用Security.addProvider()方法增加一个BouncyCastle,还需要指定密钥生成器的提供者为BC,如上面的代码的57行,否则会默认使用sun的JCE。应用场景:
对称加密算法——3重DES
3DES的好处是密钥长度增加。迭代次数增加。
实现的方式通常由JDK和BC两种,实现的方式和DES的实现方式大同小异:
package des;
import java.security.SecureRandom;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class Java3DES {
private static String src = "面向对象编程,object-oriented!@#*5"; // 需要加密的原始字符串
public static void main(String[] args) throws Exception {
System.out.println("原始字符串:" + src + "\n");
jdk3DES();
bouncyCastle3DES();
}
/** jdk实现3DES */
public static void jdk3DES() throws Exception{
//1.生成key
KeyGenerator keyGenerator = KeyGenerator.getInstance("desede");//密钥生成器
// keyGenerator.init(new SecureRandom()); //可以用它生成一个默认长度的key
keyGenerator.init(168);//指定密钥长度为112位
SecretKey secretKey = keyGenerator.generateKey();//用密钥生成器生成密钥
byte[] byteKeys = secretKey.getEncoded();//得到密钥的byte数组
//2.key转换
DESedeKeySpec deSedeKeySpec = new DESedeKeySpec(byteKeys);
SecretKeyFactory factory = SecretKeyFactory.getInstance("desede");//秘密密钥工厂
SecretKey convertSecretKey = factory.generateSecret(deSedeKeySpec);
//3.加密
Cipher cipher = Cipher.getInstance("desede/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);//加密模式
byte[]result = cipher.doFinal(src.getBytes());
System.out.println("jdk DES3加密:\n" + Hex.encodeHexString(result));
//4.解密
cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);//解密模式
result = cipher.doFinal(result);
System.out.println("jdk DES3解密:\n" + new String(result) + "\n");
}
/** bc实现3DES */
public static void bouncyCastle3DES() throws Exception{
Security.addProvider(new BouncyCastleProvider());
//1.生成key
KeyGenerator keyGenerator = KeyGenerator.getInstance("desede","BC");//密钥生成器[指定provider]
keyGenerator.init(new SecureRandom());//指定密钥的长度为默认
SecretKey secretKey = keyGenerator.generateKey();//用密钥生成器生成密钥
byte[] byteKeys = secretKey.getEncoded();//得到密钥的byte数组
//2.key转换
DESedeKeySpec deSedeKeySpec = new DESedeKeySpec(byteKeys);
SecretKeyFactory factory = SecretKeyFactory.getInstance("desede");//秘密密钥工厂
SecretKey convertSecretKey = factory.generateSecret(deSedeKeySpec);
//3.加密
Cipher cipher = Cipher.getInstance("desede/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);//加密模式
byte[]result = cipher.doFinal(src.getBytes());
System.out.println("bc DES3加密:\n" + Hex.encodeHexString(result));
//4.解密
cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);//解密模式
result = cipher.doFinal(result);
System.out.println("bc DES3解密:\n" + new String(result) + "\n");
}
}
运行结果:
对称加密算法——AES
AES产生的原因是3重DES的效率比较低而DES的安全性较低。AES是目前使用最多的对称加密算法,AES还有一个优势是至今尚未被破解。AES通常用于移动通信系统的加密以及基于SSH协议的软件(SSH Client、SecurityCRT)的加密。密钥长度以及实现方如下:
无政策限制权限文件是指:因为某些国家的进口管制限制,java发布的运行环境包中的一些加解密有一定的限制(因为美国政府的一些原因)。一般的JDK的jre的security包中的local_policy.jar和US_export_policy.jar都是没有内容的,所以只能使用128位加密。下面是JDK和BC实现的AES加密(步骤和DES类似):
package aes;
import java.security.Key;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class JavaAES {
private static String src = "面向对象编程,object-oriented!@#*5"; // 需要加密的原始字符串
public static void main(String[] args) throws Exception {
System.out.println("初始字符串:" + src + "\n");
jdkAES();
bouncyCastleAES();
}
public static void jdkAES() throws Exception{
//1.生成key
KeyGenerator keyGenerator = KeyGenerator.getInstance("aes");
keyGenerator.init(128);//初始化key的长度,只能是128,
SecretKey secretKey = keyGenerator.generateKey();//生成key
byte[] keyBytes = secretKey.getEncoded();//得到key的字节数组
//2.key的转换
Key key = new SecretKeySpec(keyBytes, "aes");
//3.加密
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//加解密方式+工作模式+填充方式
cipher.init(Cipher.ENCRYPT_MODE, key);//以加密模式初始化
byte[] result = cipher.doFinal(src.getBytes());
System.out.println("JDK AES加密:" + Base64.encodeBase64String(result));
//4.解密
cipher.init(Cipher.DECRYPT_MODE, key);
result = cipher.doFinal(result);
System.out.println("JDK AES解密:" + new String(result));
}
public static void bouncyCastleAES() throws Exception{
Security.addProvider(new BouncyCastleProvider());
KeyGenerator keyGenerator = KeyGenerator.getInstance("aes", "BC");
keyGenerator.init(128);//这里只能指定128,不能使用keyGenerator.init(new SecureRandom())
SecretKey secretKey = keyGenerator.generateKey();
byte[] keyBytes = secretKey.getEncoded();
Key key = new SecretKeySpec(keyBytes, "aes");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] result = cipher.doFinal(src.getBytes());
System.out.println("bc AES加密:" + Base64.encodeBase64String(result));
cipher.init(Cipher.DECRYPT_MODE, key);
result = cipher.doFinal(result);
System.out.println("bc AES解密:" + new String(result));
}
}
运行结果:
对称加密算法——PBE
PBE算法结合了消息摘要算法和对称加密算法的优点,是一种特殊的对称加密算法。Password Based Encryption,基于口令的加密。因为口令是比较好记的,就容易通过穷举、猜测的方式获得口令——针对这种情况,我们采用的方式是加盐(Salt),通过加入一些额外的内容(通常是随机字符)去扰乱。实现的方式有2种:JDK和BC。
JDK和BC实现的PBEWithMD5AndDES的算法如下:
package pbe;
import java.security.Key;
import java.security.SecureRandom;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class JavaPBE {
private static String src = "面向对象编程,object-oriented!@#*5"; // 需要加密的原始字符串
public static void main(String[] args) throws Exception {
System.out.println("原始字符串:" + src);
jdkPBE();
bouncyCastlePBE();
}
public static void jdkPBE() throws Exception{
//1.初始化盐
SecureRandom secureRandom = new SecureRandom();//强加密随机数生成器
byte[] salt= secureRandom.generateSeed(8);//产生盐必须是8位
//2.口令与密钥
String password = "root";
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());//密钥转换的对象
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");//实例化密钥转换工厂
Key key = factory.generateSecret(pbeKeySpec);//由工厂产生key
//3.加密
PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, 100);//PBE输入参数的材料,盐,迭代100次
Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");
cipher.init(Cipher.ENCRYPT_MODE, key, parameterSpec);
byte[] result = cipher.doFinal(src.getBytes());
System.out.println("jdk PBE加密:" + Base64.encodeBase64String(result));
//4.解密
cipher.init(Cipher.DECRYPT_MODE, key, parameterSpec);
result = cipher.doFinal(result);
System.out.println("jdk PBE解密:" + new String(result));
}
public static void bouncyCastlePBE() throws Exception{
Security.addProvider(new BouncyCastleProvider());//添加到provider
SecureRandom secureRandom = new SecureRandom();
byte[] salt = secureRandom.generateSeed(8);
String password = "admin";
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWithMD5AndDES","BC");//指定provider
Key key = factory.generateSecret(pbeKeySpec);
PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, 50);
Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");
cipher.init(Cipher.ENCRYPT_MODE, key,parameterSpec);
byte[]result = cipher.doFinal(src.getBytes());
System.out.println("bc PBE加密:" + Base64.encodeBase64String(result));
cipher.init(Cipher.DECRYPT_MODE, key, parameterSpec);
result = cipher.doFinal(result);
System.out.println("bc PBE解密:" + new String(result));
}
}
应用场景: