【问题标题】:How to encrypt / decrypt a text by using RSA method?如何使用 RSA 方法加密/解密文本?
【发布时间】:2019-07-22 19:15:07
【问题描述】:

我有一个使用 RSA 算法加密和解密数字的简单 java 代码

如果有人可以帮助我让这段代码从用户那里读取一个文本(字符串)并解密它而不只是数字,而是以一种简单的方式,这样我就可以在之后为代码绘制流程图:)

https://codedost.com/css/java-program-rsa-algorithm/

import java.util.*;
import java.math.*;

public class RSA {

public static void main(String args[]) {
    Scanner sc = new Scanner(System.in);
    int p, q, n, z, d = 0, e, i;
    System.out.println("Enter the number to be encrypted and decrypted");
    int msg = sc.nextInt();
    double c;
    BigInteger msgback;
    System.out.println("Enter 1st prime number p");
    p = sc.nextInt();
    System.out.println("Enter 2nd prime number q");
    q = sc.nextInt();

    n = p * q;
    z = (p - 1) * (q - 1);
    System.out.println("the value of z = " + z);

    for (e = 2; e < z; e++) {
        if (gcd(e, z) == 1) // e is for public key exponent
        {
            break;
        }
    }
    //e should be in the range 1-z
    System.out.println("the value of e = " + e);

    // calculate d
    for (i = 0; i <= 9; i++) {
        int x = 1 + (i * z);
        if (x % e == 0) //d is for private key exponent
        {
            d = x / e;
            break;
        }
    }
    System.out.println("the value of d = " + d);
    c = (Math.pow(msg, e)) % n;
    //Encryptin  C = msg ^e mod n
    System.out.println("Encrypted message is : -");
    System.out.println(c);


    //converting int value of n to BigInteger
    BigInteger N = BigInteger.valueOf(n);
    //converting float value of c to BigInteger
    BigInteger C = BigDecimal.valueOf(c).toBigInteger();

    msgback = (C.pow(d)).mod(N);
    //Decrypt , P = Cˆd mod N , msgback = P
    System.out.println("Derypted message is : -");
    System.out.println(msgback);

}
static int gcd(int e, int z) {
    if (e == 0) {
        return z;
    } else {
        return gcd(z % e, e);
    }
}
}

