2016-01-21 39 views
1

文件我發現了一個問題,其中來自Elephantik得到的答案基本answerd我的問題: DES Initialization Vector in C#DES decryting在Java中從DES.EXE

我這是用DES.EXE命令行工具加密的文件。我可以使用以下命令對其進行解密:「des -D -k YSTxyHBH file.cr file.txt」

使用此命令,我得到一個解密的file.txt,但我需要在Java中解密此文件。

所以我試圖將解決方案從Elephantik轉移到Java,但是我的解決方案必須有問題,因爲結果我只有在我調用decryptData(...)方法時纔得到一些加密文本。

public byte[] decryptData(byte input[], String password) throws Exception { 
    byte[] result = null; 
    //Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); 
    Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding"); 
    //byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0 }; 
    byte[] iv = { -128, -128, -128, -128, -128, -128, -128, -128 }; 
    IvParameterSpec ivspec = new IvParameterSpec(iv); 
    cipher.init(Cipher.DECRYPT_MODE, generateSecretKey(passwordToKey(password)), ivspec); 
    result = cipher.doFinal(input); 
    return result; 
} 

protected SecretKey generateSecretKey(byte[] key) throws Exception { 
    SecretKeyFactory factory = SecretKeyFactory.getInstance("DES"); 
    KeySpec keySpec = new DESKeySpec(key); 
    SecretKey secretKey = factory.generateSecret(keySpec); 
    return secretKey; 
} 

public byte[] passwordToKey(String password) throws Exception 
{ 
    if (password == null) 
     throw new IllegalArgumentException("password"); 
    if (password == "") 
     throw new IllegalArgumentException("password"); 

    byte[] key = new byte[8]; 

    for (int i = 0; i < password.length(); i++) 
    { 
     int c = (int)password.charAt(i); 
     if ((i % 16) < 8) 
     { 
      key[i % 8] ^= (byte)(c << 1); 
     } 
     else 
     { 
      // reverse bits e.g. 11010010 -> 01001011 
      c = (((c << 4) & 0xf0) | ((c >> 4) & 0x0f)); 
      c = (((c << 2) & 0xcc) | ((c >> 2) & 0x33)); 
      c = (((c << 1) & 0xaa) | ((c >> 1) & 0x55)); 
      key[7 - (i % 8)] ^= (byte)c; 
     } 
    } 

    addOddParity(key); 

    byte[] target = new byte[8]; 
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
    outputStream.write(password.getBytes("US-ASCII")); 
    outputStream.write(new byte[8]); 
    byte[] temp = outputStream.toByteArray(); 
    outputStream = new ByteArrayOutputStream(); 
    for (int i = 0; i < (password.length() + (8 - (password.length() % 8)) % 8); ++i) { 
     outputStream.write(temp[i]); 
    } 
    byte[] passwordBuffer = outputStream.toByteArray(); 

    Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding"); 
    //byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0 }; 
    byte[] iv = { -128, -128, -128, -128, -128, -128, -128, -128 }; 
    IvParameterSpec ivspec = new IvParameterSpec(iv); 
    cipher.init(Cipher.ENCRYPT_MODE, generateSecretKey(key), ivspec); 
    for (int x = 0; x < passwordBuffer.length/8; ++x) 
    { 
     cipher.update(passwordBuffer, 8 * x, 8, target, 0); 
    } 

    addOddParity(target); 

    return target; 
} 

private void addOddParity(byte[] buffer) 
{ 
    for (int i = 0; i < buffer.length; ++i) 
    { 
     buffer[i] = _oddParityTable[buffer[i] & 0xFF]; 
    } 
} 

private static byte[] _oddParityTable = { 
    -127,-127,-126,-126,-124,-124,-121,-121,-120,-120,-117,-117,-115,-115,-114,-114, 
    -112,-112,-109,-109,-107,-107,-106,-106,-103,-103,-102,-102,-100,-100, -97, -97, 
    -96, -96, -93, -93, -91, -91, -90, -90, -87, -87, -86, -86, -84, -84, -81, -81, 
    -79, -79, -78, -78, -76, -76, -73, -73, -72, -72, -69, -69, -67, -67, -66, -66, 
    -64, -64, -61, -61, -59, -59, -58, -58, -55, -55, -54, -54, -52, -52, -49, -49, 
    -47, -47, -46, -46, -44, -44, -41, -41, -40, -40, -37, -37, -35, -35, -34, -34, 
    -31, -31, -30, -30, -28, -28, -25, -25, -24, -24, -21, -21, -19, -19, -18, -18, 
    -16, -16, -13, -13, -11, -11, -10, -10, -7, -7, -6, -6, -4, -4, -1, -1, 
     0, 0, 3, 3, 5, 5, 6, 6, 9, 9, 10, 10, 12, 12, 15, 15, 
    17, 17, 18, 18, 20, 20, 23, 23, 24, 24, 27, 27, 29, 29, 30, 30, 
    33, 33, 34, 34, 36, 36, 39, 39, 40, 40, 43, 43, 45, 45, 46, 46, 
    48, 48, 51, 51, 53, 53, 54, 54, 57, 57, 58, 58, 60, 60, 63, 63, 
    65, 65, 66, 66, 68, 68, 71, 71, 72, 72, 75, 75, 77, 77, 78, 78, 
    80, 80, 83, 83, 85, 85, 86, 86, 89, 89, 90, 90, 92, 92, 95, 95, 
    96, 96, 99, 99, 101, 101, 102, 102, 105, 105, 106, 106, 108, 108, 111, 111, 
    113, 113, 114, 114, 116, 116, 119, 119, 120, 120, 123, 123, 125, 125, 126, 126 
}; 

所以希望有人能幫助我解決我的問題。

問候邁克爾

+0

你能描述更加清楚你得到什麼,什麼指望得到什麼?你能舉一個例子輸出嗎? –

+0

我得到了一個test.txt文件,其中帶有「Hello」文本。 如果我調用命令「des -E -k testkeyy test.txt test.cr」,我就會得到一個帶有文本「i¹^,ua-」的文件test.cr。 當我調用命令「des -D -k testkeyy test.cr test.txt」時,我再次得到文本「Hello」的test.txt文件。 如果我從字符數組調用decryptData(...)方法,如果從文件和密鑰「testkeyy」得到輸出「^!Èe¹õ2ª」。 –

+0

Hi @MichaelP。我有同樣的問題,你有沒有找到解決方案? – Michele

回答

0

邁克爾,在我的代碼中發現了幾個錯誤。檢查線路cipher.init(Cipher.ENCRYPT_MODE, generateSecretKey(key), ivspec);您需要將相同的關鍵初始化向量,而不是你有四。 des.exe程序基於LibDes庫的源代碼。你可以在文檔和源代碼中找到所有的細節。你有提到des -D參數。這意味着你需要解密DESCBC/NoPadding模式。請檢查您的方法_oddParityTable

如果您的文件不是UUdecoded,請省略我的代碼中的相關部分。

這裏準備的Java例子:

public class UUDES { 

    public static void main (String[] args) throws Exception 
    {         
     String password = "xxxxxx"; 
     String pathToUUEencodedEncryptedFile = "C:\DES\path-to-decoded-and-encrypted-file"; 

     byte[] secretKey = passwordToKey(password); 
     byte[] iv = new byte[8];   
     byte[] uuEncodedFile = Files.readAllBytes(Paths.get(pathToUUEencodedEncryptedFile)); 

     SecretKey key = new SecretKeySpec(secretKey, "DES"); 

     Cipher decryptor = Cipher.getInstance("DES/CBC/NoPadding"); 
     decryptor.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));   

     ByteArrayOutputStream bout = new ByteArrayOutputStream(); 
     InputStream in = null;  
     try { 
      in = MimeUtility.decode(new ByteArrayInputStream(uuEncodedFile), "uuencode"); 
      byte[] buf = new byte[1024]; 
      int length; 
      while (true) { 
       length = in.read(buf); 
       if (length == -1) { 
        break; 
       } 
       bout.write(buf, 0, length); 
      } 

      byte[] bytesDecrypted = decryptor.doFinal(bout.toByteArray()); 

      ByteArrayInputStream bais = new ByteArrayInputStream(bytesDecrypted); 
      GZIPInputStream gzis = new GZIPInputStream(bais); 
      InputStreamReader reader = new InputStreamReader(gzis); 
      BufferedReader buffer = new BufferedReader(reader); 

      String readed; 
      while ((readed = buffer.readLine()) != null) { 
       System.out.println(readed); 
      }        
     } 
     finally { 
      if (in != null) { 
       try { 
        in.close(); 
       } 
       catch (IOException e) { 
        System.out.println(e.getMessage()); 
       } 
      } 
     }         
    } 

    static SecretKey generateSecretKey(byte[] key) throws Exception { 
     SecretKeyFactory factory = SecretKeyFactory.getInstance("DES"); 
     KeySpec keySpec = new DESKeySpec(key); 
     SecretKey secretKey = factory.generateSecret(keySpec); 
     return secretKey; 
    } 

    static byte[] passwordToKey(String password) throws Exception 
    { 
     if (password == null) 
      throw new IllegalArgumentException("password"); 
     if (password == "") 
      throw new IllegalArgumentException("password"); 

     byte[] key = new byte[8]; 

     for (int i = 0; i < password.length(); i++) 
     { 
      int c = (int)password.charAt(i); 
      if ((i % 16) < 8) 
      { 
       key[i % 8] ^= (byte)(c << 1); 
      } 
      else 
      { 
       // reverse bits e.g. 11010010 -> 01001011 
       c = (((c << 4) & 0xf0) | ((c >> 4) & 0x0f)); 
       c = (((c << 2) & 0xcc) | ((c >> 2) & 0x33)); 
       c = (((c << 1) & 0xaa) | ((c >> 1) & 0x55)); 
       key[7 - (i % 8)] ^= (byte)c; 
      } 
     } 

     addOddParity(key); 

     byte[] target = new byte[8]; 
     ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
     outputStream.write(password.getBytes("US-ASCII")); 
     outputStream.write(new byte[8]); 
     byte[] temp = outputStream.toByteArray(); 
     outputStream = new ByteArrayOutputStream(); 
     for (int i = 0; i < (password.length() + (8 - (password.length() % 8)) % 8); ++i) { 
      outputStream.write(temp[i]); 
     } 
     byte[] passwordBuffer = outputStream.toByteArray(); 

     Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding"); 
     byte[] iv = key; 

     IvParameterSpec ivspec = new IvParameterSpec(iv); 
     cipher.init(Cipher.ENCRYPT_MODE, generateSecretKey(key), ivspec); 
     for (int x = 0; x < passwordBuffer.length/8; ++x) 
     { 
      cipher.update(passwordBuffer, 8 * x, 8, target, 0); 
     } 

     addOddParity(target); 

     return target; 
    } 

    static void addOddParity(byte[] buffer) 
    { 
     for (int i = 0; i < buffer.length; ++i) 
     { 
      buffer[i] = _oddParityTable[buffer[i] & 0xFF]; 
     } 
    } 

    static byte[] _oddParityTable = { 
      (byte)1,(byte)1,(byte)2,(byte)2,(byte)4,(byte)4,(byte)7,(byte)7,(byte)8,(byte)8,(byte)11,(byte)11,(byte)13,(byte)13,(byte)14,(byte)14, 
      (byte)16,(byte)16,(byte)19,(byte)19,(byte)21,(byte)21,(byte)22,(byte)22,(byte)25,(byte)25,(byte)26,(byte)26,(byte)28,(byte)28,(byte)31,(byte)31, 
      (byte)32,(byte)32,(byte)35,(byte)35,(byte)37,(byte)37,(byte)38,(byte)38,(byte)41,(byte)41,(byte)42,(byte)42,(byte)44,(byte)44,(byte)47,(byte)47, 
      (byte)49,(byte)49,(byte)50,(byte)50,(byte)52,(byte)52,(byte)55,(byte)55,(byte)56,(byte)56,(byte)59,(byte)59,(byte)61,(byte)61,(byte)62,(byte)62, 
      (byte)64,(byte)64,(byte)67,(byte)67,(byte)69,(byte)69,(byte)70,(byte)70,(byte)73,(byte)73,(byte)74,(byte)74,(byte)76,(byte)76,(byte)79,(byte)79, 
      (byte)81,(byte)81,(byte)82,(byte)82,(byte)84,(byte)84,(byte)87,(byte)87,(byte)88,(byte)88,(byte)91,(byte)91,(byte)93,(byte)93,(byte)94,(byte)94, 
      (byte)97,(byte)(byte)97,(byte)(byte)98,(byte)(byte)98,(byte)100,(byte)100,(byte)103,(byte)103,(byte)104,(byte)104,(byte)107,(byte)107,(byte)109,(byte)109,(byte)110,(byte)110, 
      (byte)112,(byte)112,(byte)115,(byte)115,(byte)117,(byte)117,(byte)118,(byte)118,(byte)121,(byte)121,(byte)122,(byte)122,(byte)124,(byte)124,(byte)127,(byte)127, 
      (byte)128,(byte)128,(byte)131,(byte)131,(byte)133,(byte)133,(byte)134,(byte)134,(byte)137,(byte)137,(byte)138,(byte)138,(byte)140,(byte)140,(byte)143,(byte)143, 
      (byte)145,(byte)145,(byte)146,(byte)146,(byte)148,(byte)148,(byte)151,(byte)151,(byte)152,(byte)152,(byte)155,(byte)155,(byte)157,(byte)157,(byte)158,(byte)158, 
      (byte)161,(byte)161,(byte)162,(byte)162,(byte)164,(byte)164,(byte)167,(byte)167,(byte)168,(byte)168,(byte)171,(byte)171,(byte)173,(byte)173,(byte)174,(byte)174, 
      (byte)176,(byte)176,(byte)179,(byte)179,(byte)181,(byte)181,(byte)182,(byte)182,(byte)185,(byte)185,(byte)186,(byte)186,(byte)188,(byte)188,(byte)191,(byte)191, 
      (byte)193,(byte)193,(byte)194,(byte)194,(byte)196,(byte)196,(byte)199,(byte)199,(byte)200,(byte)200,(byte)203,(byte)203,(byte)205,(byte)205,(byte)206,(byte)206, 
      (byte)208,(byte)208,(byte)211,(byte)211,(byte)213,(byte)213,(byte)214,(byte)214,(byte)217,(byte)217,(byte)218,(byte)218,(byte)220,(byte)220,(byte)223,(byte)223, 
      (byte)224,(byte)224,(byte)227,(byte)227,(byte)229,(byte)229,(byte)230,(byte)230,(byte)233,(byte)233,(byte)234,(byte)234,(byte)236,(byte)236,(byte)239,(byte)239, 
      (byte)241,(byte)241,(byte)242,(byte)242,(byte)244,(byte)244,(byte)247,(byte)247,(byte)248,(byte)248,(byte)251,(byte)251,(byte)253,(byte)253,(byte)254,(byte)254};  
}