精华内容
下载资源
问答
  • rsa算法java
    千次阅读
    2021-04-27 11:53:23

    1、RSAUtils

     

    package rsa;
    
    
    import javax.crypto.Cipher;
    import java.io.ByteArrayOutputStream;
    import java.security.*;
    import java.security.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import java.util.ArrayList;
    import java.util.Base64;
    import java.util.List;
    
    /**
     * @ClassName: RsaUtils
     * @Description: TODO
     * @Author: zhānghào
     * @Date: 2021/4/25 3:29 下午
     * @Version: v1.0
     **/
    public class RSAUtils {
    
        // 加密算法
        private final static String ALGORITHM_RSA = "RSA";
    
        /**
         * 直接生成公钥、私钥对象
         *
         * @param modulus
         *
         * @throws NoSuchAlgorithmException
         *
         */
        public static List<Key> getRSAKeyObject(int modulus) throws NoSuchAlgorithmException{
    
            List<Key> keyList = new ArrayList<>(2);
            // 创建RSA密钥生成器
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM_RSA);
            // 设置密钥的大小,此处是RSA算法的模长 = 最大加密数据的大小
            keyPairGen.initialize(modulus);
            KeyPair keyPair = keyPairGen.generateKeyPair();
            // keyPair.getPublic() 生成的是RSAPublic的是咧
            keyList.add(keyPair.getPublic());
            // keyPair.getPrivate() 生成的是RSAPrivateKey的实例
            keyList.add(keyPair.getPrivate());
            return keyList;
        }
    
        /**
         * 生成公钥、私钥的字符串
         * 方便传输
         *
         * @param modulus 模长
         * @return
         * @throws NoSuchAlgorithmException
         */
        public static List<String> getRSAKeyString(int modulus) throws NoSuchAlgorithmException{
    
            List<String> keyList = new ArrayList<>(2);
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM_RSA);
            keyPairGen.initialize(modulus);
            KeyPair keyPair = keyPairGen.generateKeyPair();
            String publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
            String privateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
            keyList.add(publicKey);
            keyList.add(privateKey);
            return keyList;
        }
    
        // Java中RSAPublicKeySpec、X509EncodedKeySpec支持生成RSA公钥
        // 此处使用X509EncodedKeySpec生成
        public static RSAPublicKey getPublicKey(String publicKey) throws Exception {
    
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
            byte[] keyBytes = Base64.getDecoder().decode(publicKey);
            X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
            return (RSAPublicKey) keyFactory.generatePublic(spec);
        }
    
        // Java中只有RSAPrivateKeySpec、PKCS8EncodedKeySpec支持生成RSA私钥
        // 此处使用PKCS8EncodedKeySpec生成
        public static RSAPrivateKey getPrivateKey(String privateKey) throws Exception {
    
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
            byte[] keyBytes = Base64.getDecoder().decode(privateKey);
            PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
            return (RSAPrivateKey) keyFactory.generatePrivate(spec);
        }
    
        /**
         * 公钥加密
         *
         * @param data
         * @param publicKey
         * @return
         * @throws Exception
         */
        public static String encryptByPublicKey(String data, RSAPublicKey publicKey)
                throws Exception {
            Cipher cipher = Cipher.getInstance(ALGORITHM_RSA);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            // 模长n转换成字节数
            int modulusSize = publicKey.getModulus().bitLength() / 8;
            // PKCS Padding长度为11字节,所以实际要加密的数据不能要 - 11byte
            int maxSingleSize = modulusSize - 11;
            // 切分字节数组,每段不大于maxSingleSize
            byte[][] dataArray = splitArray(data.getBytes(), maxSingleSize);
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            // 分组加密,并将加密后的内容写入输出字节流
            for (byte[] s : dataArray) {
                out.write(cipher.doFinal(s));
            }
            // 使用Base64将字节数组转换String类型
            return Base64.getEncoder().encodeToString(out.toByteArray());
        }
    
        /**
         * 私钥解密
         *
         * @param data
         * @param privateKey
         * @return
         * @throws Exception
         */
        public static String decryptByPrivateKey(String data, RSAPrivateKey privateKey)
                throws Exception {
            Cipher cipher = Cipher.getInstance(ALGORITHM_RSA);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            // RSA加密算法的模长 n
            int modulusSize = privateKey.getModulus().bitLength() / 8;
            byte[] dataBytes = data.getBytes();
            // 之前加密的时候做了转码,此处需要使用Base64进行解码
            byte[] decodeData = Base64.getDecoder().decode(dataBytes);
            // 切分字节数组,每段不大于modulusSize
            byte[][] splitArrays = splitArray(decodeData, modulusSize);
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            for(byte[] arr : splitArrays){
                out.write(cipher.doFinal(arr));
            }
            return new String(out.toByteArray());
        }
    
        /**
         * 按指定长度切分数组
         *
         * @param data
         * @param len 单个字节数组长度
         * @return
         */
        private static byte[][] splitArray(byte[] data,int len){
    
            int dataLen = data.length;
            if (dataLen <= len) {
                return new byte[][]{data};
            }
            byte[][] result = new byte[(dataLen-1)/len + 1][];
            int resultLen = result.length;
            for (int i = 0; i < resultLen; i++) {
                if (i == resultLen - 1) {
                    int slen = dataLen - len * i;
                    byte[] single = new byte[slen];
                    System.arraycopy(data, len * i, single, 0, slen);
                    result[i] = single;
                    break;
                }
                byte[] single = new byte[len];
                System.arraycopy(data, len * i, single, 0, len);
                result[i] = single;
            }
            return result;
        }
    
    
    }
    

     

    2、RSATest

    package rsa;
    
    import java.security.Key;
    import java.security.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    import java.util.List;
    
    /**
     * @ClassName: RSATest
     * @Description: TODO
     * @Author: zhānghào
     * @Date: 2021/4/25 3:41 下午
     * @Version: v1.0
     **/
    public class RSATest {
    
        public static void main(String[] args) throws Exception {
    
            // 使用公钥、私钥对象加解密
            List<Key> keyList = RSAUtils.getRSAKeyObject(1024);
            RSAPublicKey puk = (RSAPublicKey) keyList.get(0);
            RSAPrivateKey prk = (RSAPrivateKey) keyList.get(1);
            String message = "referrer:[http://www.example.com/start.html](http://www.example.com/start.htmluser_agent: Mozilla/4.08 [en] (Win98; I ;Nav)";
            String encryptedMsg = RSAUtils.encryptByPublicKey(message, puk);
            String decryptedMsg = RSAUtils.decryptByPrivateKey(encryptedMsg, prk);
            System.out.println("object key ! message ==  decryptedMsg ? " + message.equals(decryptedMsg));
    
            // 使用字符串生成公钥、私钥完成加解密
            List<String> keyStringList = RSAUtils.getRSAKeyString(1024);
            String pukString = keyStringList.get(0);
            String prkString = keyStringList.get(1);
            System.out.println("公钥:" + pukString);
            System.out.println("私钥:" + prkString);
            // 生成公钥、私钥
            puk = RSAUtils.getPublicKey(pukString);
            prk = RSAUtils.getPrivateKey(prkString);
            encryptedMsg = RSAUtils.encryptByPublicKey(message, puk);
            decryptedMsg = RSAUtils.decryptByPrivateKey(encryptedMsg, prk);
            System.out.println("string key ! message ==  decryptedMsg ? " + message.equals(decryptedMsg));
    
        }
    }
    

     

    更多相关内容
  • RSA算法Java实现

    2019-03-23 16:27:06
    RSAPrivateKey prk = (RSAPrivateKey) b.readObject(); BigInteger d = prk.getPrivateExponent(); // 获取私钥参数及解密 BigInteger n = prk.getModulus(); System.out.println("d= " + d); System.out...
  • JAVA RSA 加密算法 RSA.java RSA公钥加解密,RSA私钥加解密,MD5withRSA 签名 MD5withRSA签名较验
  • RSA算法Java实现

    千次阅读 2022-02-22 09:13:38
    一、RSA算法描述 RSA主要利用的是大素数分解的困难性,即知道n如何求出p和q。 二、总体结构 //判断是否是素数 public static boolean isPrime(long n) { } //计算欧拉数 public static long Euler(long...

    一、RSA算法描述

    RSA主要利用的是大素数分解的困难性,即知道n如何求出p和q。

    二、总体结构

        //判断是否是素数
        public static boolean isPrime(long n) {
    
        }
    
        //计算欧拉数
        public static long Euler(long p, long q) {
    
        }
    
        //欧几里得算法求两数的最大公因数---a>b
        static long gcd(long a, long b) {
    
        }
    
        //求模反元素d(私钥)
        public static long Key(long e, long euler) {
    
        }
    
        //递归求n次方
        public static long power(long a, long n) {
    
        }
    
        //加密
        public static long encryption(long msg, long e, long n) {
    
        }
    
        //解密
        public static long decryption(long c, long key, long n) {
    
        }
    
        public static void main(String[] args) {
    
        }

    三、模块分解

    1.判断是否是素数

        public static boolean isPrime(long n) {
            boolean b = true;
            for (long i = 2; i <= Math.sqrt(n); i++) {
                if (n % i == 0) {
                    b = false;
                    break;
                } else
                    b = true;
            }
            return b;
        }

    2.计算欧拉数

        public static long Euler(long p, long q) {
            return (p - 1) * (q - 1);
        }

    3.欧几里德算法求两数的最大公因数

        static long gcd(long a, long b) {
            if (a < b) {
                long t = a;
                a = b;
                b = t;
            }
            if (a % b == 0) return b;
            else return gcd(b, a % b);
        }

    4.求模范元素

        public static long Key(long e, long euler) {
            long key = 1;
            while ((key * e) % euler != 1) {
                key++;
            }
            return key;
        }

    5.递归求a的n次方

        public static long power(long a, long n) {
            long r = 1;
            if (n == 0) r = 1;
            else {
                r = a * power(a, n - 1);
            }
            return r;
        }

    6.加密过程

        public static long encryption(long msg, long e, long n) {
            System.out.println("加密中.......");
            return power(msg, e) % n;
        }

    7.解密过程

        public static long decryption(long c, long key, long n) {
            System.out.println("解密中.......");
            return power(c, key) % n;
        }

    四、数据结构

    long p:大素数p

    long q:大素数q

    boolean b:判断素数的flag

    long euler:p*q的欧拉数

    long e:最小的加密密钥e

    long key:e对euler的模范元素(即算法描述中的d)

    long msg:明文

    long c:密文

    五、运行结果

     这个是选取较小的素数进行测试得到的正确的结果,但是由于long的范围有限,当选取较大的素数进行测试的时候就会因为范围溢出导致数据丢失,从而影响最终的结果,具体如下图所示。

     六、源代码

    package RSA;
    
    import java.awt.desktop.SystemEventListener;
    import java.util.Scanner;
    
    public class Demo {
        //判断是否是素数
        public static boolean isPrime(long n) {
            boolean b = true;
            for (long i = 2; i <= Math.sqrt(n); i++) {
                if (n % i == 0) {
                    b = false;
                    break;
                } else
                    b = true;
            }
            return b;
        }
    
        //计算欧拉数
        public static long Euler(long p, long q) {
            return (p - 1) * (q - 1);
        }
    
        //欧几里得算法求两数的最大公因数---a>b
        static long gcd(long a, long b) {
            if (a < b) {
                long t = a;
                a = b;
                b = t;
            }
            if (a % b == 0) return b;
            else return gcd(b, a % b);
        }
    
        //求模反元素d(私钥)
        public static long Key(long e, long euler) {
            long key = 1;
            while ((key * e) % euler != 1) {
                key++;
            }
            return key;
        }
    
        //递归求n次方
        public static long power(long a, long n) {
            long r = 1;
            if (n == 0) r = 1;
            else {
                r = a * power(a, n - 1);
            }
            return r;
        }
    
        //加密
        public static long encryption(long msg, long e, long n) {
            System.out.println("加密中.......");
            return power(msg, e) % n;
        }
    
        //解密
        public static long decryption(long c, long key, long n) {
            System.out.println("解密中.......");
            return power(c, key) % n;
        }
    
        public static void main(String[] args) {
            System.out.println("--------RSA--------");
            //两个大素数
            long p;
            long q;
            System.out.print("输入两个大素数p、q:");
            Scanner sc = new Scanner(System.in);
            p = sc.nextLong();
            q = sc.nextLong();
            // System.out.println("p = " + p + ",q = " + q);
            //判断输入的是否是素数
            boolean b;   //flag
            //判断p
            b = isPrime(p);
            if (b == false) {
                System.out.println("p = " + p + "不是素数。重新输入p!");
                p = sc.nextLong();
                b = isPrime(p);
                while (b = false) {
                    System.out.println("p = " + p + "不是素数。重新输入p!");
                    p = sc.nextLong();
                    b = isPrime(p);
                }
            }
            System.out.println(" p = " + p + "是素数。");
    
            //判断q
            b = isPrime(q);
            if (b == false) {
                System.out.println("q = " + q + "不是素数。重新输入q!");
                q = sc.nextLong();
                b = isPrime(q);
                while (b = false) {
                    System.out.println("q = " + q + "不是素数。重新输入q!");
                    q = sc.nextLong();
                    b = isPrime(q);
                }
            }
            System.out.println(" q = " + q + "是素数。");
            //打印最终的p、q
            System.out.println("p = " + p + ",q = " + q);
    
            //计算p、q的欧拉数
            long euler = Euler(p, q);
            System.out.println("Euler(p,q) = " + euler);
    
            //选取最小的公钥e,1<e<euler,且与euler互质
            long e = 2;
            while (gcd(e, euler) != 1 || e > euler || e < 1) {
                e++;
            }
            System.out.println("e = " + e);
    
            //求出模反元素(私钥)
            long key = Key(e, euler);
            System.out.println("key = " + key);
    
            //System.out.println(power(2, 2));
            //加密过程
            System.out.println("输入明文:");
            long msg = sc.nextLong();
            System.out.println("明文:" + msg);
            long c = encryption(msg, e, p * q);//密文
            System.out.println("加密后的密文:" + c);
            //解密过程
            msg = decryption(c, key, p * q);
            System.out.println("解密后的明文:" + msg);
    
        }
    }
    

    展开全文
  • RSA算法JAVA

    2013-06-01 16:51:38
    这是用JAVA编写的RSA算法,功能比较完整,不过注意支持的数字不能太大。
  • 编程利用Java实现RSA算法

    千次阅读 2021-06-17 14:46:58
    使用该程序可利用eclipse打开源代码文件夹,然后运行RSA.java即可根据默认的明文和密钥输出加密、解密结果。默认使用的密钥由文件读出的1024位大素数产生,也可以更改参数使用自定义算法产生指定位的大素数。同时为...

    1.使用说明

    本程序利用eclipse使用Java语言编写。使用该程序可利用eclipse打开源代码文件夹,然后运行RSA.java即可根据默认的明文和密钥输出加密、解密结果。默认使用的密钥由文件读出的1024位大素数产生,也可以更改参数使用自定义算法产生指定位的大素数。同时为保证安全性以及照顾到算法加密、解密时间,两个大素数强制规定必须在1024位及以上,公钥指数为最常用的65537。

    2.运行截图

    在这里插入图片描述

    3.总体设计

    3.1类和函数

    本程序只有一个RSA.java类。

    • (1)public RSA(BigInteger e, int generateKeyFlag, int pqLength) throws RSA.pqException,该构造函数根据传入的形参公钥指数e、大质数p和q的产生方式标识generateKeyFlag、q和p的长度(比特数)pqLength,来调用函数generateKey来产生密钥(公钥和私钥)。
    • (2)public static void main(String[] args) throws RSA.pqException,主函数指定明文等参数并调用函数encryption和decryption来进行加密、解密。
    • (3)自定义内部类private class pqException extends Exception,只有一个构造函数传入形参message,用于输出由于大素数p、q不符合要求所产生的异常。
    • (4)private void generateKey(int generateKeyFlag, int pqLength) throws RSA.pqException,密钥产生函数,形参分别是大质数p和q的产生方式标识(0:文件读入;1:随机产生)generateKeyFlag、p和q的长度(比特数)pqLength。
    • (5)private BigInteger[] encryption(String plainText)RSA加密函数,形参传入String类型的明文plainText,返回加密后的BigInteger类型的数组。
    • (6)private String decryption(BigInteger[] c)RSA解密函数,形参传入BigInteger数组类型表达的密文c,返回String类型的new String(result)解密结果。
    • (7)private static BigInteger[] extdGcd(BigInteger e, BigInteger φn) 利用扩展欧几里得算法求出私钥d,使得de = kφ(n)+1,k为整数。形参分别是公钥e、φn (=(p-1)(q-1)),返回BigInteger数组形式返回最大公约数、私钥d、k(gdk)。
    • (8)private static boolean isPrime(BigInteger p) 利用米勒·罗宾算法判断一个数是否是质数,形参是要判断的数,返回true/false。
    • (9)private static BigInteger generateNBitRandomPrime(int n),随机产生n比特的素数,形参数比特数n,返回产生的素数。
    • (10)private static BigInteger expMod(BigInteger base, BigInteger exponent, BigInteger module) 蒙哥马利快速幂模运算,返回base^exponent mod module的结果,形参分别是底数base、指数exponent、模数module,返回结果result。

    3.2结构说明

    RSA算法的具体描述如下:

    • (1)任意选取两个不同的大素数p和q计算乘积n=pq,φ(n)=(p-1)(q-1);
    • (2)任意选取一个大整数e,满足gcd(e, φ(n))=1且1<e<φ(n),e用做加密钥;
    • (3)确定的解密钥d,满足(de)modφ(n)=1,即de=kφ(n)+1,k>=1且为整数;
    • (4)公开整数n和e,秘密保存d;
    • (5)将明文m(m<n,是一个整数)加密成密文c,加密算法为c=E(m)=memodn;
    • (6)将密文c解密为明文m,解密算法为m=D©=cdmodn。
      根据如上所示的RSA算法的基本流程,结合本实例来说明一下程序结构。公钥e直接使用通用的65537,在generateKey函数中可使用文件读入或随机的方式产生p、q,随机产生的方式会利用到函数generateNBitRandomPrime和isPrime产生指定位的素数,然后利用extdGcd函数计算出私钥d。接着在encryption加密函数中会根据m<n的原则进行分组逐组加密,利用expMod进行快速幂模运算,解密函数decryption中同样逐组利用expMod函数进行幂模运算。

    4.详细设计

    RSA.java类中定义三个变量,分别是两个大质数乘积n、公钥指数e、私钥指数d,以及一个常量PQMINLENGTH表示质数q和p最小长度(比特数)。

    • (1)public RSA(BigInteger e, int generateKeyFlag, int pqLength) throws RSA.pqException,该构造函数根据传入的形参公钥指数e、大质数p和q的产生方式标识generateKeyFlag、q和p的长度(比特数)pqLength,来调用函数generateKey来产生密钥(公钥和私钥)。
    • (2)public static void main(String[] args) throws RSA.pqException,主函数定义变量generateKeyFlag、pqLength(p和q长度,比特数)、公钥指数e、以及要加密的原文originalText。利用指定参数初始化对象,然后调用函数encryption并传入原文进行加密同时返回密文数组,并输出密文。再将密文数组传进decryption函数来进行解密并返回明文。
    • (3)自定义内部异常类private class pqException extends Exception,该自定义异常类很简单,只有一个构造函数传入形参字符串类型的形参message,用于输出由于大素数p、q不符合要求所产生的异常。
    • (4)private void generateKey(int generateKeyFlag, int pqLength) throws RSA.pqException,密钥产生函数,形参分别是大质数p和q的产生方式标识(0:文件读入;1:随机产生)generateKeyFlag、p和q的长度(比特数)pqLength。首先定义两个大素数和φ(n),也就是大素数分别减一的乘积。判断素数产生的标识,如果为0则代表由文件读入。利用FileReader和BufferedReader对象,利用循环和后者的readline逐行读物出两个素数并赋值(文件中的两个素数按行存取,每一行代表一个素数),然后利用close方法关闭输入流。
    • 接着逐个两个两个数是否是质数(利用函数isPrime判定)、长度是否大于所规定的,如果不满足其中一个则直接抛出异常,程序结束。如果是随机产生两个大素数,首先对参数pqLength判断是否小于规定的最小长度,如果小于,则抛出指定的自定义异常,程序结束;否则调用函数generateNBitRandomPrime传入素数长度这个产生两个素数。
    • 接着分别求出n和φ(n),并利用自定义的扩展欧几里得算法extdGcd求出私钥d,如果求出的私钥小于0,则加上φ(n)即可。
    • (5)private BigInteger[] encryption(String plainText)RSA加密函数,形参传入String类型的明文plainText,返回加密后的BigInteger类型的数组。利用getByte函数将String类型的明文转化为byte数组类型,指定编码为UTF-8,然后这里每个字节利用3为整数来表示,不够则在前面补0,因此循环遍历字节数组将每位和0xff(16进制数,10进制为255)进行与操作得到一个非负整数,然后添加到字符串上。
    • 之后利用BigInteger的构造函数将这字符串转化为BigInteger类型保存在m上,判定该数是否小于n,若小于n则为mArray数组分配一个BigInteger大小的空间并将m保存到该数组上;如果大于n,由于算法的规定,因此需要进行分组加密,每组的长度规定为n的字符串的长度-1,这样是避免分组后大小依然超过n。同时也由于前面的每个字节是由3位整数保存的,因此分组的长度也应该为3的整数,避免恢复时出错。
    • 因此判读此时的每组长度是否为3的整数,如果不是,则减一。然后判断明文数字形式字符串长度模上每组的长度是否为0,如果补是则明文数组mArray应该为明文数字字符串长度除每组长度加1,否则就不用加1。接着利用循环分割明文数字形式字符串保存在BigInteger数组中,然后再次利用循环调用expMod快速幂模函数逐组加密保存到数组上并返回。
    • (6)private String decryption(BigInteger[] c)RSA解密函数,形参传入BigInteger数组类型表达的密文c,返回String类型的new String(result)解密结果。对密文BigInteger数组利用快速幂模函数expMod进行逐组解密,由于解密出来的每组的数字可能由于最前面的数字为0而缺失,导致转化为byte数组时出错,因此这里需要判断 是否为3的整数,如果不是则在最前面补0直到为3的整数倍,然后将每组所得的结果组合成一个长的数字字符串,利用循环每3为代表一个字节逐段截取并强化转为byte类型(byte) (Integer.parseInt(cPadding.substring(i * 3, i * 3 + 3))),并保存到byte数组上,然后利用String构造方法将次byte数组转化为明文。
    • (7)private static BigInteger[] extdGcd(BigInteger e, BigInteger φn) 利用扩展欧几里得算法求出私钥d,使得de = kφ(n)+1,k为整数。形参分别是公钥e、φn (=(p-1)(q-1)),返回BigInteger数组形式返回最大公约数、私钥d、k(gdk)。7~10涉及到的数学原理就不再过多介绍,因为我们的重点并不在这里。定义3个BigInteger大小的数组用来保存最大公约数g、私钥d、k,如果φ(n)为0,为将公钥指数e赋给g,1赋给d,0赋给k,并返回gdk;否则将传入φ(n),e % φ(n)递归调用该函数,然后临时保存k,k为d-e/φ(n)*k,将临时保存的k赋给d,最后返回。
    • (8)private static boolean isPrime(BigInteger p) 利用米勒·罗宾算法判断一个数是否是质数,形参是要判断的数,返回true/false。如果小于2则返回false,又不为2且可以整除2也直接返回false,否则利用如下代码BigInteger p_1 = p.subtract(BigInteger.ONE);BigInteger m = p_1;int q = m.getLowestSetBit();m = m.shiftRight(q); 找到q和m使得p = 1 + 2^q * m。然后在1~p区间上生成均匀随机数,将下面步骤的利用循环判断5轮(判断的轮数,精度、轮数和时间三者之间成正比关系),BigInteger z = RSA.expMod(b, m, p);while (!((j == 0 && z.equals(BigInteger.ONE)) || z.equals(p_1))) {if ((j > 0 && z.equals(BigInteger.ONE)) || ++j == q) {return false;}z = RSA.expMod(z, BigInteger.TWO, p);},若通过了米勒·罗宾算法则代表是素数,返回true。
    • (9)private static BigInteger generateNBitRandomPrime(int n),随机产生n比特的素数,形参数比特数n,返回产生的素数。这里主要的思想是先算出在该比特数下的最小数,也就是2^(n-1),然后先随机生成一个1-100的整数用于确定0和1出现的比率,保证生成的01的概率都是50%,然后除了最高位(最高位肯定是1),逐位产生01并根据所在位置计算值和最小值相加,也就是二进制转化为10进制,最后便得到一个指定位的整数,然后利用前面的素数判断函数判断该数是否是素数,如果是则直接返回否则继续生成,直到是素数为止。
    • (10)private static BigInteger expMod(BigInteger base, BigInteger exponent, BigInteger module) 蒙哥马利快速幂模运算,返回base^exponent mod module的结果,形参分别是底数base、指数exponent、模数module,返回结果result。Result为1,tmp = base.mod(module)。循环条件为指数不为0,然后判断指数和1进行与操作的值是否为0,如果不是则result = result.multiply(tmp).mod(module);出if语句,然后tmp = tmp.multiply(tmp).mod(module);,指数右移1位,继续进行循环,循环结束返回结果即可。

    5.源码

    https://gitee.com/zhz000/rsa
    https://github.com/zhz000/rsa

    展开全文
  • 25行代码实现完整的RSA算法Java

    万次阅读 多人点赞 2018-03-29 00:07:43
    25行代码实现完整的RSA算法Java版   我的上一篇博客《25行代码实现完整的RSA算法》自从上个月发表了以后,很多程序员给我打电话或者发短信说,终于看到了一篇能把RSA算法的代码写明白的,他们问我说能不能把...

    25行代码实现完整的RSA算法Java版

      我的上一篇博客《25行代码实现完整的RSA算法》自从上个月发表了以后,很多程序员给我打电话或者发短信说,终于看到了一篇能把RSA算法的代码写明白的,他们问我说能不能把代码写成Java版的,我说Java的会看着很费劲,Python代码的直观性在数字计算方面有很大的优势。
      但是架不住他们非要我写,我一拍肩膀说,好吧,我答应你们的请求。花了一晚上的时间,就把代码从Python翻译成为Java,经过测试完美。如果写得不好,请大家轻轻拍砖。
      至于RSA理论我就不再这里讲了,代码如果看不懂,请看我的上一篇博客《25行代码实现完整的RSA算法》。下面就主要把代码贴出来了。

    1、计算最大公约数与扩展欧几里得算法

      GCD.java文件,gcd方法用来计算两个整数的最大公约数。ext_gcd是扩展欧几里得方法的计算公式。

    import java.math.BigInteger;
    
    /**
     * 求最大公约数
     * @author 北门大官人
     *
     */
    public class GCD {
    	/**
    	 * <p>辗转相除法求最大公约数
    	 * @param a
    	 * @param b
    	 * @return
    	 */
    	public BigInteger gcd(BigInteger a, BigInteger b){
    		if(b.equals(BigInteger.ZERO)){
    			return a ;
    		}else{
    			return gcd(b, a.mod(b)) ;
    		}
    	}
    	/**
    	 * <p>扩展欧几里得算法:
    	 * <p>求ax + by = 1中的x与y的整数解(a,b互质)
    	 * @param a
    	 * @param b
    	 * @return
    	 */
    	public BigInteger[] extGcd(BigInteger a, BigInteger b){
    		if(b.equals(BigInteger.ZERO)){
    			BigInteger x1 = BigInteger.ONE ;
    			BigInteger y1 = BigInteger.ZERO ;
    			BigInteger x = x1 ;
    			BigInteger y = y1 ;
    			BigInteger r = a ;
    			BigInteger[] result = {r, x, y} ;
    	        return result ;
    		}else{
    			BigInteger[] temp = extGcd(b, a.mod(b)) ;
    			BigInteger r  = temp[0] ;
    			BigInteger x1 = temp[1] ;
    			BigInteger y1 = temp[2] ;
    			
    			BigInteger x = y1 ;
    			BigInteger y = x1.subtract(a.divide(b).multiply(y1)) ;
    			BigInteger[] result = {r, x, y} ;
    	        return result ;
    		}
    	} 
    }
    
    

    2、大整数幂取模算法

      Exponentiation.java文件,主要用于计算超大整数超大次幂然后对超大的整数取模。我在网上查询到这个算法叫做“蒙哥马利算法”。

    import java.math.BigInteger;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 主要用于计算超大整数超大次幂然后对超大的整数取模。
     * 我在网上查询到这个算法叫做"蒙哥马利算法"。
     * @author 北门大官人
     */
    public class Exponentiation {
    	
    	/**
    	 * 超大整数超大次幂然后对超大的整数取模
    		(base ^ exponent) mod n
    	 * @param base
    	 * @param exponent
    	 * @param n
    	 * @return
    	 */
    	public BigInteger expMode(BigInteger base, BigInteger exponent, BigInteger n){
    		char[] binaryArray = new StringBuilder(exponent.toString(2)).reverse().toString().toCharArray() ;
    		int r = binaryArray.length ;
    		List<BigInteger> baseArray = new ArrayList<BigInteger>() ;
    		
    		BigInteger preBase = base ;
    		baseArray.add(preBase);
    		for(int i = 0 ; i < r - 1 ; i ++){
    			BigInteger nextBase = preBase.multiply(preBase).mod(n) ;
    			baseArray.add(nextBase) ;
    	        preBase = nextBase ;
    		}
    		BigInteger a_w_b = this.multi(baseArray.toArray(new BigInteger[baseArray.size()]), binaryArray, n) ;
    		return a_w_b.mod(n) ;
    	}
    	
    	
    	private BigInteger multi(BigInteger[] array, char[] bin_array, BigInteger n){
    	    BigInteger result = BigInteger.ONE ;
    	    for(int index = 0 ; index < array.length ; index ++){
    	        BigInteger a = array[index] ;
    	        if(bin_array[index] == '0'){
    	            continue ;
    	        }
    	        result = result.multiply(a) ;
    	        result = result.mod(n) ;
    	    }
    	    return result ;
    	}
    
    }
    
    

    3、公钥私钥生成

      RSA.java,生成公钥、私钥、并对信息加密解密。

    import java.math.BigInteger;
    
    /**
     * RSA加密、解密、测试正确性
     * @author 北门大官人
     *
     */
    public class RSA {
    	/**
    	 * <pre>
    	 def gen_key(p, q):
    	    n = p * q
    	    fy = (p - 1) * (q - 1)
    	    e = 3889
    	    # generate d
    	    a = e
    	    b = fy
    	    r, x, y = ext_gcd(a, b)
    	    print x
    	    d = x
    	    # 公钥    私钥
    	    return (n, e), (n, d)
    	    </pre>
    	 * @param p
    	 * @param q
    	 * @return
    	 */
    	public BigInteger[][] genKey(BigInteger p, BigInteger q){
    		BigInteger n = p.multiply(q) ;
    		BigInteger fy = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE)) ;
    		BigInteger e = new BigInteger("65537") ;
    		// generate d
    		BigInteger a = e ;
    		BigInteger b = fy ;
    		BigInteger[] rxy = new GCD().extGcd(a, b) ;
    		BigInteger r = rxy[0] ;
    		BigInteger x = rxy[1] ;
    		BigInteger y = rxy[2] ;
    		
    		BigInteger d = x ;
    		// 对于计算出来的负数d,需要d=d+fy
    		if(d.compareTo(BigInteger.valueOf(0)) < 0){
    			d = d.add(fy) ;
    		}
    		// 公钥  私钥
    		return new BigInteger[][]{{n , e}, {n , d}} ;
    	}
    	
    	/**
    	 * 加密
    	 * @param m 被加密的信息转化成为大整数m
    	 * @param pubkey 公钥
    	 * @return
    	 */
    	public BigInteger encrypt(BigInteger m, BigInteger[] pubkey){
    		BigInteger n = pubkey[0] ;
    		BigInteger e = pubkey[1] ;
    	    
    		BigInteger c = new Exponentiation().expMode(m, e, n) ;
    	    return c ;
    	}
    	
    	/**
    	 * 解密
    	 * @param c 
    	 * @param selfkey 私钥
    	 * @return
    	 */
    	public BigInteger decrypt(BigInteger c, BigInteger[] selfkey){
    		BigInteger n = selfkey[0] ;
    		BigInteger d = selfkey[1] ;
    		
    		BigInteger m = new Exponentiation().expMode(c, d, n) ;
    		return m ;
    	}
    
    	
    	public static void main(String[] args) {
    		// 公钥私钥中用到的两个大质数p,q'''
    		BigInteger p = new BigInteger("106697219132480173106064317148705638676529121742557567770857687729397446898790451577487723991083173010242416863238099716044775658681981821407922722052778958942891831033512463262741053961681512908218003840408526915629689432111480588966800949428079015682624591636010678691927285321708935076221951173426894836169") ;
    		BigInteger q = new BigInteger("144819424465842307806353672547344125290716753535239658417883828941232509622838692761917211806963011168822281666033695157426515864265527046213326145174398018859056439431422867957079149967592078894410082695714160599647180947207504108618794637872261572262805565517756922288320779308895819726074229154002310375209") ;
    		
    		RSA rsa = new RSA() ;
    	    // 生成公钥私钥'''
    	    // pubkey, selfkey = gen_key(p, q)
    	    BigInteger[][] keys = rsa.genKey(p, q) ;
    	    BigInteger[] pubkey  = keys[0] ;
    	    BigInteger[] selfkey = keys[1] ;
    	    
    	    // 需要被加密的信息转化成数字,长度小于秘钥n的长度,如果信息长度大于n的长度,那么分段进行加密,分段解密即可。'''
    	    BigInteger m = new BigInteger("1356205320457610288745198967657644166379972189839804389074591563666634066646564410685955217825048626066190866536592405966964024022236587593447122392540038493893121248948780525117822889230574978651418075403357439692743398250207060920929117606033490559159560987768768324823011579283223392964454439904542675637683985296529882973798752471233683249209762843835985174607047556306705224118165162905676610067022517682197138138621344578050034245933990790845007906416093198845798901781830868021761765904777531676765131379495584915533823288125255520904108500256867069512326595285549579378834222350197662163243932424184772115345") ;
    	    System.out.println("被加密信息:" + m);
    	    // 信息加密'''
    	    BigInteger c = rsa.encrypt(m, pubkey) ;
    	    System.out.println("密文:" + c);
    	    // 信息解密'''
    	    BigInteger d = rsa.decrypt(c, selfkey) ;
    	    System.out.println("被解密后信息:" + d);
    	}
    }
    
    

      用Java写出来的数值运算就是没有Python的直观。大整数运算只能用BigInteger,确实看得人眼睛疼。如果哪里不懂可以对照上一篇《25行代码实现完整的RSA算法》一起看,祝大家晚安。
      代码经过运行以后,发现加密的速度很快,但是解密的速度有点惨不忍睹。在2048位秘钥的时候,解密时间为0.14秒,比Python版的慢3倍多。python只用0.038秒左右。由此说明,Java语言不适合做数值运算,而Python语言在这方面有着很大的优势。
      最后,觉得代码写得好的,请给我打赏
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 可以直接运行成功的RSA加密解密示例 JAVA端采用公钥加密,服务端C#采用私钥解密。
  • 从网上找到的,是别人的代码,但是自己还是不会,而且在自己的机子里实现不了,但是大神们可以看看,就不要积分了。
  • 包括RSA算法的两种语言实现,原理正确,可以正常运行,对应博客为:https://blog.csdn.net/qq_41112170/article/details/104904340
  • 一、RSA算法1.密钥生成随机生成两个大素数p、q计算n=p*q计算n的欧拉函数f=(p-1)*(q-1)选取1计算d,ed=1modf公钥为(e,n),私钥为(d,n)2.加密c=m^e mod n3.解密m=c^e mod n二、BigInteger类(大数)定义:BigInteger b=...
  • 提供了rsa算法java类及测试代码.其中已经用过,有需要的可以拿去
  • RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。 这时一个简单的Java实现,在RSA网络安全工具类是比较完整的实现。
  • 主要介绍了Java加密算法RSA代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 下面小编就为大家带来一篇RSA加密算法java简单实现方法(必看)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • RSA算法JAVA实现的代码

    2013-11-23 10:59:16
    RSA加密解密,物流信息安全方面,用java实现rsa算法
  • RSA算法,有界面操作,能随机产生素数,进而随机产生公钥和私钥,功能完善
  • RSA jar包是网络安全中关于RSA算法的实现,是我实习的时候写的
  • RSA算法JAVA通用代码

    千次阅读 2018-08-21 20:48:51
    一 获取密钥 KeyPairGenerator keyPairGenerator = ...RSA&quot;); KeyPair keyPair = keyPairGenerator.generateKeyPair(); PrivateKey privateKey = keyPair.getPrivate(); 二 保存公钥 因为公钥是二进制...
  • java编程实现RSA加密算法

    千次阅读 2021-03-07 11:02:25
    那么我今天就给大家介绍一下如何利用Java编程来实现RSA加密算法。一、RSA加密算法描述RSA加密算法是1978年提出的。经过多年的分析和研究,在众多的公开密钥加密算法中,RSA加密算法最受推崇,它也被推荐为公开密钥...
  • 最近处理RSA算法,找了一些相关的资料和代码,整理了一下,汇总成这篇文章。基础RSA算法非常简单,概述如下:找两素数p和q取n=p*q取t=(p-1)*(q-1)取任何一个数e,要求满足e取d*e%t==1这样最终得到三个数: n d e设...
  • RSA算法JS加密JAVA解密

    2017-10-30 16:20:00
    RSA非对称算法,前端JS通过公钥加密,后端JAVA通过私钥解密
  • RSA算法加解密java工具

    2020-02-23 23:15:56
    RSA算法加解密java工具, 包括: 创建公钥、私钥、加密、解密、分段加密 创建公钥、私钥、加密、解密、分段加密 创建公钥、私钥、加密、解密、分段加密
  • 主要介绍了Java实现的RSA加密解密算法,结合实例形式分析了java RAS加密解密算法的相关实现技巧,需要的朋友可以参考下
  • 浅析用Java编程实现RSA算法的过程.pdf
  • RSA加密算法是一种非对称加密算法,其玩法打破了以往所有加密算法的规则.在RSA出现之前,所有的加密方法都是同一种模式:加密解密的规则使用同一种方式.这种长达几个世纪的加密方案有一个致命的缺陷.在传递加密信息时,...
  • 非对称加密——RSA算法JAVA代码实践

    千次阅读 2020-11-18 17:41:32
    2:下面代码是RSAJAVA中API级别的代码实现,具体实现原理见前面章节 3:下面代码中只需要JDK即可,其中为了便于阅读使用了commons-codec中Base64编码 4:公钥密码既可以公钥加密私钥解密,又可以私钥加密公钥解密...
  • Java -- RSA 非对称加密算法工具类

    千次阅读 2022-05-01 14:54:44
    RSA公开密钥密码体制是一种使用不同的加密密钥与解密密钥,“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制” RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪...本文提供RSA 非对称加密算法工具类

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 36,919
精华内容 14,767
关键字:

rsa算法java