Java開發環境配置以及RSA加密算法的實現

RSA算法的Java實現

在Java實現該算法前我們先完成Java開發環境的配置,筆者選擇的是JDK1.8版本,開發環境用Eclipse

開發環境配置

  • JDK安裝
  • Eclipse安裝

JDK安裝
(1)JDK下載鏈接,進入鏈接後找到以下所示界面:
在這裏插入圖片描述
選擇最後一列Windows x64位的下載

x86適用於32位操作系統,x64適用於64位以及32位操作系統

下載完成並放置於C盤中:
在這裏插入圖片描述
(2)配置環境變量

配置JAVA_HOME,Path,CLASSPATH

  • JAVA_HOME
    右鍵點擊文件夾中“此電腦”選項,選擇“屬性”,選擇其中的“高級系統設置”,
    在這裏插入圖片描述
    出現如圖所示
    在這裏插入圖片描述
    點擊環境變量選擇系統變量新建,配置如下:在這裏插入圖片描述
    變量名填:JAVA_HOME
    變量值:填JDK的安裝目錄,及如圖所示在這裏插入圖片描述
    PS:點擊最上邊一欄即可得到JDK安裝目錄,然後複製該地址到變量值即可
  • Path
    同配置JAVA_HOME操作一樣,不過變量值不一樣
    Path的值: %JAVA_HOME%\bin

%JAVA_HOME%\bin是Windows操作系統用來尋找可執行文件的路徑,當然在我們的JDK目錄下的jre中也有bin文件,其中也有部分執行文件,這個配不配置基本不影響的,如果需要,將Path設置爲%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin即可

在這裏插入圖片描述

  • CLASSPATH
    同上述環境變量的配置一樣
    CLASSPATH的值爲: .;%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\lib\dt.jar

CLASSPATH的路徑告訴類裝載器到哪裏去尋找第三方提供的類和用戶定義的類
dt.jar:運行環境類庫,主要是Swing包
tools.jar:工具類庫

在這裏插入圖片描述

到此爲止,JDK的配置即完成。查看是否配置成功:
打開cmd輸入java –version以及java ,javac命令無異常即代表成功
在這裏插入圖片描述

Eclipse安裝
下載鏈接
如正常下載軟件一樣,下載並安裝即可使用
在這裏插入圖片描述

RSA的算法原理

我簡單介紹一下RSA算法的基本原理
RSA算法基於大整數因子分解困難性問題

  1. 首先選擇兩個互異的大素數pq(保密),計算n=p*q(公開),βn=(p-1)*(q-1)(保密)
  2. 選擇一個隨機整數 e (0<e<βn)(公開),滿足 gcd(e,βn)=1。計算選擇一個隨機整數 e (0<e<βn)(公開),滿足 gcd(e,βn)=1
  3. 計算d= e^-1 mod βn(保密)
  4. 確定: 公鑰KU={ e,n},私鑰KR={d,p,q},或KR={d,n}
  5. 加密:已知明文:M 計算密文:C=(M^e)mod n
  6. 解密:已知密文:C 和私鑰 KR={d,n} 計算明文:M=C^d mod n

密鑰生成時,如果要求 n 很大,攻擊者要將其成功地分解爲 p乘以q是困難的,這就是著名的大整數因子分解性問題,這保證了攻擊者不能得出 βn=(p-1)*(q-1),因此即使知道公鑰{ e,n},也不能通過解密算法將私鑰{d,n}推導出來。 --來自《應用密碼學》

算法實現:

Main類:

package RSAtest;

import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;

public class Main {

	public static void main(String[] args) throws Exception {
		HashMap<String, Object> map=RSAUtils.getKeys();
		RSAPublicKey publicKey=(RSAPublicKey)map.get("public");
		RSAPrivateKey privateKey=(RSAPrivateKey) map.get("private");
		
		//得到公開的N(PS:N=p*q,p和q是保密的
		String modulus=publicKey.getModulus().toString();
		
		//得到公開的E(PS:E是公鑰中中公開的隨機整數
		String public_exponent=publicKey.getPublicExponent().toString();
		//得到私鑰D
		String private_exponent=privateKey.getPrivateExponent().toString();
		
		String ming="128";
		
		RSAPublicKey pubKey=RSAUtils.getPublicKey(modulus, public_exponent);
		
		RSAPrivateKey priKey=RSAUtils.getPrivateKey(modulus, private_exponent);
		
		String mi=RSAUtils.encrytByPublicKey(ming, pubKey);
		System.out.println(mi);
		
		ming=RSAUtils.decryptByPrivateKey(mi, priKey);
		System.err.println(ming);
		
	}
}	      

RSAUtils類;

package RSAtest;

import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.HashMap;

import javax.crypto.Cipher;

