【问题标题】:Encrypting plain text using own RSA implementation使用自己的 RSA 实现加密纯文本
【发布时间】:2014-02-13 03:51:21
【问题描述】:

我正在尝试使用我自己在 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

【问题讨论】:

    标签: java encryption encoding cryptography rsa


    【解决方案1】:

    几个注意事项:

    1. 您的模数(在您的示例中为 n)至少需要与您要加密的信息量一样长。这是 RSA 的警告之一,这就是为什么像 AES 这样的东西更适合像文件这样的较长流。下面我选择了128 作为p 和q 的范围,而不是10,其他值也可以。
    2. 是cipherText.modPow(d, n)
    3. 您必须将 BigInteger 转换回字符串才能正确打印,所以:new String(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);
    

    【讨论】:

    • new Sting(byte[]) 构造函数和String.getBytes() 方法使用默认字符编码,因系统而异。您需要明确指定编码。 (如有疑问,UTF-8。)
    【解决方案2】:

    是的,但是 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 个字符。所以要小心。

    【讨论】:

      猜你喜欢
      • 2019-05-09
      • 1970-01-01
      • 2013-01-02
      • 2019-10-12
      • 1970-01-01
      • 1970-01-01
      • 2011-12-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多