2016-01-28 12 views
1

我有一個與文件解密相關的特定問題。我發現了一個Java程序,解密特定文件(這是遊戲中的保存文件,你可以在這裏找到這個文件的例子:https://www.adrive.com/public/6DBShx/game.sii),我想把這個程序改寫成C# - 這樣我就可以將它整合到不同的程序中我用C#寫的。 這是我第一次使用加密文件,所以我製作的程序無法正常工作,實際上我不知道如何調試它。我寫的程序有固定的文件路徑 - 這是臨時解決方案。將AES文件解密程序從Java重寫爲C#

原始的Java程序:

package scsc; 

import javax.crypto.Cipher; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.SecretKeySpec; 
import java.io.*; 
import java.lang.reflect.Field; 
import java.nio.charset.Charset; 
import java.nio.file.Files; 
import java.nio.file.StandardCopyOption; 
import java.security.Permission; 
import java.security.PermissionCollection; 
import java.util.Map; 
import java.util.zip.InflaterInputStream; 

/* 
* Published under the Do What the Fuck You Want to Public License (  http://www.wtfpl.net/) 
*/ 
public class ScsC { 
private static byte[] AES_KEY = new byte[]{ 
     (byte) 0x2a, (byte) 0x5f, (byte) 0xcb, (byte) 0x17, 
     (byte) 0x91, (byte) 0xd2, (byte) 0x2f, (byte) 0xb6, 
     (byte) 0x02, (byte) 0x45, (byte) 0xb3, (byte) 0xd8, 
     (byte) 0x36, (byte) 0x9e, (byte) 0xd0, (byte) 0xb2, 
     (byte) 0xc2, (byte) 0x73, (byte) 0x71, (byte) 0x56, 
     (byte) 0x3f, (byte) 0xbf, (byte) 0x1f, (byte) 0x3c, 
     (byte) 0x9e, (byte) 0xdf, (byte) 0x6b, (byte) 0x11, 
     (byte) 0x82, (byte) 0x5a, (byte) 0x5d, (byte) 0x0a, 
}; 

public static void main(String[] args) throws Exception { 
    if (args.length < 1) { 
     System.out.println("ERROR: expecting at least one file."); 
    } else { 
     removeCryptographyRestrictions(); 
     for (String filename : args) { 
      decrypt(filename); 
     } 
    } 
} 

private static void decrypt(String filename) throws Exception { 
    File scsc = new File(filename); 
    if (!scsc.isFile() || !scsc.canWrite()) { 
     throw new IllegalArgumentException(filename + " is not a writable file."); 
    } 
    boolean encrypted = isEncrypted(scsc); 
    if (!encrypted) { 
     System.out.println(scsc + " does not seem to be encrypted."); 
    } else { 
     File decrypted = decrypt(scsc); 
     Files.copy(decrypted.toPath(), scsc.toPath(), StandardCopyOption.REPLACE_EXISTING); 
     System.out.println("decrypted: " + scsc); 
    } 
} 

private static boolean isEncrypted(File file) throws Exception { 
    byte[] header = new byte[4]; 
    FileInputStream fis = new FileInputStream(file); 
    if (fis.read(header) != header.length) { 
     throw new RuntimeException("could not read header of " + file); 
    } 
    fis.close(); 
    String headerAsString = new String(header, Charset.forName("UTF-8")); 
    return "ScsC".equals(headerAsString); 
} 

private static File decrypt(File input) throws Exception { 
    File out = File.createTempFile("scsc-", ".tmp"); 
    out.deleteOnExit(); 

    byte[] data = new byte[(int) (input.length())]; 
    FileInputStream fis = new FileInputStream(input); 
    if (fis.read(data) != data.length) { 
     throw new RuntimeException("Could not read " + input + " into memory"); 
    } 
    fis.close(); 

    byte[] cipherText = new byte[data.length - 0x38]; 
    byte[] iv = new byte[0x10]; 
    System.arraycopy(data, 0x38, cipherText, 0, cipherText.length); 
    System.arraycopy(data, 0x24, iv, 0, iv.length); 
    byte[] decrypted = decrypt(cipherText, AES_KEY, iv); 

    ByteArrayInputStream bis = new ByteArrayInputStream(decrypted); 
    InflaterInputStream iis = new InflaterInputStream(bis); 
    InputStreamReader ir = new InputStreamReader(iis); 
    BufferedReader br = new BufferedReader(ir); 

    FileOutputStream fos = new FileOutputStream(out); 
    OutputStreamWriter osw = new OutputStreamWriter(fos); 
    PrintWriter pw = new PrintWriter(osw); 

    for (String line = br.readLine(); line != null; line = br.readLine()) { 
     pw.println(line); 
    } 
    pw.close(); 
    br.close(); 

    return out; 
} 

private static byte[] decrypt(byte[] cipherText, byte[] keyBytes, byte[] iv) throws Exception { 
    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); 
    SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); 
    cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); 
    return cipher.doFinal(cipherText); 
} 

private static void removeCryptographyRestrictions() throws Exception { 
    // taken from http://stackoverflow.com/questions/1179672/unlimited-strength-jce-policy-files 
    final Class<?> jceSecurity = Class.forName("javax.crypto.JceSecurity"); 
    final Class<?> cryptoPermissions = Class.forName("javax.crypto.CryptoPermissions"); 
    final Class<?> cryptoAllPermission = Class.forName("javax.crypto.CryptoAllPermission"); 

    final Field isRestrictedField = jceSecurity.getDeclaredField("isRestricted"); 
    isRestrictedField.setAccessible(true); 
    isRestrictedField.set(null, false); 

    final Field defaultPolicyField = jceSecurity.getDeclaredField("defaultPolicy"); 
    defaultPolicyField.setAccessible(true); 
    final PermissionCollection defaultPolicy = (PermissionCollection) defaultPolicyField.get(null); 

    final Field perms = cryptoPermissions.getDeclaredField("perms"); 
    perms.setAccessible(true); 
    ((Map<?, ?>) perms.get(defaultPolicy)).clear(); 

    final Field instance = cryptoAllPermission.getDeclaredField("INSTANCE"); 
    instance.setAccessible(true); 
    defaultPolicy.add((Permission) instance.get(null)); 
} 
} 

我的代碼,我在C#寫的農產品似乎工作,但並不如預期輸出... 預期的結果應該是可讀的文件(鏈接:https://www.adrive.com/public/E3rsfv/game.sii_decrypted_by_java

第一解密文件的幾行:

SiiNunit 
{ 
economy : _nameless.0357.B5D0 { 
bank: _nameless.0371.CD48 
player: _nameless.0369.3070 
companies: 811 
companies[0]: company.volatile.trameri.esbjerg 
companies[1]: company.volatile.bcp.turku 
companies[2]: company.volatile.itcc.liege 
companies[3]: company.volatile.tree_et.geneve 
companies[4]: company.volatile.tree_et.arhus 
companies[5]: company.volatile.itcc.jonkoping 
companies[6]: company.volatile.kaarfor.poznan 
companies[7]: company.volatile.fcp.milano 
companies[8]: company.volatile.posped.swansea 
companies[9]: company.volatile.tradeaux.lille 
companies[10]: company.volatile.euroacres.osnabruck 

用C#解密 - 我不能把許多環節在這裏:(

前幾行:

 xڬ�M�$������C��4fcm�o��#=-  ��rLV������̪[���<�8�J��F����t��C������:�>������>Ƿ_��Ƿ ��m��~|�9�T����ߦ?�����*[�����X��} ���=����S�������9��Q����?�����~����|���?? O���������ӳx�Y<<����uz�PoAw����w���������������~sz�� ������z|��Wf��ٜ�O�6�/�;I�m���[-����}�������c��T��| ��D��K�8S�ۯ�q�x�~�y�8lN_���)7�������ux��xг���@}l�����15} x�������c��#Ul�>>���͛|�T����>�q�����py�! ����X�'�tW����!��ow�w��۸c�Ə��^κ �ŗ�{�I�P���7���9<| ��O�}�������6_�ؾ=��}�����{RVħ�9��?��i�|A�awz#;���w�Km� %�3a�"~ݜ��9y4�����r�6����ގ_�/ �1<ݍqL����w�����=�l~���H\�y4J������(gU(k��m�S�S���es8��3m Ű,�M��_��~��w� ��S- ��Y|z�KP�P�����:ֆ������G�q��v�&�QLp6��C}<? �G5�cY�����q��)���q�D�|ڪε�i�����XI��>Ӕ_:c� 
��~�<�1��h���=���{8m��G�8X��ٞҚB�6�Oۅ�Jy<�>���� ����b�Mu�l�v�W[u 
�]�V'�����帗�Cv��H�C��9 ����t�e��V�������^�Cy�߁oIñ���r�����R΃��H���C{�����ӏ�m ��� 

和類,在C#創建此:

public partial class Form1 : Form 
    { 
     string file_original; 
     byte[] file_orig_bytes; 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      byte[] AES_KEY = new byte[]{ 
      (byte) 0x2a, (byte) 0x5f, (byte) 0xcb, (byte) 0x17, 
      (byte) 0x91, (byte) 0xd2, (byte) 0x2f, (byte) 0xb6, 
      (byte) 0x02, (byte) 0x45, (byte) 0xb3, (byte) 0xd8, 
      (byte) 0x36, (byte) 0x9e, (byte) 0xd0, (byte) 0xb2, 
      (byte) 0xc2, (byte) 0x73, (byte) 0x71, (byte) 0x56, 
      (byte) 0x3f, (byte) 0xbf, (byte) 0x1f, (byte) 0x3c, 
      (byte) 0x9e, (byte) 0xdf, (byte) 0x6b, (byte) 0x11, 
      (byte) 0x82, (byte) 0x5a, (byte) 0x5d, (byte) 0x0a, 
      }; 

      string path = "game.sii"; 
      load_file_to_memory(path); 
      //decrypt_file(AES_KEY); 
      byte[] iv = new byte[0x10]; 
      byte[] cipherText = new byte[file_orig_bytes.Length - 0x38]; 
      Array.Copy(file_orig_bytes, 0x38, cipherText, 0, cipherText.Length); 
      Array.Copy(file_orig_bytes, 0x24, iv, 0, iv.Length); 

      string new_file = DecryptStringFromBytes_Aes(cipherText, AES_KEY, iv); 
      int a; 

     } 
     private void load_file_to_memory(string path) 
     { 
      file_original = File.ReadAllText(path); 
      file_orig_bytes = File.ReadAllBytes(path); 
      int i; 
     } 

     static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key 
, byte[] IV) 
     { 
      // Check arguments. 
      if (cipherText == null || cipherText.Length <= 0) 
       throw new ArgumentNullException("cipherText"); 
      if (Key == null || Key.Length <= 0) 
       throw new ArgumentNullException("Key"); 
      if (IV == null || IV.Length <= 0) 
       throw new ArgumentNullException("Key"); 

      // Declare the string used to hold 
      // the decrypted text. 
      string plaintext = null; 

      // Create an Aes object 
      // with the specified key and IV. 
      using (Aes aesAlg = Aes.Create()) 
      { 
       aesAlg.Key = Key; 
       aesAlg.IV = IV; 

       // Create a decrytor to perform the stream transform. 
       ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV); 

       // Create the streams used for decryption. 
       using (MemoryStream msDecrypt = new MemoryStream(cipherText)) 
       { 
        using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) 
        { 
         using (StreamReader srDecrypt = new StreamReader(csDecrypt)) 
         { 

          // Read the decrypted bytes from the decrypting stream 
          // and place them in a string. 
          plaintext = srDecrypt.ReadToEnd(); 
         } 
        } 
       } 

      } 

      return plaintext; 

     } 

