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,这是为什么呢?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值