将AES文件解密程序从Java重写为C#
我有一个与文件解密相关的特定问题。我在Java中找到了一个解密特定文件的程序(这是一个游戏中的游戏保存文件,你可以在这里找到该文件的示例:),我想将这个程序重写为C#-这样我就可以将它集成到我用C#编写的完全不同的程序中。 这是我第一次使用加密文件,所以我制作的程序不起作用,实际上我不知道如何调试它。我写的程序有固定的文件路径——这是临时解决方案 原始Java程序:将AES文件解密程序从Java重写为C#,java,c#,encryption,Java,C#,Encryption,我有一个与文件解密相关的特定问题。我在Java中找到了一个解密特定文件的程序(这是一个游戏中的游戏保存文件,你可以在这里找到该文件的示例:),我想将这个程序重写为C#-这样我就可以将它集成到我用C#编写的完全不同的程序中。 这是我第一次使用加密文件,所以我制作的程序不起作用,实际上我不知道如何调试它。我写的程序有固定的文件路径——这是临时解决方案 原始Java程序: package scsc; import javax.crypto.Cipher; import javax.crypto.sp
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#解密-我无法在此处放置许多链接:(
前几行:
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 ���
xڬ�M�$������C��4fcm�o��#=- ��rLV������̪[���������>Ƿ_��Ƿ ��M��~|�9�T����ߦ?�����*[�����X��} ���=����s�������9��Q����?�����~����|���?? O���������ӳx�Y���͛|�T����>�Q�����派克�! ����X�'�tW����!��噢�W��۸c�Ə��^κ �ŗ�{�我�P���7.���这是我的版本,似乎效果不错。
上一段代码中的问题是,原始java版本中未加密的内容是用c#中的“InflateInputStream”类填充的,我在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;
}
}
我已经从代码中显示的url复制了解密函数,我对读取SII文件产生了兴趣,在遇到相同的Java程序后,我偶然发现了这个堆栈问题,在bdn02的回答的帮助下,我启动并运行了一个应用程序,并做了一些更改
此版本使用System.IO.Compression
命名空间中的类,而不是SharpZipLib,并跳过压缩内容的前两个字节,因为这些字节包含zlib规范()的压缩信息和标志,而此代码使用deflate规范()
为将来遇到这个问题的任何人,以及不想依赖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();
}
}
}
为什么不使用框架现有类?@bdn02 AES和Rijndael是默认块大小128的同义词。我已经用默认示例重写了它-效果更好-没有空字符串。答案中附加了代码(我应该改为编辑原始帖子吗?),但仍然没有原始结果。返回字符串似乎仍然被加密…删除了我的答案,并用新的,可能更好的版本重写了第一篇文章。添加一些输出,一些完整的文件供下载,但声誉不允许我发送更多的链接,然而…我已经查看了代码和sharpziplib库。据我所知,“装束”我一开始收到的age'内容实际上是压缩文件?是吗?是的,我想是的。如果你找到了'InflaterInputStream'的java类定义,你可以读到:'这个类实现了一个流过滤器,用于解压缩“deflate”中的数据'压缩格式。它还用作其他解压缩过滤器的基础,例如GZIPInputStream的
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;
}
}
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();
}
}
}