网络信息安全学习笔记,手动实现rsa加密解密

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));
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dareu_4523

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值