2014-02-06 34 views
0

我試圖使用我自己的Java中的RSA實現來加密和解密字符串,並最終生成一個包含明文的文件。我試着在SO和Web上嘗試過無數的例子,其中人們使用內置的Java RSA函數或者它們自己的算法實現,但是不能讓它們中的任何一個工作,因爲解密後的文本永遠不會匹配原始字符串。使用自己的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); 

輸出有不同的價值觀對所有三件事情,每次我跑我的程序: 但他們總是在相同的相對形式:

[[email protected] 
157529 
24312 

回答

1

幾個注意事項:

  1. 你的模量(在n在你的例子)需要爲至少只要是作爲量您想要加密的信息。這是RSA的一個注意事項,這就是爲什麼像AES這樣的東西更適合更長的文件流。下面我選擇了128,範圍爲pq,而不是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); 
+1

'新的Sting(byte [])'構造函數和'String.getBytes()'方法使用默認的字符編碼,因系統而異。您需要明確指定編碼。 (如有疑問,請使用UTF-8。) – ntoskrnl

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。所以要小心。