2011-02-04 93 views
2

我試圖使用ElGamal爲我的研究加密和解密文本文件,但似乎我無法使其正常工作。 我有一組文本文件,大小從1kb到1mb不等,而我的密鑰大小是512bit。我已經知道,就像RSA一樣,ELGamal不能加密超過其模數的值,因此我決定將每個文件分成塊(小於其模數),以便能夠對它進行加密幸運的是這些解決方案適用於加密。我的問題是,當我試圖解密它時,生成的輸出不是我期望看到的實際輸出。我不知道我的問題是什麼原因,我真的需要在幾天內找到解決方案。如何使用ElGamal加密/解密文本文件

我會告訴你一些我的代碼片段,只是爲了說清楚。

我曾致電

public static void encryptFile(String srcFileName, String destFileName, PublicKey key) throws Exception 
{ 
    encryptDecryptFile(srcFileName,destFileName, key, Cipher.ENCRYPT_MODE); 
} 

產生我的密鑰對具有下列

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ElGamal", "BC"; 
keyGen.initialize(512); 

我加密和我通過調用

public static void decryptFile(String srcFileName, String destFileName, PrivateKey key) throws Exception 
{ 
    encryptDecryptFile(srcFileName,destFileName, key, Cipher.DECRYPT_MODE); 
} 

解密這裏的encryptDecryptFile的定義(.. )方法

public static void encryptDecryptFile(String srcFileName, String destFileName, Key key, int cipherMode) throws Exception 
    { 
     OutputStream outputWriter = null; 
     InputStream inputReader = null; 
     try 
     { 
      Cipher cipher = Cipher.getInstance("ElGamal/None/NoPadding", "BC""); 
      String textLine = null; 
    //buffer(my chunks) depends wether it is encyption or decryption 
      byte[] buf = (cipherMode == Cipher.ENCRYPT_MODE? new byte[50] : new byte[64]); 
      int bufl; 
      // init the Cipher object for Encryption... 
      cipher.init(cipherMode, key); 

      // start FileIO 
      outputWriter = new FileOutputStream(destFileName); 
      inputReader = new FileInputStream(srcFileName); 
      while ((bufl = inputReader.read(buf)) != -1) 
      { 
       byte[] encText = null; 
       if (cipherMode == Cipher.ENCRYPT_MODE) 
       { 
         encText = encrypt(copyBytes(buf,bufl),(PublicKey)key); 
       } 
       else 
       { 
        if (_log.isDebugEnabled()) 
        { 
         System.out.println("buf = " + new String(buf)); 
        } 
        encText = decrypt(copyBytes(buf,bufl),(PrivateKey)key); 
       } 
       outputWriter.write(encText); 
       if (_log.isDebugEnabled()) 
       { 
        System.out.println("encText = " + new String(encText)); 
       } 
      } 
      outputWriter.flush(); 

     } 
     catch (Exception e) 
     { 
      _log.error(e,e); 
      throw e; 
     } 
     finally 
     { 
      try 
      { 
       if (outputWriter != null) 
       { 
        outputWriter.close(); 
       } 
       if (inputReader != null) 
       { 
        inputReader.close(); 
       } 
      } 
      catch (Exception e) 
      { 
       // do nothing... 
      } // end of inner try, catch (Exception)... 
     } 
    } 

對於copyBytes:

public static byte[] copyBytes(byte[] arr, int length) 
{ 
    byte[] newArr = null; 
    if (arr.length == length) 
    { 
     newArr = arr; 
    } 
    else 
    { 
     newArr = new byte[length]; 
     for (int i = 0; i < length; i++) 
     { 
      newArr[i] = (byte) arr[i]; 
     } 
    } 
    return newArr; 
} 

對於encypt(...)

public static byte[] encrypt(byte[] text, PublicKey key) throws Exception 
{ 
    byte[] cipherText = null; 
    try 
    { 

     Cipher cipher = Cipher.getInstance("ElGamal/None/NoPadding", "BC""); 
     if (_log.isDebugEnabled()) 
     { 
      _log.debug("\nProvider is: " + cipher.getProvider().getInfo()); 
      _log.debug("\nStart encryption with public key"); 
     } 

     // encrypt the plaintext using the public key 
     cipher.init(Cipher.ENCRYPT_MODE, key); 
     cipherText = cipher.doFinal(text); 
    } 
    catch (Exception e) 
    { 
     _log.error(e, e); 
     throw e; 
    } 
    return cipherText; 
} 

和解密(..)

public static byte[] decrypt(byte[] text, PrivateKey key) throws Exception 
    { 
     byte[] dectyptedText = null; 
     try 
     { 
      // decrypt the text using the private key 
      Cipher cipher = Cipher.getInstance("ElGamal/None/NoPadding", "BC""); 
       cipher.init(Cipher.DECRYPT_MODE, key); 
      dectyptedText = cipher.doFinal(text); 
     } 
     catch (Exception e) 
     { 
      _log.error(e, e); 
      throw e; 
     } 
     return dectyptedText; 

    } 

原始代碼由阿維朗盟

我認爲這就是你需要的一切,只要告訴我你是否想看完整的源代碼。 謝謝,

回答

2

我終於有了解決方案,無論如何我只是把它放在這裏,以防萬一有人也遇到同樣的問題。所有你所要做的就是更換

byte[] buf = (cipherMode == Cipher.ENCRYPT_MODE? new byte[50] : new byte[64]); 
在encryptDecryptFile

(..)方法

byte[] buf = (cipherMode == Cipher.ENCRYPT_MODE? new byte[50] : new byte[128]); 

以來的ElGamal 512密鑰大小加密50B時產生的128B。我希望這很清楚。

2

這與您的代碼並不完全相關,但它嘗試將具有固定寬度塊大小的塊密碼轉換爲可通過僅分裂來處理流的塊密碼輸入到塊並加密它們中的每一個。如果你這樣做,你基本上正在做一個美化的單字母替換密碼,其中每個「字符」是一個區塊寬。這使得攻擊者可以恢復輸入結構的一部分,從而破壞了您通常從這些密碼基元中獲得的保證。作爲一個例子,請參閱this Wikipedia discussion of this particular mode of encryption並查看它如何加密Linux企鵝的Tux。加密的圖像立即允許您查看輸入的結構。

如果您想使用塊密碼一樣的ElGamal加密文本流,你應該使用更復雜的結構像cipher block chaining (CBC)counter mode (CTR),這是可證明密碼在合理的規模投入安全。如果您使用其中一種模式,攻擊者會極度困難地試圖破壞您的安全。

對於沒有任何關於您的代碼更實質的說法,我表示抱歉,但我真的認爲在嘗試調試此代碼之前,應該備份並選擇一個強大的加密系統。否則,你最終會得到一個聰明的攻擊者可以阻止的系統。

+0

嗨, 感謝您的回覆,但我認爲我必須對此有更具體的瞭解。我非常感謝你給出這樣的提示,但是我最關心的並不是算法本身的安全性。我的研究重點是如何輸入類型(可能是所有字母,數字,字母數字符號或四個組合 - 我使用組合輸入類型作爲我的控件)會影響算法的速度,我的測試算法之一是elgamal 。如果有人能夠給我一個建議,我會很高興,再次感謝你的快速回復templatetypedef。 – celax 2011-02-04 10:08:17