📄 rsa.java
字号:
/**
* 本程序实现对文件进行非对称RSA加密
* 版权所有@计算机科学学院 何文
* 注意:在点击按钮“随机产生后”如果n的值小于65535,或者大于131072时,需要再次点击按钮,直到n值符合条件
* 加密后产生的文件为源文件名相同但后缀为encrypt的文件,文件与源文件在同一个目录下
* 解密后产生的文件为源文件名相同但后缀为decrypt的文件,文件与源文件在同一个目录下
*/
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.util.*;
import java.lang.Double;
import java.awt.Color;
import javax.swing.BorderFactory;
import java.math.*;
public class RSA extends JFrame
{
public static final int WIDTH = 550;
public static final int HEIGHT = 200;
keyPanel pp;
Container c;
//主函数
public static void main(String args[])
{
new RSA();
}
//构造函数
public RSA()
{
this.setSize(WIDTH,HEIGHT);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension screenSize = tk.getScreenSize();
this.setLocation((screenSize.width - WIDTH)/2,
(screenSize.height - HEIGHT)/2);
this.setTitle("文件加密器(TriDES)");
c = this.getContentPane();
c.setLayout( new FlowLayout());
final FilePanel fp = new FilePanel("文件选择");
c.add(fp);
pp = new keyPanel();
c.add(pp);
JButton jbE = new JButton("加密");
c.add(jbE);
jbE.addActionListener(new ActionListener(){ //侦听函数
public void actionPerformed(ActionEvent event)
{
System.out.println((int)RSAcrypt(8831,70871,-213));
System.out.println(RSAcrypt(40271,70871,-2035));
try{
File f = new File(fp.getFileName());
int length = (int)f.length();
int[] data = new int[length/2];
short[] OutPut = new short[length/2];
DataInputStream in = new DataInputStream(new FileInputStream(f));
DataOutputStream out = new DataOutputStream(new FileOutputStream(f+".encrypt"));
for(int i=0;i<length/2;i++)
{
data[i]=in.readUnsignedShort();
}
OutPut = crypt(Integer.valueOf(pp.fileText3.getText()).intValue(),Integer.valueOf(pp.fileText4.getText()).intValue(),data);
for(int i=0;i<length/2;i++)
{
out.writeShort((int)OutPut[i]);
}
out.flush();
out.close();
in.close();
}catch(IOException IOE){}
JOptionPane.showMessageDialog( c,"加密成功!");
}
});
JButton jbD = new JButton("解密");
c.add(jbD);
jbD.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
try{
File f = new File(fp.getFileName());
int length = (int)f.length();
int[] data = new int[length/2];
short[] OutPut = new short[length/2];
DataInputStream in = new DataInputStream(new FileInputStream(f));
DataOutputStream out = new DataOutputStream(new FileOutputStream(f+".decrypt"));
for(int i=0;i<length/2;i++)
{
data[i]=in.readUnsignedShort();
}
OutPut = crypt(Integer.valueOf(pp.fileText1.getText()).intValue(),Integer.valueOf(pp.fileText4.getText()).intValue(),data);
for(int i=0;i<length/2;i++)
{
out.writeShort((int)OutPut[i]);
}
out.flush();
out.close();
in.close();
}catch(IOException IOE){}
JOptionPane.showMessageDialog( c,"解密成功!");
}
});
this.setVisible(true);
}
/**
* 对单个数字进行加密的函数
* @param d
* @param n
* @param c
* 返回加密后的数据
*/
int RSAcrypt(int d,int n, int c)
{
int i;
for(i=1;i<=d;i++)
{
if(Math.pow(c, i)>n)break;
}
int k = d/i;
int x = d%i;
double y = (Math.pow(c, x))%n;
Double z;
while(k>0)
{
y = ((Math.pow(c, i))%n*y)%n;
k--;
}
Double qq = new Double(y);
return (short)qq.intValue();
}
/**
* 加密函数,或者解密函数
* 当输入私钥时进行加密,当输入公钥时进行解密
* 参数d,n分别为私钥的d,n或者公钥的e,n
* 加密或者解密的数据为data数组
*/
short[] crypt(int d,int n,int[] data)
{
int in;
short ctr[] = new short[data.length];
for(int i=0;i<data.length;i++)
{
ctr[i] = (short)RSAcrypt(d,n,data[i]);
}
return ctr;
}
}
/**
* 文件选择面板类,继承自JPanel
*/
class FilePanel extends JPanel{
FilePanel(String str){
JLabel label = new JLabel(str);
JTextField fileText = new JTextField(35);
JButton chooseButton = new JButton("浏览...");
this.add(label);
this.add(fileText);
this.add(chooseButton);
clickAction ca = new clickAction(this);
chooseButton.addActionListener(ca);
}
public String getFileName(){
JTextField jtf = (JTextField)this.getComponent(1);
return jtf.getText();
}
private class clickAction implements ActionListener{
clickAction(Component c){
cmpt = c;
}
public void actionPerformed(ActionEvent event){
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new File("."));
int ret = chooser.showOpenDialog(cmpt);
if(ret==JFileChooser.APPROVE_OPTION){
JPanel jp = (JPanel)cmpt;
JTextField jtf = (JTextField)jp.getComponent(1);
jtf.setText(chooser.getSelectedFile().getPath());
}
}
private Component cmpt;
}
}
/**
* 密钥获可视化类,继承自JPanel
* 它显示由类key产生的随机公钥和私钥
*/
class keyPanel extends JPanel
{
JTextField fileText1,fileText2,fileText3,fileText4;
keyPanel(){
JLabel label = new JLabel("公钥");
label.setBorder(BorderFactory.createLineBorder(Color.blue));
JLabel labe2 = new JLabel("e");
JLabel labe3 = new JLabel("n");
JLabel labe4 = new JLabel("私钥");
labe4.setBorder(BorderFactory.createLineBorder(Color.blue));
JLabel labe5 = new JLabel("d");
JLabel labe6 = new JLabel("n");
JButton b1 = new JButton("随机产生");
fileText1 = new JTextField(7);
fileText2 = new JTextField(7);
fileText3 = new JTextField(7);
fileText4 = new JTextField(7);
this.add(label);
this.add(labe2);
this.add(fileText1);
this.add(labe3);
this.add(fileText2);
this.add(labe4);
this.add(labe5);
this.add(fileText3);
this.add(labe6);
this.add(fileText4);
this.add(b1);
b1.addActionListener(new ActionListener(){ //侦听函数
public void actionPerformed(ActionEvent event)
{
key k = new key();
fileText1.setText(String.valueOf(k.e));
fileText2.setText(String.valueOf(k.n));
fileText3.setText(String.valueOf(k.d));
fileText4.setText(String.valueOf(k.n));
}
});
}
}
/**
* 产生密钥对的类
* p()产生一个随机素数
* p,q分别为随机素数
* n=p*q
* e为小于(p-1)*(q-1)且与(p-1)*(q-1)互为素数的一个数
* d为e关于(p-1)*(q-1)的乘法逆元
* 公钥为e,n;私钥为d,n
*/
class key
{
static int p;
static int q;
static int n;
static int e;
static int d;
protected int howb(int M, int N) //求最大公约数
{
if(N<0||M<0)
{
return -1;
}
if(N==0)
{
return M;
}
return howb(N,M%N);
}
public static boolean isSushu(int x){//定义一个判断一个数是否是素数的函数
if(x<2) return false;
if( x==2)return true;
for(int i=2;i<= Math.sqrt(x);i++)
if(x%i==0) return false;
return true;
}
protected int p()//产生随机素数
{
int p = new Random().nextInt(1024); //产生一个随机数
while(!isSushu(p))p = new Random().nextInt(1024);
return p;
}
key()
{
p = p(); //产生大于3的素数1
q = p(); //产生大于3的素数2
n = p*q;
//while(n>131072 || n<=65536)n = p*q;
e = (new Random().nextInt((p-1)*(q-1)))/3;//随机产生一个e值
while(e<(p-1)*(q-1))
{
e++; //求e的值
if(howb(e,(p-1)*(q-1))==1)break; //假如e与(p-1)*(q-1)互为素数,则结束循环
}
ExtendedEuclid ExtendedEuclid= new ExtendedEuclid();
d = ExtendedEuclid.Extended((p-1)*(q-1),e);
}
}
/*扩展欧几里德类
* 即a1关于a的乘法逆元
*/
class ExtendedEuclid
{
int x1 = 1;
int x2 = 0;
int y1 = 0;
int y2 = 1;
int t1,t2,t3;
int q;
ExtendedEuclid(){}//构造函数为空
public int Extended(int a,int a1)//求a1关于a的乘法逆元
{
int yy = a;
while(a1 != 1)
{
q = a / a1 ;
t1 = x1;
t2 = x2;
t3 = a;
x1 = y1 ;
x2 = y2 ;
a = a1 ;
y1 = t1 - q*x1;
y2 = t2 - q*x2;
a1 = t3 - q*a;
if(a1 == 0) return -1;
}
if(y2%yy>=0)return y2%yy;
else return yy+y2%yy;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -