1、基于DH(Diffie-Hellman)密钥交换算法的非对称加密:
1.1、实现过程:
1.2、代码实现如下:
import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import java.security.*;
import java.security.spec.X509EncodedKeySpec;
import java.util.Objects;
/**
* 基于 DH 算法的非对称加密工具类
*
* @Author young
*/
public class DhUtils1 {
static final String DH = "DH";
static final String DES = "DES";
static final String STR = "Hello young";
public static void jdkDH() {
try {
// 1.发送方构建公钥私钥
KeyPair senderKeyPair = generateSenderPublicKey();
// 2.发送方发布公钥
byte[] senderPublicKeyBytes = senderKeyPair.getPublic().getEncoded();
// 3.接收方构建公钥私钥->接收方通过发送方公钥构建公钥私钥
KeyPair receiverKeyPair = generateReceiverPublicKey(senderPublicKeyBytes);
// 4.接收方发布公钥
byte[] receiverPublicKeyBytes = receiverKeyPair.getPublic().getEncoded();
// 5.接收方构建对称加密秘钥->依据发送方公钥和接收方公钥私钥构建
SecretKey receiverDESKey = generateSecretKey(receiverKeyPair, senderPublicKeyBytes);
// 6.发送方构建对称加密秘钥->依据接收方公钥和发送方公钥私钥构建
SecretKey senderDESKey = generateSecretKey(senderKeyPair, receiverPublicKeyBytes);
if (Objects.equals(receiverDESKey, senderDESKey)) {
System.out.println("双方密钥相同");
}
// 7.发送方加密
Cipher cipher = Cipher.getInstance(DES);
cipher.init(Cipher.ENCRYPT_MODE, senderDESKey);
byte[] result = cipher.doFinal(STR.getBytes());
System.out.println("JDK DH Encrypt: " + Base64.encodeBase64(result));
// 8.接收方解密
cipher.init(Cipher.DECRYPT_MODE, receiverDESKey);
result = cipher.doFinal(result);
System.out.println("JDK DH Decrypt: " + new String(result));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 发送方构建密钥
*
* @return 构建完的公钥私钥
* @throws NoSuchAlgorithmException
*/
private static KeyPair generateSenderPublicKey() throws NoSuchAlgorithmException {
KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance(DH);
senderKeyPairGenerator.initialize(512);
return senderKeyPairGenerator.generateKeyPair();
}
/**
* 依据发送方公钥构建接收方公钥私钥
*
* @param senderPublicKey 发送方公钥
* @return 接收方公钥私钥
* @throws Exception
*/
private static KeyPair generateReceiverPublicKey(byte[] senderPublicKey) throws Exception {
KeyFactory receiverKeyFactory = KeyFactory.getInstance(DH);
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(senderPublicKey);
PublicKey receiverPublicKey = receiverKeyFactory.generatePublic(x509EncodedKeySpec);
DHParameterSpec dhParameterSpec = ((DHPublicKey) receiverPublicKey).getParams();
KeyPairGenerator receiverKeyPairGenerator = KeyPairGenerator.getInstance(DH);
receiverKeyPairGenerator.initialize(dhParameterSpec);
return receiverKeyPairGenerator.generateKeyPair();
}
/**
* 使用自己的公钥私钥与对方的公钥构建 对称密钥
*
* @param keyPair 自己的公钥私钥
* @param publicKeyBytes 对方的公钥
* @return 本地对称加密密钥
* @throws Exception
*/
private static SecretKey generateSecretKey(KeyPair keyPair, byte[] publicKeyBytes) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance(DH);
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyBytes);
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
KeyAgreement keyAgreement = KeyAgreement.getInstance(DH);
keyAgreement.init(keyPair.getPrivate());
keyAgreement.doPhase(publicKey, true);
return keyAgreement.generateSecret(DES);
}
}a
在这里插入代码片
运行结果:
2、RSA算法:
2.1实现原理:
RSA公开密钥密码体制的原理是:根据数论,寻求两个大素数比较简单,而将它们的乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。支持公钥加密、私钥解密和私钥加密、公钥解密两种方式。
2.2、代码实现:
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
/**
* 基于 RSA 算法的非对称加密工具类
*/
public class RsaUtils {
static final String RSA = "RSA";
static final String STR = "Hello young";
public static void jdkRSA() {
try {
// 构建密钥对
KeyPair keyPair = generateSenderPublicKey();
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
// 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(STR.getBytes());
System.out.println("私钥加密、公钥解密——加密结果:" +Base64.encodeBase64(result));
// 2.私钥加密、公钥解密——解密
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));
// 3.公钥加密、私钥解密——加密
x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
keyFactory = KeyFactory.getInstance(RSA);
publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
result = cipher.doFinal(STR.getBytes());
System.out.println("公钥加密、私钥解密——加密结果:" + Base64.encodeBase64(result));
// 4.公钥加密、私钥解密——解密
pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
keyFactory = KeyFactory.getInstance(RSA);
privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
result = cipher.doFinal(result);
System.out.println("公钥加密、私钥解密——解密结果:" + new String(result));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 构建密钥对
*
* @return 构建完的公钥私钥
* @throws NoSuchAlgorithmException
*/
private static KeyPair generateSenderPublicKey() throws NoSuchAlgorithmException {
KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance(RSA);
senderKeyPairGenerator.initialize(512);
return senderKeyPairGenerator.generateKeyPair();
}
}
运行结果如下:
由于JDK版本不兼容的原因,可能出现如下错误:
java.security.NoSuchAlgorithmException: Unsupported secret key algorithm: DES
错误由于, JDK 版本不同,在 Java 8 update 161 版本以后就会出现此问题,根本原因还是 DH 密钥长度至少为 512 位,而 DES 算法密钥没有这么长,密钥长度不一致引起的。
解决方法:配置JVM的系统变量:-Djdk.crypto.KeyAgreement.legacyKDF=true
3、基于离散对数的EIGamal算法:
3.1、实现过程:只支持公钥加密、私钥解密
3.2、代码实现:
/**
* 基于 ElGamal 算法的非对称加密工具类
*
*
*/
public class ElGamalUtils {
static final String ELGAMAL = "ElGamal";
static final String STR = "Hello young";
public static void bcElGamal() {
Security.addProvider(new BouncyCastleProvider());
try {
AlgorithmParameterGenerator algorithmParameterGenerator = AlgorithmParameterGenerator.getInstance(ELGAMAL);
System.out.println(algorithmParameterGenerator.getProvider());
algorithmParameterGenerator.init(256);
AlgorithmParameters algorithmParameters = algorithmParameterGenerator.generateParameters();
DHParameterSpec dhParameterSpec = algorithmParameters.getParameterSpec(DHParameterSpec.class);
// 构建密钥对
KeyPair keyPair = generateSenderPublicKey(dhParameterSpec);
PublicKey elGamalPublicKey = keyPair.getPublic();
PrivateKey elGamalPrivateKey = keyPair.getPrivate();
// 公钥加密、私钥解密——加密
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(elGamalPublicKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance(ELGAMAL);
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] result = cipher.doFinal(STR.getBytes());
System.out.println("公钥加密、私钥解密——加密:" + Base64.encodeBase64(result));
// 公钥加密、私钥解密——解密
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded());
keyFactory = KeyFactory.getInstance(ELGAMAL);
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
result = cipher.doFinal(result);
System.out.println("公钥加密、私钥解密——解密:" + new String(result));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 构建密钥对
*
* @return 构建完的公钥私钥
* @throws NoSuchAlgorithmException
*/
private static KeyPair generateSenderPublicKey(DHParameterSpec dhParameterSpec) throws Exception {
KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance(ELGAMAL);
senderKeyPairGenerator.initialize(dhParameterSpec, new SecureRandom());
return senderKeyPairGenerator.generateKeyPair();
}
}
运行结果: