加密算法Java

1、加密算法的分類

對稱加密算法:使用一個密鑰,即可加密,也可解密。

非對稱加密算法:使用一對密鑰,公鑰只能加密不能解密,只有私鑰可以用來解密。運算速度不及對稱加密算法。

常見的加密算法:

算法名 分類 是否冪等 目前是否破解 破解年限
RSA-155(512bit) 非對稱加密 已被破解 1999年耗費5個月
RSA-786(786bit) 非對稱加密 已被破解 2009年
RSA-1024(1024bit) 非對稱加密 未被破解 預計這幾年
RSA-2048(2048bit) 非對稱加密 未被破解
RSA系列 非對稱加密 量子計算機
DES 對稱加密 已被破解 1990年短時間內
AES 對稱加密 未被破解

2、RSA 算法演示

需要選擇兩個質數:5 和 11

計算 n : 5 * 11 = 55

n = 11, 0111 因此 這個密鑰是 6 bit

計算 φ(n) = (5 - 1) * (11 - 1) = 40

選擇一個數 e 當作公鑰因子,需要滿足 1 < e < φ(n), 並且 e 和 φ(n) 互質:e = 13

得到公鑰 :(n = 35, e = 13)

計算私鑰因子 d,需要滿足 (e * d) mod φ(n) = 1。計算得出 d = 37

得到私鑰:(n = 55, d = 37)

加密公式:f(x) = (x ^ e) mod n

解密公式:f(x) = (x ^ d) mod n

對 20 進行加密,結果爲:(20 ^ 13) mod 55 = 25

對 25 進行解密,結果爲:(25 ^ 37) mod 55 = 20

public static void main(String[] args) {
		rsa(20, 55, 13); // 加密, 25
		rsa(25, 55, 37); // 解密, 20
	}
	
	/**
	 * 
	 * @param x 待加密或解密的值
	 * @param n 
	 * @param e 密鑰因子
	 */
	public static void rsa(int x, int n, int e) {
		int sum = x;
		for (int i = 1; i < e; i++) {
			sum = sum * x;
			if (sum > n)
				sum = sum % n;
		}
		System.out.println(sum);
	}

3、使用工具生成 RSA 密鑰

使用 openSSL 工具生成私鑰

openssl genrsa -out rsa_pri.key 1024

使用 openssl 根據私鑰生成公鑰

openssl rsa -in rsa_pri.key -pubout -out rsa_pub.key

生成的私鑰編碼爲 pkcs12, Java 不能直接使用,需要轉成 pkcs8 格式

openssl pkcs8 -topk8 -inform PEM -in rsa_pri.key -outform PEM -nocrypt

4、Java加解密

package zh.utils;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

import javax.crypto.Cipher;



public class RSA {
	

	public static void main(String[] args) throws Exception {
		String priKeyStr = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANg9tNBlqb0rIAKXzkFOZ8+Uk3qOLaqXpqBSeiV/YOiAlWe5lI7U7RAiV/vHabsm0jRWz+UdsSgMOfUaJmAjAMvdqPEua3mJo5rGNkeBqop42bj0XLGDcyd562HwV1yaZDGQrAREqLrsDIcSc3R9ULl+9R/m9MFpwK6mr5IkG6xBAgMBAAECgYEAl+kBlUVWMSaSnj+3Dfnew91Endw0CJvw2sAWPzF1CuEKFIwy6QR8ZdE6rg4xIODs2wgBlJt/UPsF3EI6o17ztviac/pCvu09au1eW1f2aHGRvLSHTVVpA6V7FcZvZsk0J+3dGWhv0VxnVrUGW2r/BBwouxoe4R3ZL/Mvi3YxM2ECQQD/UHrgAa9wATMiuBcmcPTZSDHjr9DbddTs9XmHpAGYSrODLpWBHfYX8yGMGQfEpaJFIRccScankF+OoRsfhDYvAkEA2NJdXpy3SKxePLrcHWI9XnpFxg4QDIfK11fiy7DspHJGNxkgnuz6OqxZ71l88z0tlU2Q8D6793dzGdaw0GMYjwJBANs8bIb2a4OuRA7ILXjg/h+mktCFJL+Oyyw/DgCfoI75dnRrCA47gBrIuEHpLHZ8FH9wDrxHzcINg0Cirvu9OBkCQGZUEgDfEZlY0Dj1L4EmpjP6nQd2B5kCVXcAYWcknuqVjBHg6AZZbVdXlDJkF5ZsnyDBtM/Nq8SFOWtOabBPtH0CQQCzVp0/Awzo7CYYXnQcK6qro8x9eDSB1eZ0DVuth36xh2CC2OKi2gjMiQBrs2se3W/TUaTiW546rCwTDTvSHqjs";
		String pubKeyStr = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYPbTQZam9KyACl85BTmfPlJN6ji2ql6agUnolf2DogJVnuZSO1O0QIlf7x2m7JtI0Vs/lHbEoDDn1GiZgIwDL3ajxLmt5iaOaxjZHgaqKeNm49Fyxg3Mneeth8FdcmmQxkKwERKi67AyHEnN0fVC5fvUf5vTBacCupq+SJBusQQIDAQAB";
		String data = "this is rsa";
		// 加載公鑰
		RSAPublicKey pubKey = loadPublicKey(pubKeyStr);
		// 加載私鑰
		PrivateKey priKey = loadPrivateKey(priKeyStr);
		
		// 使用公鑰加密
		String sign = sign(pubKey, data);
		System.out.println("加密結果爲:" + sign);
		
		String decrypt = decrypt(priKey, sign);
		System.out.println("解密結果爲:" + decrypt);
	}
	
    /**
     * 公鑰加密過程
     *
     */
    public static String sign(RSAPublicKey publicKey, String data)
            throws Exception {
    	Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] output = cipher.doFinal(data.getBytes());
        return Base64ByteToString(output);
    }
    
    //私鑰解密
  	public static String decrypt(PrivateKey privateKey, String data) throws Exception{
  		Cipher cipher = Cipher.getInstance("RSA");
  		cipher.init(Cipher.DECRYPT_MODE, privateKey);
  		byte[] bytes = cipher.doFinal(StringToBase64Byte(data));
  		return new String(bytes);
  	}

  	/**
     * 從字符串中加載私鑰
     */
  	public static PrivateKey loadPrivateKey(String priStr) throws Exception{
		byte[] keyBytes = StringToBase64Byte(priStr);
		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
		return privateKey;
	}


    /**
     * 從字符串中加載公鑰
     */
    public static RSAPublicKey loadPublicKey(String publicKeyStr)
            throws Exception {
    	byte[] buffer = StringToBase64Byte(publicKeyStr);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
        return (RSAPublicKey) keyFactory.generatePublic(keySpec);
    }
    

    /**
     * 將byte[] 轉換成字符串
     */
    public static String byte2Hex(byte[] srcBytes) {
        StringBuilder hexRetSB = new StringBuilder();
        for (byte b : srcBytes) {
            String hexString = Integer.toHexString(0x00ff & b);
            hexRetSB.append(hexString.length() == 1 ? 0 : "").append(hexString);
        }
        return hexRetSB.toString();
    }


    /**
     * 將字符串轉爲 Base64 格式的 byte
     */
    public static byte[] StringToBase64Byte(String str) {
    	return Base64.getDecoder().decode(str);
    }
    
    /**
     * 將 Base64 格式的 byte 轉爲字符串
     */
    public static String Base64ByteToString(byte[] bt) {
    	return Base64.getEncoder().encodeToString(bt);
    }
    
	
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章