任何幫助?謝謝

+1

爲什麼你不使用框架現有的類https://msdn.microsoft.com/en-us/library/system.security.cryptography.aes(v=vs.110).aspx? – bdn02

+1

@ bdn02 AES和Rijndael是128的默認塊大小的代名詞。 –

+0

我用默認示例重寫了它 - 它效果更好 - 沒有空字符串。代碼附在答案中(我應該編輯原始文章嗎?),但仍然沒有原始結果。返回字符串似乎仍然被加密... –

回答

1

這是我的版本,似乎很好。 最後一個代碼的問題是原始java版本中的未加密內容是用「InflaterInputStream」類來處理的,在c#中,我在sharpziplib中發現了這個類。

public class Test2 
{ 
    static string file_original; 
    static byte[] file_orig_bytes; 

    static void Main(string[] args) 
    { 
     byte[] AES_KEY = new byte[]{ 
      (byte) 0x2a, (byte) 0x5f, (byte) 0xcb, (byte) 0x17, 
      (byte) 0x91, (byte) 0xd2, (byte) 0x2f, (byte) 0xb6, 
      (byte) 0x02, (byte) 0x45, (byte) 0xb3, (byte) 0xd8, 
      (byte) 0x36, (byte) 0x9e, (byte) 0xd0, (byte) 0xb2, 
      (byte) 0xc2, (byte) 0x73, (byte) 0x71, (byte) 0x56, 
      (byte) 0x3f, (byte) 0xbf, (byte) 0x1f, (byte) 0x3c, 
      (byte) 0x9e, (byte) 0xdf, (byte) 0x6b, (byte) 0x11, 
      (byte) 0x82, (byte) 0x5a, (byte) 0x5d, (byte) 0x0a, 
      }; 

     string path = @"C:\temp_10\game.sii"; 
     load_file_to_memory(path); 
     //decrypt_file(AES_KEY); 
     byte[] iv = new byte[0x10]; 
     byte[] cipherText = new byte[file_orig_bytes.Length - 0x38]; 
     Array.Copy(file_orig_bytes, 0x38, cipherText, 0, cipherText.Length); 
     Array.Copy(file_orig_bytes, 0x24, iv, 0, iv.Length); 

     byte[] decoded_binary_content = AESDecrypt(cipherText, AES_KEY, iv); 

     string decoded_string_content = ""; 
     using (MemoryStream ms = new MemoryStream(decoded_binary_content)) 
     using (ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream iis = new ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream(ms)) 
     using (StreamReader sr = new StreamReader(iis)) 
      decoded_string_content = sr.ReadToEnd(); 
    } 

    private static void load_file_to_memory(string path) 
    { 
     file_original = File.ReadAllText(path); 
     file_orig_bytes = File.ReadAllBytes(path); 
    } 

    //http://lamahashim.blogspot.it/2009/08/encyptiondecryption-in-c-and-java.html 
    static byte[] AESDecrypt(byte[] encryptedData, byte[] keyBytes, byte[] iv) 
    { 
     RijndaelManaged rijndaelCipher = new RijndaelManaged(); 
     rijndaelCipher.Mode = CipherMode.CBC; 
     rijndaelCipher.Padding = PaddingMode.None; 
     rijndaelCipher.IV = iv; 

     rijndaelCipher.KeySize = 0x80; 
     rijndaelCipher.BlockSize = 0x80; 
     rijndaelCipher.Key = keyBytes; 
     rijndaelCipher.IV = iv; 
     byte[] plainText = rijndaelCipher.CreateDecryptor().TransformFinalBlock(encryptedData, 0, encryptedData.Length); 
     return plainText; 
    } 
} 

我抄在代碼

+0

謝謝,工作就像一個魅力! –

+0

我已閱讀代碼和sharpziplib庫。據我瞭解,我在初始階段收到的'垃圾'內容是被壓縮的文件?是對的嗎? –

+0

是的,我認爲是。如果你找到'InflaterInputStream'的java類定義,你可以閱讀:'這個類實現了一個流壓縮格式的數據解壓縮流過濾器。它也被用作其他解壓縮過濾器的基礎,例如GZIPInputStream' – bdn02

0

顯示的URL解密函數在讀SII文件已經開發出一種興趣,我碰到這個堆棧問題偶然發現同一個Java程序來後,並與bdn02的回答幫助我得到了一個應用程序並運行並做了一些修改。

這個版本使用DeflateStream類從System.IO.Compression命名空間,而不是SharpZipLib,並跳過的壓縮內容,因爲這些字節的頭兩個字節含有用於zlib規範(RFC 1950),而此代碼使用deflate壓縮信息和標誌規格(RFC 1951)。

爲將來遇到此問題的其他人提供此答案,以及誰不想依賴SharpZipLib或任何第三方軟件包。

class Program 
{ 
    private static byte[] AES_Key = { 42, 95, 203, 23, 145, 210, 47, 182, 2, 69, 179, 216, 54, 158, 208, 178, 194, 115, 113, 86, 63, 191, 31, 60, 158, 223, 107, 17, 130, 90, 93, 10 }; 

    static void Main(string[] args) 
    { 
     // Get bytes of AES Key, read contents 
     var contentsBytes = File.ReadAllBytes("profile.sii"); 

     // Create IV & Cipher test byte arrays 
     var iv = new byte[0x10]; 
     var cipherText = new byte[contentsBytes.Length - 0x38]; 

     // Copy contents bytes to cipherText & IV arrays 
     Array.Copy(contentsBytes, 56, cipherText, 0, cipherText.Length); 
     Array.Copy(contentsBytes, 36, iv, 0, iv.Length); 

     // Create AES Crypto Service Provider with our Key & Vector. 
     var cryptoServiceProvider = new AesCryptoServiceProvider 
     { 
      Mode = CipherMode.CBC, 
      Padding = PaddingMode.None, 
      KeySize = 0x80, 
      BlockSize = 0x80, 
      Key = AES_Key, 
      IV = iv 
     }; 

     // Create decryptor and get plain text of encrypted contents. 
     var decryptor = cryptoServiceProvider.CreateDecryptor(); 
     var plainText = decryptor.TransformFinalBlock(cipherText, 0, cipherText.Length); 

     string decompressedContents; 
     // Load into Memory Stream and skip the first 2 bytes. 
     // Use a Deflate stream to decompress the contents 
     // Read the deflated contents via our StreamReader 
     using (var memStream = new MemoryStream(plainText, 2, plainText.Length - 2)) 
     using (var iis = new DeflateStream(memStream, CompressionMode.Decompress)) 
     using (var streamReader = new StreamReader(iis)) 
     { 
      decompressedContents = streamReader.ReadToEnd(); 
     } 
    } 
}