【问题讨论】:

  • RSA 仅适用于数字;但是您可以,例如将您的字符串转换为字节,并单独加密每个字节;或将 8 个字节组合成一个 long 并加密 long-s;或使用其他技术(例如将先前计算的值添加到被加密的下一个字符等)。
  • 通常你会对字节进行操作并使用BigInteger 来计算。
  • (1) 最大 31 位 p 和 q,更不用说最大 31 位 n,太小而无法提供任何安全性 (2) 计算 d 的方法无法使用非荒谬的 n 甚至远低于 31 位 (3) 使用 Math.pow 对超过 52 位不起作用,并且为合理的大小执行 pow then mod (not combined) 将需要更长的时间比地球存在 (4) 即使有合理的大小和工作代码,未填充的 RSA 大多不安全;这对于 SO 来说是 OT,但在加密和安全堆栈上被数十个 Q 所涵盖(5)这些基本错误可以通过阅读维基百科来避免
  • 为避免大文本的 CPU 成本过高,您可以有一个标头来表示通过公钥加密交付的主密钥,然后使用来自该主密钥的 AES 文件的其余部分。
  • @Daniele 我知道,但不幸的是我没有那种编程技能:(

标签: java string security encryption rsa


【解决方案1】:

由于您已经为单个号码实现了加密和解密,您可以轻松扩展它并为更长的消息提供支持。实际上,您需要的唯一更改是执行相同的操作 N 次(对于输入消息中的每个字符)。看看下面的代码:



import java.util.*;
import java.math.*;

public class Rsa {

    private static final Scanner sc = new Scanner(System.in);

    private int p, q, n, z, d = 0, e, i;

    public Rsa() {
        System.out.println("Enter 1st prime number p");
        p = sc.nextInt();
        System.out.println("Enter 2nd prime number q");
        q = sc.nextInt();

        n = p * q;
        z = (p - 1) * (q - 1);
        System.out.println("the value of z = " + z);

        for (e = 2; e < z; e++) {
            if (gcd(e, z) == 1) // e is for public key exponent
            {
                break;
            }
        }
        //e should be in the range 1-z
        System.out.println("the value of e = " + e);

        // calculate d
        for (i = 0; i <= 9; i++) {
            int x = 1 + (i * z);
            if (x % e == 0) //d is for private key exponent
            {
                d = x / e;
                break;
            }
        }
        System.out.println("the value of d = " + d);
    }

    private static int gcd(int e, int z) {
        if (e == 0) {
            return z;
        } else {
            return gcd(z % e, e);
        }
    }

    double encrypt(int msg) {
        //Encrypting  C = msg ^e mod n
        return (Math.pow(msg, e)) % n;
    }

    double[] encrypt(String msg) {
        int[] charactersAsNumbers = new int[msg.length()];
        for(int i = 0; i < msg.length(); i++) {
            charactersAsNumbers[i] = msg.codePointAt(i);
        }
        System.out.println("Plain text as sequence of numbers: " + Arrays.toString(charactersAsNumbers));

        double[] encryptedMsg = new double[msg.length()];
        for(int i = 0; i < charactersAsNumbers.length; i++) {
            encryptedMsg[i] = encrypt(charactersAsNumbers[i]);
        }
        return encryptedMsg;
    }

    BigInteger decrypt(double encrypted) {
        //converting int value of n to BigInteger
        BigInteger N = BigInteger.valueOf(n);
        //converting float value of c to BigInteger
        BigInteger C = BigDecimal.valueOf(encrypted).toBigInteger();

        //Decrypt , P = Cˆd mod N , msgback = P
        return (C.pow(d)).mod(N);
    }

    String decrypt(double[] encrypted) {
        StringBuilder builder = new StringBuilder();
        for(double encryptedCharacter: encrypted) {
            BigInteger decryptedCharacter = decrypt(encryptedCharacter);
            builder.append(Character.toChars(decryptedCharacter.intValue()));
        }
        return builder.toString();
    }

    public static void main(String args[]) {
        System.out.println("Enter the text to be encrypted and decrypted");
        String msg = sc.nextLine();
        Rsa rsa = new Rsa();

        double[] c = rsa.encrypt(msg);
        System.out.println("Encrypted message is: " + Arrays.toString(c));

        String msgBack = rsa.decrypt(c);
        System.out.println("Decrypted message is: " + msgBack);
    }
}

我在这里所做的是:

  • 重载encryptdecrypt 方法。现在它们支持更长的消息; encrypt 接受String 参数并返回double[]decrypt 接受double[] 并返回String
  • 在不改变原始数据类型和一般流程的情况下将逻辑转移到方法中

我知道给定的解决方案不是最优的,但我想在这种情况下性能和代码风格对你来说并不重要。

希望它能帮助您解决问题。

编辑:我稍微改进了日志,这里是示例输出(和输入):

Enter the text to be encrypted and decrypted
Secret.
Enter 1st prime number p
13
Enter 2nd prime number q
19
the value of z = 216
the value of e = 5
the value of d = 173
Plain text as sequence of numbers: [83, 101, 99, 114, 101, 116, 46]
Encrypted message is: [239.0, 43.0, 112.0, 95.0, 43.0, 51.0, 50.0]
Decrypted message is: Secret.

【讨论】:

  • 非常感谢,我真的很感激,但是第 6 行 public Rsa() 有一个简单的错误,你能告诉我如何解决它吗:(再次感谢你
  • @FtounAlmutairi 你能解释一下问题是什么吗?程序在我的机器上使用 jdk 11.0.2 编译并运行成功。
  • 非常感谢我尝试在 NetBeans 上更改程序包名称和整个项目,现在它可以正常工作了,非常感谢,但我想问一下加密消息是否出现在语句之前“加密的消息是“?
  • 加密后的信息显示为数字,与原文不一样,请问有办法解决吗?
  • 好的,我知道你的意思:输出是正确的,但日志可能不那么明显。我已经编辑了代码,看看新版本和示例输出。现在一切都应该清楚了。
猜你喜欢
  • 1970-01-01
  • 2019-08-12
  • 2013-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-07
  • 2011-05-27
  • 1970-01-01
相关资源
最近更新 更多