1⃣️前言
Rsa.java作为server,Client.java作为client端进行通信,先启动server,后启动client.
如果自己手动实现大数运算还有点困难,目前大数运算只实现了减法,乘法和作商和求余数,代码里面是调用了BigInteger类的,所以我的代码并没有实现大数运算,因为还需要用到其他的大数运算的其他算法,比如最重要的是那个求下一位可能是素数的函数,这个我暂时没有实现,因为遇到了一些bug。以后有空再来实现吧。
2⃣️client.java
package 实验3;
import javax.swing.*;
import java.awt.*;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.net.Socket;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Scanner;
public class Client extends JFrame {
private Socket s;
private JButton send;
private JTextField plainText;
private JLabel plainLabel;
private JPanel north,center,south;
private static LinkedHashMap<Character, Integer> cmap;
public Client(){
super("加密窗口🔐");
initMem();
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
private void initMem(){
try {
s=new Socket("127.0.0.1",30000);
} catch (IOException e) {
e.printStackTrace();
}
send=new JButton("发送");
plainText=new JTextField(20);
plainLabel=new JLabel("明文");
north=new JPanel();
center=new JPanel();
south=new JPanel();
north.add(plainLabel);
north.add(plainText);
south.add(send);
add(north,BorderLayout.NORTH);
add(center,BorderLayout.CENTER);
add(south,BorderLayout.SOUTH);
send.addActionListener(e->{
String iplain=plainText.getText().toLowerCase();
LinkedList<BigInteger> cipherList=getCipher(iplain);
ObjectOutputStream oos;
try {
oos=new ObjectOutputStream(s.getOutputStream());
oos.writeObject(cipherList);
oos.flush();
} catch (IOException e1) {
e1.printStackTrace();
}
});
}
/**
* a->00
* b->01
* 建立字母整数映射表
*/
private static void initMap() {
for (int i = 0; i < 26; i++) {
cmap.put((char) (i+'a'), i);
}
char[] c=new char[]{
'!','\"','#','$', '%','&' ,'\'','(',')' ,'*','+',',',
'-','.','/','0','1','2','3','4','5','6','7','8','9',' ','@','^',
'<','>','?',':',';','[',']','{','}','|','\\','~','`'
};
for (int i = 33; i < 33+c.length; i++) {
cmap.put(c[i-33],i);
}
}
static {
cmap = new LinkedHashMap<>();
initMap();
}
/**
* 暂时忽略明文是奇数个字符的情况
*
* @param s 明文
* @return 密文
*/
public static LinkedList<BigInteger> getCipher(String s) {
if (s.length()%2!=0){
s=s+" ";
}
LinkedList<BigInteger> res = new LinkedList<>();
for (int i = 0; i < s.length(); i += 2) {
String t = s.substring(i, i + 2);
int i1 = cmap.get(t.charAt(0)), i2 = cmap.get(t.charAt(1));
int i3 = i1 * 100 + i2;
res.addLast(Rsa.Quick_Power(new BigInteger(i3 + ""), Rsa.e, Rsa.n));
}
return res;
}
public static void main(String[] args) {
new Client();
}
}
3⃣️rsa.java
package 实验3;
import javax.swing.*;
import java.awt.*;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.math.BigInteger;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import static java.math.BigInteger.*;
public class Rsa extends JFrame {
static BigInteger p, fn;
static BigInteger e, n, q, a, d;//公钥
private static LinkedHashMap< Integer,Character> cmap;
private ServerSocket ss;
private Socket s;
private JLabel cipherL,cnt;
private JTextField cntF,ciF;
private JButton getJB;
private JPanel north;
private JPanel center;
private JPanel south;
static {
a = new BigInteger("3");//随便选了一个3
p=generateNum();
q=p.nextProbablePrime();
n = p.multiply(q);
fn = p.subtract(ONE).multiply(q.subtract(ONE));
e = fn.nextProbablePrime();
d = getInverseNum(e, fn);
cmap = new LinkedHashMap<>();
initMap();
}
/**
* 产生100位大素数
* @return
*/
private static BigInteger generateNum(){
BigInteger i=new BigInteger("100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
return i.nextProbablePrime();
}
public static StringBuilder getPlainText(LinkedList<BigInteger> list){
StringBuilder s=new StringBuilder();
for (var item : list)
{
BigInteger t=Quick_Power(item, d ,n );
int num= t.intValue();
char c1=cmap.get(num/100);//HelloWorld
char c2=cmap.get(num%100);
s.append(c1);
s.append(c2);
}
return s;
}
public static StringBuilder getCipher(LinkedList<BigInteger> list){
StringBuilder s=new StringBuilder();
for (var item : list)
{
s.append(item);
}
return s;
}
/**
* a->00
* b->01
* 建立字母整数映射表
*/
private static void initMap() {
for (int i = 0; i < 26; i++) {
cmap.put( i,(char) (i+'a'));
}
char[] c=new char[]{
'!','\"','#','$', '%','&' ,'\'','(',')' ,'*','+',',',
'-','.','/','0','1','2','3','4','5','6','7','8','9',' ','@','^',
'<','>','?',':',';','[',']','{','}','|','\\','~','`'
};
for (int i = 33; i < 33+c.length; i++) {
cmap.put(i, c[i-33]);
}
}
private static BigInteger generateE(BigInteger x){
return x.nextProbablePrime();
}
public static void main(String[] args) {
new Rsa();
}
public Rsa(){
super("解密窗口🔓");
try {
ss=new ServerSocket(30000);
s=ss.accept();
cipherL=new JLabel("密文");
cnt=new JLabel("明文");
cntF=new JTextField(30);
ciF=new JTextField(30);
getJB=new JButton("了无㊙️密,一键解密🔓");
north=new JPanel();
center=new JPanel();
south=new JPanel();
north.add(cnt);
north.add(cntF);
center.add(cipherL);
center.add(ciF);
south.add(getJB);
add(north,BorderLayout.NORTH);
add(center,BorderLayout.CENTER);
add(south,BorderLayout.SOUTH);
} catch (IOException e) {
e.printStackTrace();
}
getJB.addActionListener(e->{
try {
ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
LinkedList<BigInteger> list=(LinkedList<BigInteger>) ois.readObject();
StringBuilder ans=getPlainText(list);
StringBuilder cipher=getCipher(list);
ciF.setText(cipher.toString());
cntF.setText(ans.toString());
} catch (ClassNotFoundException c){
c.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
});
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
/**
* a*a^-1 = 1 mod f
*
* @param a
* @param f
* @return f模a的乘法逆元
*/
private static BigInteger getInverseNum(BigInteger a, BigInteger f) {
BigInteger l = f, r = a, i = ONE, count = ZERO;
LinkedHashMap<BigInteger, BigInteger> q = new LinkedHashMap<>(), b = new LinkedHashMap<>();
while (true) {
BigInteger div = l.divide(r), reNum = l.mod(r);
q.put(i, div);
count = count.add(ONE);
if (reNum.equals(ONE)) {
break;
}
l = r;
r = reNum;
i = i.add(ONE);
}
b.put(ONE.negate(), ZERO);
b.put(ZERO, ONE);
BigInteger j = ONE;
for (; j.compareTo(count) == -1 || j.compareTo(count) == 0; j = j.add(ONE)) {
b.put(j,//下面是-1乘以。。。
ONE.negate().multiply(b.get(j.subtract(ONE)))
.multiply(q.get(j)).add(b.get(j.subtract(new BigInteger("2")))));
}
BigInteger res = b.get(j.subtract(ONE));
while (res.compareTo(ZERO) == -1) {
res = res.add(f);
}
return res;
}
/**
* @param a 乘数1
* @param b 乘数2
* @param c 模数
* @return
*/
private static BigInteger Quick_Multiply(BigInteger a, BigInteger b, BigInteger c) //快速积(和快速幂差不多)
{
BigInteger ans = ZERO, res = new BigInteger(a + "");
while (b.compareTo(ZERO) == 1) {
// if(b%2!=0)
if (b.mod(new BigInteger("2")).compareTo(ZERO) != 0) {
ans = (ans.add(res)).mod(new BigInteger(c + ""));
}
res = (res.add(res)).mod(new BigInteger(c + ""));
// b>>=1;
b = b.shiftRight(1);
}
return ans;
}
/**
* 快速幂
*
* @param a 底数
* @param b 幂
* @param c 模数,作为参数传到Quick_Multiply
* @return
*/
public static BigInteger Quick_Power(BigInteger a, BigInteger b, BigInteger c) //快速幂
{
BigInteger ans = ONE, res = a;
while (b.compareTo(ZERO) == 1) {
if ((b.mod(new BigInteger("2")).compareTo(ZERO) != 0)) {
ans=ans.multiply(res).mod(c);
}
res=res.multiply(res).mod(c);
b = b.shiftRight(1);
System.out.println(b.bitCount());
}
return ans;
}
private static BigInteger gcd(BigInteger a,BigInteger b){
if (b.compareTo(ZERO)==0){
return a;
}else {
return gcd(b, a.mod(b));
}
}
}