上篇博文中我们讲了Java中的对称加密,还没有看过的童鞋可以打开链接查看对称加密,今天我们重点讲一下Java中的非对称加密。
对于非对称加密,它需要两个密钥来进行加密和解密,分别为公钥和私钥,其相对于对称加密而言安全性更高;在Java中的非对称加密算法主要有DH算法和RSA算法。
DH算法加密:
package com.example.asiatravel.learndes.dh_util; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; import javax.crypto.KeyAgreement; import javax.crypto.SecretKey; import javax.crypto.interfaces.DHPrivateKey; import javax.crypto.interfaces.DHPublicKey; import javax.crypto.spec.DHParameterSpec; /** * Created by kuangxiaoguo on 16/9/14. * * DH加密工具类 */ public class DHUtil { public static final String PUBLIC_KEY = "DHPublicKey"; public static final String PRIVATE_KEY = "DHPrivateKey"; /** * 甲方初始化并返回密钥 * * @return 甲方的公钥和私钥 * @throws Exception */ public static Map<String, Object> initKey() throws Exception { //初始化密钥对生成器 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH"); keyPairGenerator.initialize(1024);// 默认是1024, 516-1024且是64的倍数 //生成密钥对 KeyPair keyPair = keyPairGenerator.generateKeyPair(); //得到公钥和私钥 DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic(); DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate(); Map<String, Object> keyMap = new HashMap<>(); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; } /** * 乙方根据甲方公钥初始化并返回密钥对 * * @param key 甲方的公钥 * @return 乙方的公钥和私钥 * @throws Exception */ public static Map<String, Object> initKey(byte[] key) throws Exception { //将甲方公钥从字节数组转化为publicKey X509EncodedKeySpec keySpec = new X509EncodedKeySpec(key); //实例化密钥工厂 KeyFactory keyFactory = KeyFactory.getInstance("DH"); //产出甲方公钥 DHPublicKey dhPublicKey = (DHPublicKey) keyFactory.generatePublic(keySpec); //剖析甲方公钥获取其参数 DHParameterSpec dhParameterSpec = dhPublicKey.getParams(); //实例化密钥对生成器 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH"); //用甲方公钥初始化密钥生成器 keyPairGenerator.initialize(dhParameterSpec); //获取密钥对 KeyPair keyPair = keyPairGenerator.generateKeyPair(); //获取乙方公钥和私钥 DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic(); DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate(); //将乙方的公钥和私钥存入map集合中 Map<String, Object> keyMap = new HashMap<>(); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; } /** * 根据对方的公钥和自己的私钥生成本地密钥 * * @param publicKey 对方公钥 * @param privateKey 自己私钥 * @return 本地密钥 * @throws Exception */ public static byte[] getSecretKey(byte[] publicKey, byte[] privateKey) throws Exception { //实例化密钥工厂 KeyFactory keyFactory = KeyFactory.getInstance("DH"); //将公钥从字节数组转化为publicKey X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKey); PublicKey pubKey = keyFactory.generatePublic(publicKeySpec); //将私钥从字节数组转化为privateKey PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKey); PrivateKey priKey = keyFactory.generatePrivate(privateKeySpec); //根据以上公钥和私钥生成本地的密钥secretKey //实例化keyAgreement KeyAgreement keyAgreement = KeyAgreement.getInstance("DH"); //用自己的私钥初始化keyAgreement keyAgreement.init(priKey); //结合对方的公钥进行运算 keyAgreement.doPhase(pubKey, true); //开始生成本地密钥secretKey,密钥算法为对称加密算法 SecretKey secretKey = keyAgreement.generateSecret("AES");//DES 3DES AES return secretKey.getEncoded(); } /** * 从Map中获取公钥 * * @param keyMap 存放公钥和密钥的Map * @return 公钥 */ public static byte[] getPublicKey(Map<String, Object> keyMap) { DHPublicKey key = (DHPublicKey) keyMap.get(PUBLIC_KEY); return key.getEncoded(); } /** * 从Map中获取私钥 * * @param keyMap 存放公钥和密钥的Map * @return 私钥 */ public static byte[] getPrivateKey(Map<String, Object> keyMap) { DHPrivateKey key = (DHPrivateKey) keyMap.get(PRIVATE_KEY); return key.getEncoded(); } }
RSA算法加密:
package com.example.asiatravel.learndes.rsa_util; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.util.HashMap; import java.util.Map; import javax.crypto.Cipher; /** * Created by kuangxiaoguo on 16/9/14. * * RAS加密工具类 */ public class RSAUtil { public static final String PUBLIC_KEY = "RSAPublicKey"; public static final String PRIVATE_KEY = "RSAPrivateKey"; /** * 生成RSA公钥和私钥 * * @return RSA公钥和私钥的Map集合 * @throws Exception */ public static Map<String, Object> initKey() throws Exception { //初始化密钥生成器 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(1024); //获取密钥对 KeyPair keyPair = keyPairGenerator.generateKeyPair(); //获取公钥和私钥 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); //把公钥和私钥存入map集合 Map<String, Object> keyMap = new HashMap<>(); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; } /** * 使用公钥加密 * * @param data 需要加密的数据 * @param publicKey 公钥 * @return 加密后的字节数组 * @throws Exception */ public static byte[] encrypt(byte[] data, RSAPublicKey publicKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(data); } /** * 使用私钥解密 * * @param data 被公钥加密后的数据 * @param privateKey 解密用的私钥 * @return 解密后的数据的字节数组 * @throws Exception */ public static byte[] decrypt(byte[] data, RSAPrivateKey privateKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(data); } /** * 从Map集合中获取公钥 * * @param keyMap 存储公钥和私钥的map集合 * @return 返回公钥 */ public static RSAPublicKey getPublicKey(Map<String, Object> keyMap) { return (RSAPublicKey) keyMap.get(PUBLIC_KEY); } /** * 从Map集合中获取私钥 * * @param keyMap 存储公钥和私钥的map * @return 返回私钥 */ public static RSAPrivateKey getPrivateKey(Map<String, Object> keyMap) { return (RSAPrivateKey) keyMap.get(PRIVATE_KEY); } }
非对称加密的测试代码:
package com.example.asiatravel.learndes; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import com.example.asiatravel.learndes.dh_util.DHUtil; import com.example.asiatravel.learndes.rsa_util.RSAUtil; import com.example.asiatravel.learndes.util.ByteToHexUtil; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.util.Map; public class MainActivity extends AppCompatActivity { private static final String DATA = "asiatravel"; private static final String TAG = "TAG"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); try { testDH(); } catch (Exception e) { Log.e(TAG, "onCreate: " + e.getMessage()); } try { testRSA(); } catch (Exception e) { Log.e(TAG, "onCreate: " + e.getMessage()); } } /** * 测试RSA加密-->非对称加密 */ private void testRSA() throws Exception { Map<String, Object> keyMap = RSAUtil.initKey(); RSAPublicKey publicKey = RSAUtil.getPublicKey(keyMap); RSAPrivateKey privateKey = RSAUtil.getPrivateKey(keyMap); System.out.println("RSA publicKey: " + publicKey); System.out.println("RSA privateKey: " + privateKey); //加密后的数据 byte[] encryptResult = RSAUtil.encrypt(DATA.getBytes(), publicKey); System.out.println(DATA + " RSA 加密: " + ByteToHexUtil.fromByteToHex(encryptResult)); //解密后的数据 byte[] decryptResult = RSAUtil.decrypt(encryptResult, privateKey); System.out.println(DATA + " RSA 解密: " + new String(decryptResult)); } /** * 测试DH加密-->非对称加密 */ private void testDH() throws Exception { //甲方公钥 byte[] publicKeyA; //甲方私钥 byte[] privateKeyA; //甲方本地密钥 byte[] secretKeyA; //乙方公钥 byte[] publicKeyB; //乙方私钥 byte[] privateKeyB; //乙方本地密钥 byte[] secretKeyB; //初始化密钥并生成甲方密钥对 Map<String, Object> keyMapA = DHUtil.initKey(); publicKeyA = DHUtil.getPublicKey(keyMapA); privateKeyA = DHUtil.getPrivateKey(keyMapA); System.out.println("DH 甲方公钥: " + ByteToHexUtil.fromByteToHex(publicKeyA)); System.out.println("DH 甲方私钥: " + ByteToHexUtil.fromByteToHex(privateKeyA)); //乙方根据甲方公钥生成乙方密钥对 Map<String, Object> keyMapB = DHUtil.initKey(publicKeyA); publicKeyB = DHUtil.getPublicKey(keyMapB); privateKeyB = DHUtil.getPrivateKey(keyMapB); System.out.println("DH 乙方公钥: " + ByteToHexUtil.fromByteToHex(publicKeyB)); System.out.println("DH 乙方私钥: " + ByteToHexUtil.fromByteToHex(privateKeyB)); //对于甲方,根据乙方公钥和自己的私钥生成本地密钥 secretKeyA secretKeyA = DHUtil.getSecretKey(publicKeyB, privateKeyA); //对于乙方,根据其甲公钥和自己的私钥生成本地密钥 secretKeyB secretKeyB = DHUtil.getSecretKey(publicKeyA, privateKeyB); System.out.println("DH 甲方本地密钥: " + ByteToHexUtil.fromByteToHex(secretKeyA)); System.out.println("DH 乙方本地密钥: " + ByteToHexUtil.fromByteToHex(secretKeyB)); } }总结:非对称加密想对于对称加密来讲更加安全,其代码逻辑方面相对于对称加密来讲也更为复杂,所以大家需要理解着去记忆,另外注释我在代码里都写上了,不明白的童鞋可以在下面留言。
最后,附上github源码地址:点击查看非对称加密源码,希望大家多多star!
作者:kuangxiaoguo0123 发表于2016/9/15 20:20:05 原文链接
阅读:89 评论:0 查看评论