編輯:關於Android編程
上篇博文中我們講了Java中的對稱加密,還沒有看過的童鞋可以打開鏈接查看對稱加密,今天我們重點講一下Java中的非對稱加密。
對於非對稱加密,它需要兩個密鑰來進行加密和解密,分別為公鑰和私鑰,其相對於對稱加密而言安全性更高;在Java中的非對稱加密算法主要有DH算法和RSA算法。
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 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 keyMap = new HashMap<>();
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
/**
* 乙方根據甲方公鑰初始化並返回密鑰對
*
* @param key 甲方的公鑰
* @return 乙方的公鑰和私鑰
* @throws Exception
*/
public static Map 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 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 keyMap) {
DHPublicKey key = (DHPublicKey) keyMap.get(PUBLIC_KEY);
return key.getEncoded();
}
/**
* 從Map中獲取私鑰
*
* @param keyMap 存放公鑰和密鑰的Map
* @return 私鑰
*/
public static byte[] getPrivateKey(Map keyMap) {
DHPrivateKey key = (DHPrivateKey) keyMap.get(PRIVATE_KEY);
return key.getEncoded();
}
}
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 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 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 keyMap) {
return (RSAPublicKey) keyMap.get(PUBLIC_KEY);
}
/**
* 從Map集合中獲取私鑰
*
* @param keyMap 存儲公鑰和私鑰的map
* @return 返回私鑰
*/
public static RSAPrivateKey getPrivateKey(Map 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 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 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 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!
Android實現讀取相機(相冊)圖片並進行剪裁
我們先說一下思路,在android系統中就自帶了圖片剪切的應用,所以,我們只需要將我們獲取到的相片傳給圖片剪切應用,再將剪切好的相片返回到我們自己的界面顯示就ok了在開發
2、struct2開發action 的三種方法以及通配符、路徑匹配原則、常量
struct2 開發action 的三種方法1、繼承ActionSupportpublic class UserAction extends ActionSupport
Android 操作HTTP實現與服務器通信
本示例以Servlet為例,演示Android與Servlet的通信。眾所周知,Android與服務器通信通常采用HTTP通信方式和Socket通信方式,而HTTP通信方
在生成android版本時候出現的蛋疼問題Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1),
01-11 19:47:57.153: A/libc(27675): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1),