慕课网学习笔记
参考:java加密算法
加密密钥分为公钥和私钥。可以使用公钥加密私钥解密,也可以使用私钥加密公钥解密。非对称加密算法主要有:DH(Diffie-Hellman)密钥交换算法、RSA(基于因子分解)、Elgamal(基于离散对数)、ECC(Elliptical Curve Cryptography,椭圆曲线加密)。
如何安全地传送密钥是对称加密算法的症结所在。密钥交换算法是通过构建本地密钥来解决对称加密算法中的密钥传递的问题的。
实现该算法的步骤和所需要的类如下:
具体实现:
package dh;
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 JavaDH {
private static String src = "面向对象编程,object-oriented!@#*5"; // 需要加密的原始字符串
public static void main(String[] args) throws Exception {
System.out.println("初始字符串:" + src);
jdkDH();
}
/** JDK实现密钥交换算法 */
public static void jdkDH() throws Exception{
//1.初始化发送方密钥
KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance("dh");
senderKeyPairGenerator.initialize(512);//密钥长度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();
//3.密钥构建
KeyAgreement receiverkeyAgreement = KeyAgreement.getInstance("dh");
receiverkeyAgreement.init(receiverPrivateKey);
receiverkeyAgreement.doPhase(receiverPublicKey, true);
SecretKey receiverDesKey = receiverkeyAgreement.generateSecret("des");
byte[] receiverPublicKeyEnc = receiverKeyPair.getPublic().getEncoded();
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(senderDesKey,receiverDesKey)) {
System.out.println("双方密钥相同");
}
//4.加密
Cipher cipher = Cipher.getInstance("des");
cipher.init(Cipher.ENCRYPT_MODE, senderDesKey);
byte[] result = cipher.doFinal(src.getBytes());
System.out.println("密钥交换算法加密:" + Base64.encodeBase64String(result));
//5.解密
cipher.init(cipher.DECRYPT_MODE, receiverDesKey);
result = cipher.doFinal(result);
System.out.println("密钥交换算法解密:" + new String(result));
}
}
在RSA算法中公钥的长度远远小于私钥的长度。以下是其java实现:
package rsa;
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 JavaRSA {
private static String src = "面向对象编程,object-oriented!@#*5"; // 需要加密的原始字符串
public static void main(String[] args) throws Exception {
System.out.println("初始字符串:" + src);
jdkRSA();
}
public static void jdkRSA() throws Exception{
//1.初始化密钥
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(512);//密钥长度为64的整数倍,最大是65536
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
System.out.println("RSA公钥:" + Base64.encodeBase64String(rsaPublicKey.getEncoded()));
System.out.println("RSA私钥:" + Base64.encodeBase64String(rsaPrivateKey.getEncoded()));
//2.1私钥加密,公钥解密【加密】
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("JDK RSA私钥加密:" + Base64.encodeBase64String(result));
//2.2私钥加密,公钥解密【解密】
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
cipher.init(Cipher.DECRYPT_MODE, publicKey);
result = cipher.doFinal(result);
System.out.println("JDK RSA公钥解密:" + new String(result));
//3.1公钥加密,私钥解密【加密】
x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
keyFactory = KeyFactory.getInstance("RSA");
publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
result = cipher.doFinal(src.getBytes());
System.out.println("JDK RSA公钥加密:" + Base64.encodeBase64String(result));
//3.2公约加密,私钥解密【解密】
pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
keyFactory = KeyFactory.getInstance("RSA");
privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
result = cipher.doFinal(result);
System.out.println("JDK RSA私钥解密:" + new String(result));
}
}
RSA有两种模式公钥加密私钥解密和私钥加密公钥解密两种模式,其序列图如下:
和RSA不同的是它只提供公钥加密,它依靠BouncyCastle实现。
package elgamal;
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;
/**
* 非对称加密算法——ELGamal算法
* 对于:“Illegal key size or default parameters”异常,是因为美国的出口限制,Sun通过权限文件(local_policy.jar、US_export_policy.jar)做了相应限制。
* Java 7 无政策限制文件:http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html,
* 下载后得到UnlimitedJCEPolicyJDK7.zip,解压替换%JAVA_HOME%/jre/lib/security的两个文件即可
* @author gaopengfei
*
*/
public class JavaELGamal {
private static String src = "object-oriented!@#*5"; // 需要加密的原始字符串
public static void main(String[] args) throws Exception {
System.out.println("初始字符串:" + src);
bouncyCastleELGamal();
}
/**
* Bouncy Castle实现ELGamal,这种算法和RSA算法的区别是只能公钥加密,私钥解密
* */
private static void bouncyCastleELGamal() throws Exception{
Security.addProvider(new BouncyCastleProvider());//加入对Bouncy Castle的支持
//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("ELGamal公钥:" + Base64.encodeBase64String(elGamalPublicKey.getEncoded()));
System.out.println("ELGamal私钥:" + Base64.encodeBase64String(elGamalPrivateKey.getEncoded()));
//2.加密【公钥加密】
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(elGamalPublicKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("ELGamal");
elGamalPublicKey = (PublicKey) keyFactory.generatePublic(x509EncodedKeySpec);
Cipher cipher = Cipher.getInstance("ELGamal","BC");
cipher.init(Cipher.ENCRYPT_MODE, elGamalPublicKey);
byte[] result = cipher.doFinal(src.getBytes());
System.out.println("ELGamal公钥加密:" + Base64.encodeBase64String(result));
//3.解密【私钥解密】
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded());
keyFactory = KeyFactory.getInstance("ELGamal");
elGamalPrivateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
cipher.init(Cipher.DECRYPT_MODE, elGamalPrivateKey);
result = cipher.doFinal(result);
System.out.println("ELGamal私钥解密:" + new String(result));
// //加密【私钥加密】
// pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded());
// keyFactory = KeyFactory.getInstance("ELGamal");
// elGamalPrivateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
// cipher.init(Cipher.ENCRYPT_MODE, elGamalPrivateKey);
// result = cipher.doFinal(src.getBytes());
// System.out.println("ELGamal私钥加密:" + Base64.encodeBase64String(result));
//
// //解密【公钥解密】
// x509EncodedKeySpec = new X509EncodedKeySpec(elGamalPublicKey.getEncoded());
// keyFactory = KeyFactory.getInstance("ELGamal");
// elGamalPublicKey = keyFactory.generatePublic(x509EncodedKeySpec);
// cipher.init(Cipher.DECRYPT_MODE, elGamalPublicKey);
// result = cipher.doFinal(result);
// System.out.println("ELGamal解密:" + new String(result));
}
}