在公钥体制中,用非对称算法来加密,运行的效率比对称加密都比较慢。这次在我的《网络安全》课上要实现这个RSA加密算法,RSA是用到逆运算,要用到很多很大数据的幂乘,很容易就产生溢出。在网上搜索不到这个JAVA的源码,有也是要用另外的JAVA包的,所以就自己用JAVA写了这个算法,学JAVA刚两个多月,代码有点糙,希望大家能看懂。
import java.io. * ;
import java.util.Random;
/**
*Rsa非对称加密的实现
*@author Shaojun Huang
*@version 1.0
*/
public class Rsa
{
private int keyn; //公私钥相同部分
private int publickeye; //公钥
private int privatekeyd; //私钥
/**
*Rsa构造器,初始化对象
*/
public Rsa()
{
int randomprimep = 0; //随机产生素数
int randomprimeq = 0; //随机产生素数
int eulern = 0; //公私钥相同部分的欧拉数
Random rand = new Random();
randomprimep = 10 + rand.nextInt(200);
while (ifPrime(randomprimep)) //判断是否为素数
{
randomprimep = 10 + rand.nextInt(200);
}
randomprimeq = 10 + rand.nextInt(200);
while (ifPrime(randomprimeq)) //判断是否为素数
{
randomprimeq = 10 + rand.nextInt(200);
}
keyn = randomprimep * randomprimeq;
eulern = (randomprimep - 1) * (randomprimeq - 1);
randomprimep = randomprimeq = 0; //销毁两个随机素数
publickeye = 10 + rand.nextInt(200); //随机产生公钥
while (relativePrime(publickeye,eulern)) //判断随机公钥与公私钥相同部分的欧拉数是否为相对素数
{
publickeye = 10 + rand.nextInt(200);
}
boolean mark = true; //用简捷方法求私钥,从模逆运算原始定义出发
int k = 0;
while (mark)
{
k++;
if((k * eulern + 1)%publickeye == 0)
mark = false;
}
privatekeyd = (k * eulern + 1)/publickeye; //计算私钥
System.out.println("公钥为:(" + publickeye + "," + keyn + ")");
System.out.println("私钥为:(" + privatekeyd + "," + keyn + ")");
}
/**
*判断一个整型数据是否为素数
*@param number 待判断数据
*@return true --不是素数,false -- 是素数
*/
public boolean ifPrime(int number)
{
boolean mark = false;
for (int i = 2;i < number/2 ;i++ )
{
if (number%i == 0)
{
mark = true;
break;
}
}
return mark;
}
/**
*判断两个整数数据是否为素数
*@param e 整型数据
*@param n 整型数据
*@return true -- 不是否为素数,fasle -- 是互为素数
*/
public boolean relativePrime(int e,int n)
{
boolean mark = false;
for (int i = 2;i <= n ;i++ )
{
if (n%i == 0)
if (e%i == 0)
{
mark = true;
break;
}
}
return mark;
}
/**
*模n的大数幂乘快速运算
*@param a 底数
*@param b 指数
*@param n 模数
*@return 大数幂乘结果
*/
public int fastPowerMultiplication(int a,int b,int n)
{
int c = 1;
while (b != 0)
{
while (b%2 == 0)
{
b = b/2;
a = ( a * a )%n;
}
b = b - 1;
c = ( c * a )%n;
}
return c;
}
/**
*求一个整型数据的欧拉数
*@param number 待求欧拉数的数据
*@return 欧拉数
*/
public int getPrivateKeyexp(int number)
{
int eulernumber = 0;
for (int i = 2;i < number ;i++ )
{
if(relativePrime(i,number) == false)
{
System.out.println("相互素数:" + i + "," + number);
eulernumber++;
}
}
System.out.println(eulernumber);
return eulernumber + 1;
}
/**
*对明文加密
*@param source 明文源地址
*@param destination 密文目的地
*/
public void dataEncryption(String source,String destination)
{
try
{
RandomAccessFile rafr = new RandomAccessFile(source,"r");
RandomAccessFile rafw = new RandomAccessFile(destination,"rw");
String understandtxts = "";
String passwordtxts = "";
char [] eachchar;
int charint = 0;
boolean mark = false;
try
{
long filelength = rafr.length();
long pos = 0;
while (pos != filelength)
{
understandtxts = rafr.readLine();
eachchar = understandtxts.toCharArray();
for (int i = 0 ;i < eachchar.length ;i++ )
{
charint = (int)eachchar[i];
if (charint > 127 || charint < 10)
{
System.out.println("加密失败!原文中包含不能加密的字符。");
mark = true;
break;
}
}
if (mark)
{
break;
}
pos = rafr.getFilePointer();
}
rafr.seek(0);
pos = 0;
if (!mark)
{
System.out.println("从文件读入明文:");
while (pos != filelength)
{
System.out.println(rafr.readLine());
pos = rafr.getFilePointer();
}
rafr.seek(0);
pos = 0;
System.out.println("明文加密后密文:");
while (true)
{
understandtxts = rafr.readLine();
eachchar = understandtxts.toCharArray();
for (int i = 0;i < eachchar.length ;i++ )
{
passwordtxts = passwordtxts + fastPowerMultiplication((int)eachchar[i],publickeye,keyn) + getRandomString();
}
System.out.println(passwordtxts);
rafw.writeBytes(passwordtxts);
pos = rafr.getFilePointer();
if (pos == filelength)
{
break;
}
passwordtxts = "";
rafw.writeChar(' ');
}
}
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
finally
{
rafr.close();
rafw.close();
}
}
catch (IOException ex)
{
ex.printStackTrace(System.out);
}
}
/**
*随机生成1~5个随机大写字母
*/
public String getRandomString()
{
Random rand = new Random();
String randstr = "";
int number = 1 + rand.nextInt(5);
int charint = 65 + rand.nextInt(26);
for (int i = 0;i < number ;i++ )
{
randstr = randstr + (char)charint;
charint = 65 + rand.nextInt(26);
}
return randstr;
}
/**
*对密文解密
*@param source 密文源地址
*@param destination 明文目的址
*/
public void dataDeciphering(String source,String destination)
{
try
{
RandomAccessFile rafr = new RandomAccessFile(source,"r");
RandomAccessFile rafw = new RandomAccessFile(destination,"rw");
String understandtxts = "";
String passwordtxts = "";
char [] eachchar;
int intchar = 0;
boolean mark = false;
try
{
long filelength = rafr.length();
long pos = 0;
int j = 0;
System.out.println("密文解密后明文:");
while (true)
{
passwordtxts = rafr.readLine();
eachchar = passwordtxts.toCharArray();
for (int i = 0;i < eachchar.length ;i++ )
{
if (Character.isDigit(eachchar[i]))
{
intchar = 10*intchar + Integer.valueOf(String.valueOf(eachchar[i]));
}
else
{
j = i - 1;
if (Character.isDigit(eachchar[j]) && !Character.isDigit(eachchar[i]))
{
understandtxts = understandtxts + (char)fastPowerMultiplication(intchar,privatekeyd,keyn);
intchar = 0;
}
}
}
System.out.println(understandtxts);
rafw.writeBytes(understandtxts);
pos = rafr.getFilePointer();
if (pos == filelength)
{
break;
}
System.out.println(' ');
understandtxts = "";
}
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
finally
{
rafr.close();
rafw.close();
}
}
catch (IOException ex)
{
ex.printStackTrace(System.out);
}
}
public static void main(String[] args)
{
Rsa rsa = new Rsa();
rsa.dataEncryption("b.txt","c.txt");
rsa.dataDeciphering("c.txt","d.txt");
}
}
可惜在运算中文时,数据产生了溢出,不能对中文加密,也添加了检测不能加密字符的功能。这个是实现单表体制的加密,也就是在明文中相同的字符加密出来的密文也是一样的,这样的密文就很容易被概论法破译密文。解决办法就是可以采用双表体制的加密办法,一个字符的密文要收到它前一个字符的影响,也就在加密的时候明文字符要加上前一个字符加密的结果一个去进行模运算,解密的时候就做相应的逆运算可以解决。