Java 使用自己的RSA实现加密纯文本

Java 使用自己的RSA实现加密纯文本,java,encryption,encoding,cryptography,rsa,Java,Encryption,Encoding,Cryptography,Rsa,我试图用我自己的RSA Java实现加密和解密一个字符串,最终是一个包含明文的文件。我在SO和web上尝试了无数的例子,人们要么使用内置的Java RSA函数,要么使用他们自己的算法实现,但都无法实现,因为解密的文本与原始字符串从不匹配 我不知道我的文本编码/解码是否有问题,我尝试过在java.xml.*中使用默认UTF-8和Base64编码器,但也没有成功。我没有使用任何填充,我不知道这是否对它的工作是必要的,我只是使用一个任意的密钥长度,我试图改变的大小,但也不能使事情的工作。这只是我自己的

我试图用我自己的RSA Java实现加密和解密一个字符串,最终是一个包含明文的文件。我在SO和web上尝试了无数的例子,人们要么使用内置的Java RSA函数,要么使用他们自己的算法实现,但都无法实现,因为解密的文本与原始字符串从不匹配

我不知道我的文本编码/解码是否有问题,我尝试过在
java.xml.*
中使用默认UTF-8和Base64编码器,但也没有成功。我没有使用任何填充,我不知道这是否对它的工作是必要的,我只是使用一个任意的密钥长度,我试图改变的大小,但也不能使事情的工作。这只是我自己的一个练习,任何人的信息都不会受到这个或任何东西的保护。但是我不确定问题出在哪里,所以这是我的代码,它试图加密/解密一个简单的字符串:

   BigInteger ONE = new BigInteger("1");
   SecureRandom rand = new SecureRandom();

   BigInteger d;
   BigInteger e;
   BigInteger n;
   BigInteger p = BigInteger.probablePrime(10, rand); // 10 is arbitrary, have tried different numbers
   BigInteger q = BigInteger.probablePrime(10, rand);
   BigInteger phi = (p.subtract(ONE)).multiply(q.subtract(ONE));

   n = p.multiply(q); //10 bits * 10 bits = ??? bits for key length
   e = new BigInteger("65537"); //public key exponent 
   d = e.modInverse(phi); //private key exponent

   String string = "this is a test";
   byte[] bytes = string.getBytes();
   BigInteger plainText = new BigInteger(bytes);
   BigInteger cipherText = plainText.modPow(e, n);
   BigInteger originalMessage = cipherText.modPow(d, e);

   System.out.println(string.getBytes());
   System.out.println(cipherText);
   System.out.println(originalMessage);
每次运行程序时,这三种输出的值都不同: 但它们总是以相同的相对形式出现:

[B@52d85409
157529
24312
几点注意:

  • 您的模数(示例中的
    n
    )需要至少与要加密的信息量一样长。这是RSA的一个警告,这就是为什么AES这样的东西更适合像文件这样的较长流。下面我选择了
    128
    作为
    p
    q
    的范围,而不是
    10
    ,其他值也可以工作
  • 它是密文.modPow(d,n)
  • 必须将BigInteger转换回字符串才能正确打印,因此:
    新字符串(originalMessage.toByteArray())
  • 总而言之:

    BigInteger ONE = new BigInteger("1");
    SecureRandom rand = new SecureRandom();
    
    BigInteger d, e, n;
    BigInteger p = BigInteger.probablePrime(128, rand);
    BigInteger q = BigInteger.probablePrime(128, rand);
    BigInteger phi = (p.subtract(ONE)).multiply(q.subtract(ONE));
    
    n = p.multiply(q);
    e = new BigInteger("65537");
    d = e.modInverse(phi);
    
    String string = "this is a test";
    BigInteger plainText = new BigInteger(string.getBytes());
    BigInteger cipherText = plainText.modPow(e, n);
    BigInteger originalMessage = cipherText.modPow(d, n);
    String decrypted = new String(originalMessage.toByteArray());
    
    System.out.println("original: " + string);
    System.out.println("decrypted: " + decrypted);
    

    是的,但是E应该是一个相对于φ的素数的随机数。所以,E应该等于这样的值:

        BigInteger e = new BigInteger("65537"); //to make the compiler happy
        BigInteger counter = (BigInteger.probablePrime(128, random)).mod(phi);
        while(counter.intValue() > 2)
        {
            if((e.gcd(phi)).intValue() == 1)
            {
                e = counter;
                break;
            }
            counter = counter.subtract(BigInteger.ONE);
        }
    
    此外,在解密不起作用之前,您可以输入的最大字符数为32。所以要小心。

    new Sting(byte[])构造函数和
    String.getBytes()
    方法使用默认的字符编码,这种编码因系统而异。您需要明确指定编码。(如有疑问,请参阅UTF-8。)