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

时间:2014-02-06 05:01:04

标签: java encryption encoding cryptography rsa

我尝试使用我自己的Java中的RSA实现来加密和解密字符串,并最终使用明文文件。我曾尝试在SO和网络上关注无数的例子,其中人们使用内置的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

2 个答案:

答案 0 :(得分:1)

几点说明:

  1. 您的模数(示例中的n)必须至少与您要加密的信息量一样长。这是RSA的一个警告,这就是为什么像AES这样的东西更适合文件等更长的流。以下我选择了128作为pq而不是10的范围,其他值也可以使用。
  2. 这是cipherText.modPow(d, n)
  3. 您必须将BigInteger转换回String才能正确打印,因此:new String(originalMessage.toByteArray())
  4. 全部放在一起:

    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);
    

答案 1 :(得分:0)

是的,但E应该是一个随机数,对于phi来说是相对优质的。所以,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。所以要小心。