public class RSAUtils {
	public static HashMap<String,Object>getKeys() throws NoSuchAlgorithmException{
		HashMap<String,Object>map=new HashMap<String,Object>();
		//調用產生RSA算法
		KeyPairGenerator KeyPairGen=KeyPairGenerator.getInstance("RSA");
		//設置產生RSA算法的密鑰長度
		KeyPairGen.initialize(Integer.parseInt("1024"));
		//生成密鑰對
		KeyPair keyPair=KeyPairGen.generateKeyPair();
		//獲取公鑰
		RSAPublicKey publicKey=(RSAPublicKey) keyPair.getPublic();
		//獲取私鑰
		RSAPrivateKey privateKey=(RSAPrivateKey) keyPair.getPrivate();
		map.put("public", publicKey);
		map.put("private", privateKey);
		return map;
	}
	
	public static RSAPublicKey getPublicKey(String modulus,String exponent) throws Exception{
		BigInteger b1=new BigInteger(modulus);
		BigInteger b2=new BigInteger(exponent);
		KeyFactory keyFactory=KeyFactory.getInstance("RSA");
		RSAPublicKeySpec keySpec=new RSAPublicKeySpec(b1, b2);
		return (RSAPublicKey) keyFactory.generatePublic(keySpec);
	}
	
	public static RSAPrivateKey getPrivateKey(String modulus,String exponent) throws Exception{
		BigInteger b1=new BigInteger(modulus);
		BigInteger b2=new BigInteger(exponent);
		KeyFactory keyFactory=KeyFactory.getInstance("RSA");
		RSAPrivateKeySpec keySpec=new RSAPrivateKeySpec(b1, b2);
		return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
	}
	
	public static String encrytByPublicKey(String data,RSAPublicKey publicKey) throws Exception{
		Cipher cipher=Cipher.getInstance("RSA");
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
		int key_len=publicKey.getModulus().bitLength();
		String []datas =splitString(data,key_len-11);
		String mi="";
		for(String s:datas) {
			mi+=bcd2Str(cipher.doFinal(s.getBytes()));
		}
		return mi;
	}
	
	public static String decryptByPrivateKey(String data,RSAPrivateKey privateKey) throws Exception{
		Cipher cipher=Cipher.getInstance("RSA");
		cipher.init(Cipher.DECRYPT_MODE, privateKey);
		int key_len=privateKey.getModulus().bitLength();
		byte []bytes=data.getBytes();
		byte []bcd=ASCII_TO_BCD(bytes,bytes.length);
		System.err.println(bcd.length);
		String ming="";
		byte[][] arrays =splitArray(bcd,key_len);
		for(byte[]arr:arrays) {
			ming+=new String(cipher.doFinal(arr));
		}
		return ming;
	}
	
	public static byte[] ASCII_TO_BCD(byte[] ascii,int asc_len) {
		byte[] bcd=new byte[asc_len/2];
		int j=0;
		for(int i=0;i<(asc_len+1)/2;i++) {
			bcd[i]=asc_to_bcd(ascii[j++]);
			bcd[i]=(byte)(((j>=asc_len)?0x00:asc_to_bcd(ascii[j++]))+(bcd[i]<<4));
		}
		return bcd;
	}
	
	public static byte asc_to_bcd(byte asc) {
		byte bcd;
		if((asc>='0')&&(asc<='9'))
			bcd=(byte)(asc-'0');
		else if((asc>='A')&&(asc<='F'))
			bcd=(byte)(asc-'A'+10);
		else if((asc>='a')&&(asc<='f'))
			bcd=(byte)(asc-'a'+10);
		else
			bcd=(byte)(asc-48);
		return bcd;
	}
	
	public static String bcd2Str(byte[] bytes) {
		char temp[]=new char[bytes.length*2],val;
		
		for(int i=0;i<bytes.length;i++) {
			val=(char)(((bytes[i]&0xf0)>>4)&0xf0);
			temp[i*2]=(char)(val>9?val+'A'-10:val+'0');
			
			val=(char)(bytes[i]&0x0f);
			temp[i*2+1]=(char)(val>9?val+'A'-10:val+'0');
		}
		return new String(temp);
	}
	
	public static String[] splitString(String string,int len) {
		int x=string.length()/len;
		int y=string.length()%len;
		int z=0;
		if(y!=0) {
			z=1;
		}
		String[] strings=new String[x+z];
		String str="";
		for(int i=0;i<x+z;i++) {
			if(i==x+z-1&&y!=0) {
				str=string.substring(i*len, i*len+y);
			}else {
				str=string.substring(i*len,i*len+len);
			}
			strings[i]=str;
		}
		return strings;
	}
	
	public static byte[][] splitArray(byte[] data,int len){
		int x=data.length/len;
		int y=data.length%len;
		int z=0;
		if(y!=0) {
			z=1;
		}
		byte[][] arrays=new byte[x+z][];
		byte[] arr;
		for(int i=0;i<x+z;i++) {
			arr=new byte[len];
			if(i==x+z-1&&y!=0) {
				System.arraycopy(data, i*len, arr, 0, y);
			}else {
				System.arraycopy(data, i*len, arr, 0, len);
			}
			arrays[i]=arr;
		}
		return arrays;
	}
}

代碼參考來源:https://blog.csdn.net/centralperk/article/details/8558678

運行結果演示:
在這裏插入圖片描述
代碼運行的問題在於不管怎麼修改明文,解密後的明文輸出都是128,這是爲什麼呢?

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