介绍:
非对称加密相对与对称加密算法来说是高级的。
举个双保险的例子:
银行的保险柜,客户往银行的保险柜存贵重东西,这个保险柜的钥匙会有两把,客户有一把,银行有一把。如果想打开保险柜就需要银行的钥匙和客户的钥匙一块使用才能打开保险柜。
公钥,私钥:客户和银行的钥匙
公钥:是通过非安全的通道发放的,也就是说是公开的方式
私钥:自己保存的。
公钥和私钥一般是成对出现的,使用公钥加密的数据只有与它对应的私钥才能解开。
在非对称加密算法中有一些算法是可以公钥加密私钥解密,私钥加密公钥解密都支持的,有一些算法只支持一种方式的。
非对称加密算法种类:
DH(Diffie-Hellman):密钥交换算法
RSA:基于因子分解,既能用于数字加密也能用于数字签名
Elgamal:基于离散对数
ECC(Elliptical Curve Cryptography):椭圆曲线加密
DH
对称加密算法的弊端:
对称加密算法中公布密钥这个步骤会有问题,发送密钥的时候可能会出现泄露密钥的情况。一旦密钥被泄露,那么所有的数据就很容易被破解掉。
但是DH(密钥交换算法)是通过构建本地密钥来解决密钥容易在传递中泄露的问题的。
初始化发送方密钥涉及的三个类:
1. KeyPairGenerator(通过KeyPairGenerator来得到KeyPair类的对象)
//创建KeyPairGenerator对象
KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance("DH");//"DH"指定算法的名称
2 KeyPair(得到密钥对,包括公钥和私钥)
3. PublicKey:公钥
初始化接收方密钥涉及到的类:
1. KeyFactory:作用是生成密钥(包括公钥和私钥)
generatePublic()方法用来生成公钥
generatePrivate()方法用来生成私钥
2 X509EncodedKeySpec:根据ASN.1标准进行密钥编码
3. DHPublicKey:是PublicKey的某种具体的形式
4. DHParameterSpec:随从着DH算法来使用的参数的集合
5. KeyPairGenerator:通过KeyPairGenerator来得到KeyPair类的对象
6. PrivateKey:私钥
密钥构建涉及的类
- KeyAgreement:提供密钥一致性(或密钥交换)协议的功能
//生成实现指定密钥一致算法的KeyAgreement对象
static keyAgreement getInstance(String algorithm)
//为来自指定提供程序的指定密钥一致算法生成一个KeyAgreement对象
static keyAgreement getInstance(String algorithm,Provider provider)
2 SecretKey:生成一个分组的秘密密钥,同时提供了相应的类型安全的操作
3. KeyFactory
4. X509EncodedKeySpec
5. PublicKey
加解密涉及到的类:
Cipher
例子
package com.timliu.security.asymmetric_encryption;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Objects;
import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import org.apache.commons.codec.binary.Base64;
public class DHTest {
public static final String src = "hello world";
public static void main(String[] args) {
jdkDH();
}
// jdk实现:
public static void jdkDH() {
try {
/*
* 发送方的操作
*/
// 1.初始化发送方密钥
KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator
.getInstance("DH");
senderKeyPairGenerator.initialize(512);//设置长度
KeyPair senderKeyPair = senderKeyPairGenerator.generateKeyPair();//生成keypair
// 保存了发送方公钥的字节数组,发送给接收方(发送方式:网络、文件。。。)
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("发送方和接收方密钥相同。");
}else{
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();
}
}
}
运行结果:
DH算法的应用场景
RSA
唯一广泛接受并实现的非对称加密的算法。
可以实现数据加密和数字签名。
提供了:
1. 公钥加密,私钥解密
2. 私钥加密,公钥解密
例子:
package com.timliu.security.asymmetric_encryption;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import org.apache.commons.codec.binary.Base64;
public class RSATest {
public static final String src = "hello world";
public static void main(String[] args) {
jdkRSA();
}
// 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();
}
}
}
运行结果:
Public Key:
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAOz8ggiZp7ly13XoE9CtW3OlXQjVbrXc8zZCdKhFagXSSFcUvGqKbdfZuvjAjET7Vec7GurqLX14w99KnxFAbD8CAwEAAQ==
Private Key:
MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEA7PyCCJmnuXLXdegT0K1bc6VdCNVutdzzNkJ0qEVqBdJIVxS8aopt19m6+MCMRPtV5zsa6uotfXjD30qfEUBsPwIDAQABAkAjp4nYyWVWnVSVRKlWh/5uU76/iXzyl59v1me+uVLONR7XjkQyz7Kq3uh33276FAxZtHFlabphCpZf0aqpUFuBAiEA9lAF2lMjx379oTtRJhs75iw11z7f+hpaxaUN+JMa1RECIQD2TpWxJfF20bRyDCi0U2sl2ElqdxjZe0pAAiebgr3sTwIgbEChQeHWUMBUMf9C2++ONMvrYc1FXMMmb8TpzfzBBzECIQCOB4y8JRQTHyO9bBOAwGWV4h2bneefaT/MnzF1tDOOcwIhALs3oH3XIAPBU2bFBaGqBTO//XIUoE8CfyOfPA3fvusC
私钥加密、公钥解密 ---- 加密:
cIvL/HQH8gMBpD5qi99B4Cql/qZiNFc7eHfnua9qlQLGfQ436wNV9tzCQg+n7cR+/mDlAUSAvegwvk/0FD/Jmw==
私钥加密、公钥解密 ---- 解密:hello world
公钥加密、私钥解密 ---- 加密:
rvG7tdyCbU5B4fbT2xrFPkH8tUUsepkpZwGALi56/CCpVWOyvGq/aqBS4dQJKxjwH0t0pfWzt+iw3fJe3qTwGg==
公钥加密、私钥解密 ---- 解密:hello world
RSA应用场景:
ElGamal
提供公钥加密算法。
基于离散对数。
JDK没有提供ElGamal算法的实现,是Bouncy Castle提供的。
例子:
package com.timliu.security.asymmetric_encryption;
import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import javax.crypto.spec.DHParameterSpec;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class ElGamalTest {
public static final String src = "hello world";
public static void main(String[] args) {
BCElgamal();
}
/**
*
* 对于:“Illegal key size or default
* parameters”异常,是因为美国的出口限制,Sun通过权限文件(local_policy
* .jar、US_export_policy.jar)做了相应限制。因此存在一些问题: Java 6
* 无政策限制文件:http://www.oracle
* .com/technetwork/java/javase/downloads/jce-6-download-429243.html Java 7
* 无政策限制文件
* :http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download
* -432124.html 我的时java7,自己安装的。
* /Library/Java/JavaVirtualMachines/jdk1.7.0_71
* .jdk/Contents/Home/jre/lib/security目录下
* ,对应覆盖local_policy.jar和US_export_policy.jar两个文件。
*
* 切换到%JDK_Home%\jre\lib\security目录下,对应覆盖local_policy.jar和US_export_policy.
* jar两个文件。同时,你可能有必要在%JRE_Home%\lib\security目录下,也需要对应覆盖这两个文件。
*/
// BC实现:“私钥解密、公钥加密” , 对于:“私钥加密、公钥解密”有问题,因为Elgamal不支持
public static void BCElgamal() {
try {
// 加入对BouncyCastle支持
Security.addProvider(new BouncyCastleProvider());
// 1.初始化发送方密钥
AlgorithmParameterGenerator 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));
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
应用场景: