一、非对称加密算法
DH(Diffie-Hellman)密钥交换算法
RSA-基于因子分解(应用范围最广)
ElGamal-基于离散对数
ECC(Elliptical Curve Cryptography)-椭圆曲线加密
非对称加密算法为高级加密算法,提供公钥、私钥双保险。
二、非对称加密算法-DH(密钥交换)
1、理论知识
对称加密带来的困扰:
密钥管理复杂;
密钥传递过程复杂(如何安全地传递密钥成为比较重要的一个环节);
非对称加密算法的起源算法,通过构建本地密钥来解决密钥来解决对称密钥传递的问题,对双方来说密钥是一样的(对称)。
密钥长度 | 默认 | 工作模式 | 填充方式 | 实现方 |
---|---|---|---|---|
512~1024(64倍数) | 1024 | 无 | 无 | JDK |
2、JDK 实现:
/**
* java.security.NoSuchAlgorithmException: Unsupported secret key algorithm: DES
* 由于JDK版本不同,在Java 8 update 161版本以后就会出现此问题,根本原因还是DH密钥长度至少为512位,而DES算法密钥没有这么长,密钥长度不一致引起的。
* 解决方法:
* 配置JVM的系统变量:-Djdk.crypto.KeyAgreement.legacyKDF=true
*/
public static void jdkDH() throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidAlgorithmParameterException, InvalidKeyException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException {
String src = "test source";
// [sender]1、初始化发送方密钥
KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance("DH");
senderKeyPairGenerator.initialize(512);
KeyPair senderKeyPair = senderKeyPairGenerator.generateKeyPair();
// 发送方公钥,需要把该公钥发送给接收方(网络、文件...)
byte[] senderPublicKeyEnc = senderKeyPair.getPublic().getEncoded();
// [receiver]2、接收方密钥构建
// 接收方拿到发送方发送的公钥
KeyFactory receiverKeyFactory = KeyFactory.getInstance("DH");
X509EncodedKeySpec receiverX509EncodedKeySpec = new X509EncodedKeySpec(senderPublicKeyEnc);
PublicKey senderPublicKeyTemp = receiverKeyFactory.generatePublic(receiverX509EncodedKeySpec);
// 初始化接收方密钥
DHParameterSpec dhParameterSpec = ((DHPublicKey)senderPublicKeyTemp).getParams();
KeyPairGenerator receiverKeyPairGenerator = KeyPairGenerator.getInstance("DH");
receiverKeyPairGenerator.initialize(dhParameterSpec);
KeyPair receiverKeyPair = receiverKeyPairGenerator.generateKeyPair();
// 接受方公钥,需要把该公钥发送给发送方(网络、文件...)
byte[] receiverPublicKeyEnc = receiverKeyPair.getPublic().getEncoded();
// 使用我的密钥和你的公钥生成密钥
KeyAgreement receiverKeyAgreement = KeyAgreement.getInstance("DH");
receiverKeyAgreement.init(receiverKeyPair.getPrivate());
receiverKeyAgreement.doPhase(senderPublicKeyTemp, true);
SecretKey receiverDESKey = receiverKeyAgreement.generateSecret("DES");
// [sender]3、发送方密钥构建
// 发送方拿到接收方返回的公钥
KeyFactory senderKeyFactory = KeyFactory.getInstance("DH");
X509EncodedKeySpec senderX509EncodedKeySpec = new X509EncodedKeySpec(receiverPublicKeyEnc);
PublicKey receiverPublicKeyTemp = senderKeyFactory.generatePublic(senderX509EncodedKeySpec);
// 使用我的密钥和你的公钥生成密钥
KeyAgreement senderKeyAgreement = KeyAgreement.getInstance("DH");
senderKeyAgreement.init(senderKeyPair.getPrivate());
senderKeyAgreement.doPhase(receiverPublicKeyTemp, true);
SecretKey senderDESKey = senderKeyAgreement.generateSecret("DES");
// ////////////////////////////////////////////////////////////////////////////////////////////
// DH算法的本质是构建本地密钥来解决密钥来解决对称密钥传递的问题
// 对双方来说密钥是一样的(对称)
// 对比验证双方各自在本地构建密钥是否一致
if (Objects.equals(receiverDESKey, senderDESKey)) {
System.out.println("双方密钥相同");
}
// ////////////////////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////////////////////
// 后续通信采用各自在本地构建的密钥进行对称机密的机制
// [sender]发送方加密,反之亦然
Cipher enCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
enCipher.init(Cipher.ENCRYPT_MODE, senderDESKey);
byte[] encode = enCipher.doFinal(src.getBytes());
// Hex 编码
String encodeHex = Hex.encodeHexString(encode);
System.out.println(enCipher.getProvider() + "- des encrypt(Hex):" + encodeHex);
// Base64 编码
String encodeBase64 = Base64.encodeBase64String(encode);
System.out.println(enCipher.getProvider() + "- des encrypt(Base64):" + encodeBase64);
// [receiver]接收方解密,反之亦然
Cipher deCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
deCipher.init(Cipher.DECRYPT_MODE, receiverDESKey);
byte[] decode = deCipher.doFinal(encode);
// byte[] decode = deCipher.doFinal(Hex.decodeHex(encodeHex));
// byte[] decode = deCipher.doFinal(Base64.decodeBase64(encodeBase64));
System.out.println(deCipher.getProvider() + "- des decrypt:" + new String(decode));
// ////////////////////////////////////////////////////////////////////////////////////////////
}
三、非对称加密算法-RSA
1、理论知识
唯一广泛接受并实现;
数据加密&数字签名;
公钥加密、私钥解密;
私钥加密、公钥解密;
密钥长度 | 默认 | 工作模式 | 填充方式 | 实现方 |
---|---|---|---|---|
512~65536(64倍数) | 1024 | ECB | NoPadding、PKCS1Padding、OAEPWITHMD5AndMGF1Padding、OAEPWITHSHA1AndMGF1Padding、OAEPWITHSHA256AndMGF1Padding、OAEPWITHSHA384AndMGF1Padding、OAEPWITHSHA512AndMGF1Padding | JDK |
同上 | 2048 | NONE | NoPadding、PKCS1Padding、OAEPWITHMD5AndMGF1Padding、OAEPWITHSHA1AndMGF1Padding、OAEPWITHSHA1AndMGF224Padding、OAEPWITHSHA256AndMGF1Padding、OAEPWITHSHA384AndMGF1Padding、OAEPWITHSHA512AndMGF1Padding、ISO9796-1Padding | BC |
2、JDK 实现:
public static void jdkRSA() throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
String src = "test source";
// 1、初始化密钥
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(512);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
System.out.println("Public Key:" + Base64.encodeBase64String(publicKey.getEncoded()));
System.out.println("Private Key:" + Base64.encodeBase64String(privateKey.getEncoded()));
// 2、RSA私钥加密、公钥解密——加密
PKCS8EncodedKeySpec priEnPKCS8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded());
KeyFactory priEnKeyFactory = KeyFactory.getInstance("RSA");
PrivateKey enPrivateKey = priEnKeyFactory.generatePrivate(priEnPKCS8EncodedKeySpec);
Cipher priEnCipher = Cipher.getInstance("RSA");
priEnCipher.init(Cipher.ENCRYPT_MODE, enPrivateKey);
byte[] priEncode = priEnCipher.doFinal(src.getBytes());
// Hex 编码
String priEncodeHex = Hex.encodeHexString(priEncode);
System.out.println(priEnCipher.getProvider() + "- RSA私钥加密、公钥解密——加密(Hex):" + priEncodeHex);
// Base64 编码
String priEncodeBase64 = Base64.encodeBase64String(priEncode);
System.out.println(priEnCipher.getProvider() + "- RSA私钥加密、公钥解密——加密(Base64):" + priEncodeBase64);
// 3、RSA私钥加密、公钥解密——解密
X509EncodedKeySpec pubDeX509EncodedKeySpec = new X509EncodedKeySpec(publicKey.getEncoded());
KeyFactory pubDekeyFactory = KeyFactory.getInstance("RSA");
PublicKey dePublicKey = pubDekeyFactory.generatePublic(pubDeX509EncodedKeySpec);
Cipher pubDeCipher = Cipher.getInstance("RSA");
pubDeCipher.init(Cipher.DECRYPT_MODE, dePublicKey);
byte[] pubDecode = pubDeCipher.doFinal(priEncode);
// byte[] pubDecode = deCipher.doFinal(Hex.decodeHex(priEncodeHex));
// byte[] pubDecode = deCipher.doFinal(Base64.decodeBase64(priEncodeBase64));
System.out.println(pubDeCipher.getProvider() + "- RSA私钥加密、公钥解密——解密:" + new String(pubDecode));
// 4、RSA公钥加密、私钥解密——加密
X509EncodedKeySpec pubEnX509EncodedKeySpec = new X509EncodedKeySpec(publicKey.getEncoded());
KeyFactory pubEnKeyFactory = KeyFactory.getInstance("RSA");
PublicKey enPublicKey = pubEnKeyFactory.generatePublic(pubEnX509EncodedKeySpec);
Cipher pubEnCipher = Cipher.getInstance("RSA");
pubEnCipher.init(Cipher.ENCRYPT_MODE, enPublicKey);
byte[] pubEncode = pubEnCipher.doFinal(src.getBytes());
// Hex 编码
String pubEncodeHex = Hex.encodeHexString(pubEncode);
System.out.println(pubEnCipher.getProvider() + "- RSA公钥加密、私钥解密——加密(Hex):" + pubEncodeHex);
// Base64 编码
String pubEncodeBase64 = Base64.encodeBase64String(pubEncode);
System.out.println(pubEnCipher.getProvider() + "- RSA公钥加密、私钥解密——加密(Base64):" + pubEncodeBase64);
// 5、RSA公钥加密、私钥解密——解密
PKCS8EncodedKeySpec priDePKCS8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded());
KeyFactory priDeKeyFactory = KeyFactory.getInstance("RSA");
PrivateKey dePrivateKey = priDeKeyFactory.generatePrivate(priDePKCS8EncodedKeySpec);
Cipher priDeCipher = Cipher.getInstance("RSA");
priDeCipher.init(Cipher.DECRYPT_MODE, dePrivateKey);
byte[] priDecode = priDeCipher.doFinal(pubEncode);
// byte[] priDecode = deCipher.doFinal(Hex.decodeHex(pubEncodeHex));
// byte[] priDecode = deCipher.doFinal(Base64.decodeBase64(pubEncodeBase64));
System.out.println(priDeCipher.getProvider() + "- RSA公钥加密、私钥解密——解密:" + new String(priDecode));
}
四、非对称加密算法-ElGamal
1、理论知识
公钥加密算法,不支持私钥加密;
Bouncy Castle 提供实现;
密钥长度 | 默认 | 工作模式 | 填充方式 | 实现方 |
---|---|---|---|---|
160~16384(8倍数) | 1024 | ECB、NONE | NoPadding、PKCS1Padding、OAEPWITHMD5AndMGF1Padding、OAEPWITHSHA1AndMGF1Padding、OAEPWITHSHA224AndMGF1Padding、OAEPWITHSHA256AndMGF1Padding、OAEPWITHSHA384AndMGF1Padding、OAEPWITHSHA512AndMGF1Padding、ISO9796-1Padding | BC |
2、BC实现:
public static void bcElGamal() throws NoSuchAlgorithmException, InvalidParameterSpecException, InvalidAlgorithmParameterException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
String src = "test source";
// 设置 BC 的提供Provider
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 publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
System.out.println("Public Key:" + Base64.encodeBase64String(publicKey.getEncoded()));
System.out.println("Private Key:" + Base64.encodeBase64String(privateKey.getEncoded()));
// 4、ElGamal公钥加密、私钥解密——加密
X509EncodedKeySpec pubEnX509EncodedKeySpec = new X509EncodedKeySpec(publicKey.getEncoded());
KeyFactory pubEnKeyFactory = KeyFactory.getInstance("ElGamal");
PublicKey enPublicKey = pubEnKeyFactory.generatePublic(pubEnX509EncodedKeySpec);
Cipher pubEnCipher = Cipher.getInstance("ElGamal");
pubEnCipher.init(Cipher.ENCRYPT_MODE, enPublicKey);
byte[] pubEncode = pubEnCipher.doFinal(src.getBytes());
// Hex 编码
String pubEncodeHex = Hex.encodeHexString(pubEncode);
System.out.println(pubEnCipher.getProvider() + "- ElGamal公钥加密、私钥解密——加密(Hex):" + pubEncodeHex);
// Base64 编码
String pubEncodeBase64 = Base64.encodeBase64String(pubEncode);
System.out.println(pubEnCipher.getProvider() + "- ElGamal公钥加密、私钥解密——加密(Base64):" + pubEncodeBase64);
// 5、ElGamal公钥加密、私钥解密——解密
PKCS8EncodedKeySpec priDePKCS8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded());
KeyFactory priDeKeyFactory = KeyFactory.getInstance("ElGamal");
PrivateKey dePrivateKey = priDeKeyFactory.generatePrivate(priDePKCS8EncodedKeySpec);
Cipher priDeCipher = Cipher.getInstance("ElGamal");
priDeCipher.init(Cipher.DECRYPT_MODE, dePrivateKey);
byte[] priDecode = priDeCipher.doFinal(pubEncode);
// byte[] priDecode = deCipher.doFinal(Hex.decodeHex(pubEncodeHex));
// byte[] priDecode = deCipher.doFinal(Base64.decodeBase64(pubEncodeBase64));
System.out.println(priDeCipher.getProvider() + "- ElGamal公钥加密、私钥解密——解密:" + new String(priDecode));
}
主要知识点来源于慕课慕课网上 moocer老师 提供的 java 加密系列教程。 原创不易,如需转载,请标明出处!
最后修改:2019-10-14 10:33:01
© 著作权归作者所有
如果觉得我的文章对你有用,请随意赞赏
扫一扫支付

发表评论