?? 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 + -