-
非对称加密算法
工作原理
主要应用
主要功能
主要算法
算法区别
说了这么多概念性东西,都是方便大家加深理解,想要理解的更仔细可以自行百度。
下面我会以实战的方式实现常用的非对称加密算法的加密和解密。
一:DH实现非对称加密算法:
方式一:jdk的方式实现DH
// jdk实现:
public static void jdkDH()
{
try
{
// 1.初始化发送方密钥
KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance("DH");
senderKeyPairGenerator.initialize(512);
KeyPair senderKeyPair = senderKeyPairGenerator.generateKeyPair();
// 发送方公钥,发送给接收方(网络、文件。。。)
byte[] senderPublicKeyEnc = senderKeyPair.getPublic().getEncoded();
// 2.初始化接收方密钥
KeyFactory receiverKeyFactory = KeyFactory.getInstance("DH");
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(senderPublicKeyEnc);
PublicKey receiverPublicKey = receiverKeyFactory.generatePublic(x509EncodedKeySpec);
DHParameterSpec dhParameterSpec = ((DHPublicKey) receiverPublicKey).getParams();
KeyPairGenerator receiverKeyPairGenerator = KeyPairGenerator.getInstance("DH");
receiverKeyPairGenerator.initialize(dhParameterSpec);
KeyPair receiverKeypair = receiverKeyPairGenerator.generateKeyPair();
PrivateKey receiverPrivateKey = receiverKeypair.getPrivate();
byte[] receiverPublicKeyEnc = receiverKeypair.getPublic().getEncoded();
// 3.密钥构建
KeyAgreement receiverKeyAgreement = KeyAgreement.getInstance("DH");
receiverKeyAgreement.init(receiverPrivateKey);
receiverKeyAgreement.doPhase(receiverPublicKey, true);
SecretKey receiverDesKey = receiverKeyAgreement.generateSecret("DES");
KeyFactory senderKeyFactory = KeyFactory.getInstance("DH");
x509EncodedKeySpec = new X509EncodedKeySpec(receiverPublicKeyEnc);
PublicKey senderPublicKey = senderKeyFactory.generatePublic(x509EncodedKeySpec);
KeyAgreement senderKeyAgreement = KeyAgreement.getInstance("DH");
senderKeyAgreement.init(senderKeyPair.getPrivate());
senderKeyAgreement.doPhase(senderPublicKey, true);
SecretKey senderDesKey = senderKeyAgreement.generateSecret("DES");
if(Objects.equals(receiverDesKey, senderDesKey))
{
System.out.println("双方密钥相同。");
}
// 4.加密
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, senderDesKey);
byte[] result = cipher.doFinal(src.getBytes());
System.out.println("bc dh encrypt:" + Base64.encodeBase64String(result));
// 5.解密
cipher.init(Cipher.DECRYPT_MODE, receiverDesKey);
result = cipher.doFinal(result);
System.out.println("bc dh decrypt:" + new String(result));
} catch (Exception e) {
e.printStackTrace();
}
}
方式二:elgamal方式实现:
// jdk实现:“私钥解密、公钥加密” , 对于:“私钥加密、公钥解密”有问题,因为Elgamal不支持
public static void jdkElgamal()
{
try
{
// 加入对BouncyCastle支持
Security.addProvider(new BouncyCastleProvider());
// 1.初始化发送方密钥
AlgorithmParameterGenerato algorithmParameterGenerator= AlgorithmParameterGenerator.getInstance("Elgamal");
// 初始化参数生成器
algorithmParameterGenerator.init(256);
// 生成算法参数
AlgorithmParameters algorithmParameters = algorithmParameterGenerator.generateParameters();
// 构建参数材料
DHParameterSpec dhParameterSpec = (DHParameterSpec)algorithmParameters.getParameterSpec(DHParameterSpec.class);
// 实例化密钥生成器
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("Elgamal");
// 初始化密钥对生成器
keyPairGenerator.initialize(dhParameterSpec, new SecureRandom());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// 公钥
PublicKey elGamalPublicKey = keyPair.getPublic();
// 私钥
PrivateKey elGamalPrivateKey = keyPair.getPrivate();
System.out.println("Public Key:" + Base64.encodeBase64String(elGamalPublicKey.getEncoded()));
System.out.println("Private Key:" + Base64.encodeBase64String(elGamalPrivateKey.getEncoded()));
// 2.私钥解密、公钥加密 ---- 加密
// 初始化公钥
// 密钥材料转换
X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(elGamalPublicKey.getEncoded());
// 实例化密钥工厂
KeyFactory keyFactory2 = KeyFactory.getInstance("Elgamal");
// 产生公钥
PublicKey publicKey2 = keyFactory2.generatePublic(x509EncodedKeySpec2);
// 数据加密
// Cipher cipher2 = Cipher.getInstance("Elgamal");
Cipher cipher2 = Cipher.getInstance(keyFactory2.getAlgorithm());
cipher2.init(Cipher.ENCRYPT_MODE, publicKey2);
byte[] result2 = cipher2.doFinal(src.getBytes());
System.out.println("私钥加密、公钥解密 ---- 加密:" + Base64.encodeBase64String(result2));
// 3.私钥解密、公钥加密 ---- 解密
PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded());
KeyFactory keyFactory5 = KeyFactory.getInstance("Elgamal");
PrivateKey privateKey5 = keyFactory5.generatePrivate(pkcs8EncodedKeySpec5);
// Cipher cipher5 = Cipher.getInstance("Elgamal");
Cipher cipher5 = Cipher.getInstance(keyFactory5.getAlgorithm());
cipher5.init(Cipher.DECRYPT_MODE, privateKey5);
byte[] result5 = cipher5.doFinal(result2);
System.out.println("Elgamal 私钥加密、公钥解密 ---- 解密:" + new String(result5));
/*
// 私钥加密、公钥解密: 有问题
// 4.私钥加密、公钥解密 ---- 加密
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("Elgamal");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance("Elgamal");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] result = cipher.doFinal(src.getBytes());
System.out.println("私钥加密、公钥解密 ---- 加密:" + Base64.encodeBase64String(result));
// 5.私钥加密、公钥解密 ---- 解密
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(elGamalPublicKey.getEncoded());
keyFactory = KeyFactory.getInstance("Elgamal");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
cipher = Cipher.getInstance("Elgamal");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
result = cipher.doFinal(result);
System.out.println("Elgamal 私钥加密、公钥解密 ---- 解密:" + new String(result));
*/
} catch (Exception e) {
e.printStackTrace();
}
}
方式二:
//非对称密钥算法
public static final String KEY_ALGORITHM="ElGamal";
/**
* 密钥长度,DH算法的默认密钥长度是1024
* 密钥长度必须是8的倍数,在160到16384位之间
* */
private static final int KEY_SIZE=256;
//公钥
private static final String PUBLIC_KEY="ElGamalPublicKey";
//私钥
private static final String PRIVATE_KEY="ElGamalPrivateKey";
/**
* 初始化密钥对
* @return Map 甲方密钥的Map
* */
public static Map<String,Object> initKey() throws Exception{
//加入对BouncyCastle支持
Security.addProvider(new BouncyCastleProvider());
AlgorithmParameterGenerator apg=AlgorithmParameterGenerator.getInstance(KEY_ALGORITHM);
//初始化参数生成器
apg.init(KEY_SIZE);
//生成算法参数
AlgorithmParameters params=apg.generateParameters();
//构建参数材料
DHParameterSpec elParams=(DHParameterSpec)params.getParameterSpec(DHParameterSpec.class);
//实例化密钥生成器
KeyPairGenerator kpg=KeyPairGenerator.getInstance(KEY_ALGORITHM) ;
//初始化密钥对生成器
kpg.initialize(elParams,new SecureRandom());
KeyPair keyPair=kpg.generateKeyPair();
//甲方公钥
PublicKey publicKey= keyPair.getPublic();
//甲方私钥
PrivateKey privateKey= keyPair.getPrivate();
//将密钥存储在map中
Map<String,Object> keyMap=new HashMap<String,Object>();
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
/**
* 公钥加密
* @param data待加密数据
* @param key 密钥
* @return byte[] 加密数据
* */
public static byte[] encryptByPublicKey(byte[] data,byte[] key) throws Exception{
//实例化密钥工厂
KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
//初始化公钥
//密钥材料转换
X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(key);
//产生公钥
PublicKey pubKey=keyFactory.generatePublic(x509KeySpec);
//数据加密
Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
return cipher.doFinal(data);
}
/**
* 私钥解密
* @param data 待解密数据
* @param key 密钥
* @return byte[] 解密数据
* */
public static byte[] decryptByPrivateKey(byte[] data,byte[] key) throws Exception{
//取得私钥
PKCS8EncodedKeySpec pkcs8KeySpec=new PKCS8EncodedKeySpec(key);
KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
//生成私钥
PrivateKey privateKey=keyFactory.generatePrivate(pkcs8KeySpec);
//数据解密
Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 取得私钥
* @param keyMap 密钥map
* @return byte[] 私钥
* */
public static byte[] getPrivateKey(Map<String,Object> keyMap){
Key key=(Key)keyMap.get(PRIVATE_KEY);
return key.getEncoded();
}
/**
* 取得公钥
* @param keyMap 密钥map
* @return byte[] 公钥
* */
public static byte[] getPublicKey(Map<String,Object> keyMap) throws Exception{
Key key=(Key) keyMap.get(PUBLIC_KEY);
return key.getEncoded();
}
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
//初始化密钥
//生成密钥对
Map<String,Object> keyMap=ElGamalTest2.initKey();
//公钥
byte[] publicKey=ElGamalTest2.getPublicKey(keyMap);
//私钥
byte[] privateKey=ElGamalTest2.getPrivateKey(keyMap);
System.out.println("公钥:/n"+Base64.encodeBase64String(publicKey));
System.out.println("私钥:/n"+Base64.encodeBase64String(privateKey));
System.out.println("================密钥对构造完毕,甲方将公钥公布给乙方,开始进行加密数据的传输=============");
String str="ElGamal密码交换算法";
System.out.println("/n===========甲方向乙方发送加密数据==============");
System.out.println("原文:"+str);
//乙方使用公钥对数据进行加密
byte[] code2=ElGamalTest2.encryptByPublicKey(str.getBytes(), publicKey);
System.out.println("===========乙方使用公钥对数据进行加密==============");
System.out.println("加密后的数据:"+Base64.encodeBase64String(code2));
//甲方使用私钥对数据进行解密
byte[] decode2=ElGamalTest2.decryptByPrivateKey(code2, privateKey);
System.out.println("甲方解密后的数据:"+new String(decode2));
}
方式三:RSA实现非对称加密算法:
方式一:jdk实现
// jdk实现:私钥加密、公钥解密: 并发时间测试
public static void RSA()
{
try
{
long startTimes = System.currentTimeMillis();
// 1.初始化发送方密钥
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(512);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
final RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
System.out.println("Public Key:" + Base64.encodeBase64String(rsaPublicKey.getEncoded()));
System.out.println("Private Key:" + Base64.encodeBase64String(rsaPrivateKey.getEncoded()));
// 2.公钥加密、私钥解密 ---- 加密
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
result = cipher.doFinal(src.getBytes());
System.out.println("公钥加密、私钥解密 ---- 加密:" + Base64.encodeBase64String(result));
long endEncryptTime = System.currentTimeMillis();
System.out.println("公钥加密、私钥解密 ---- 加密1个时间(单位毫秒):" + (endEncryptTime - startTimes));
int decryptTimes = 200000; // 并发解密的个数
//创建一个可重用固定线程数的线程池
ExecutorService pool = Executors.newCachedThreadPool(); // Executors.newFixedThreadPool(1000);
for(int i=0; i<decryptTimes;i++)
{
pool.execute(new Thread(new Runnable() {
@Override
public void run() {
try {
// 3.私钥解密、公钥加密 ---- 解密
PKCS8EncodedKeySpec pkcs8EncodedKeySpec2 = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
KeyFactory keyFactory2 = KeyFactory.getInstance("RSA");
PrivateKey privateKey2 = keyFactory2.generatePrivate(pkcs8EncodedKeySpec2);
Cipher cipher2 = Cipher.getInstance("RSA");
cipher2.init(Cipher.DECRYPT_MODE, privateKey2);
byte[] result2 = cipher2.doFinal(result);
// System.out.println("公钥加密、私钥解密 ---- 解密:" + new String(result2));
} catch (Exception e) {
e.printStackTrace();
}
}
}));
}
pool.shutdown();
while (true) {
if (pool.isTerminated()) {
System.out.println("结束了!");
long endDencryptTime = System.currentTimeMillis() ;
long totalTimes = (endDencryptTime - endEncryptTime) / 1000;
System.out.println("公钥加密、私钥解密 ---- 并发:" + decryptTimes + "个解密时间(单位秒):" + totalTimes);
break;
}
Thread.sleep(200);
}
} catch (Exception e) {
e.printStackTrace();
}
}
方式二:
// jdk实现:
public static void jdkRSA()
{
try
{
// 1.初始化发送方密钥
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(512);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
System.out.println("Public Key:" + Base64.encodeBase64String(rsaPublicKey.getEncoded()));
System.out.println("Private Key:" + Base64.encodeBase64String(rsaPrivateKey.getEncoded()));
// 2.私钥加密、公钥解密 ---- 加密
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] result = cipher.doFinal(src.getBytes());
System.out.println("私钥加密、公钥解密 ---- 加密:" + Base64.encodeBase64String(result));
// 3.私钥加密、公钥解密 ---- 解密
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
result = cipher.doFinal(result);
System.out.println("私钥加密、公钥解密 ---- 解密:" + new String(result));
// 4.公钥加密、私钥解密 ---- 加密
X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
KeyFactory keyFactory2 = KeyFactory.getInstance("RSA");
PublicKey publicKey2 = keyFactory2.generatePublic(x509EncodedKeySpec2);
Cipher cipher2 = Cipher.getInstance("RSA");
cipher2.init(Cipher.ENCRYPT_MODE, publicKey2);
byte[] result2 = cipher2.doFinal(src.getBytes());
System.out.println("公钥加密、私钥解密 ---- 加密:" + Base64.encodeBase64String(result2));
// 5.私钥解密、公钥加密 ---- 解密
PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
KeyFactory keyFactory5 = KeyFactory.getInstance("RSA");
PrivateKey privateKey5 = keyFactory5.generatePrivate(pkcs8EncodedKeySpec5);
Cipher cipher5 = Cipher.getInstance("RSA");
cipher5.init(Cipher.DECRYPT_MODE, privateKey5);
byte[] result5 = cipher5.doFinal(result2);
System.out.println("公钥加密、私钥解密 ---- 解密:" + new String(result5));
} catch (Exception e) {
e.printStackTrace();
}
}
好了,对称加密算法就总结到这里了,在下一篇中,我将会总结常用的对称加密算法。