public bool isPackage(string path, keyIterator key) { if (!MainClass.isFile(path)) { if (debug) { Console.WriteLine("{0} is not a file", path); } return(false); } using (FileStream inFile = new FileStream(path, FileMode.Open)) { byte[] check = new byte[64]; byte[] checksum = new byte[64]; for (int i = 0; i < 64; i++) { check[i] = (byte)(inFile.ReadByte() ^ key.getKeyByte()); } for (int i = 0; i < 64; i++) { checksum[i] = (byte)(inFile.ReadByte() ^ key.getKeyByte()); } check = SHA512.Create().ComputeHash(check); key.resetKey(); if (!check.SequenceEqual(checksum)) { if (debug) { Console.WriteLine("{0} failed checksum test", path); } return(false); } return(true); } }
public void encrypt(keyIterator key) { foreach (String path in fullNames) { if (debug) { sw.Start(); } //first, get the file's name String name = Path.GetFileName(path); Console.WriteLine("Encrypting " + path); //we also need the bytes of the name byte[] nameBytes = Encoding.Unicode.GetBytes(name); byte lengthByte = (byte)nameBytes.Length; //Should always be sub 255, most of the time if (debug) { Console.WriteLine("Name Length is: {0}", lengthByte); } //generate a byte for the amount of salt that is to be produced byte saltByte = 0; //Kind of random? It's close enough for this foreach (byte b in nameBytes) { saltByte = (byte)(saltByte ^ b); } if (debug) { Console.WriteLine("Salt Byte is {0}", saltByte); } var salter = new RNGCryptoServiceProvider(); int prefixLength = saltByte % 16; byte[] prefix = new byte[prefixLength]; salter.GetNonZeroBytes(prefix); int suffixLength = ((saltByte - (saltByte % 16)) / 16); byte[] suffix = new byte[suffixLength]; salter.GetNonZeroBytes(suffix); if (debug) { Console.WriteLine("Prefix and Suffix lengths: {0}, {1}", prefixLength, suffixLength); } //Put the salt on the ends of the name List <byte> saltedName = new List <byte>(); for (int i = 0; i < prefixLength; i++) { saltedName.Add(prefix[i]); } saltedName.AddRange(nameBytes); for (int i = 0; i < suffixLength; i++) { saltedName.Add(suffix[i]); } if (debug) { Console.WriteLine("Length of salted name is: " + saltedName.Count); } //Start putting together the new file MD5 nameGen = MD5.Create(); String outName = BitConverter.ToString(nameGen.ComputeHash(nameBytes)).Replace("-", "").ToLower(); //Create the "header" and write it List <byte> headerBytes = new List <byte>(); headerBytes.Add(lengthByte); headerBytes.Add(saltByte); headerBytes.AddRange(saltedName.ToArray()); if (debug) { Console.WriteLine(("Writing to: " + Path.GetDirectoryName(path) + "\\" + outName + "\n")); } using (FileStream outFile = File.Open((Path.GetDirectoryName(path) + "\\" + outName), FileMode.Append, FileAccess.Write)) { foreach (byte b in headerBytes) { outFile.WriteByte((byte)(b ^ key.getKeyByte())); } //Write in the rest of the file, byte by byte using (FileStream inFile = File.Open(path, FileMode.Open, FileAccess.Read)) { FileInfo inFileSize = new FileInfo(path); for (int i = 0; i < inFileSize.Length; i++) { outFile.WriteByte((byte)(inFile.ReadByte() ^ key.getKeyByte())); } } } File.Delete(path); key.resetKey(); if (debug) { sw.Stop(); Console.WriteLine("Elapsed time: {0}\n", sw.Elapsed); sw.Reset(); } } }
public void decrypt(keyIterator key) { foreach (String path in fullNames) { if (debug) { sw.Start(); } Console.WriteLine("Decrypting {0}", path); using (FileStream inFile = File.Open(path, FileMode.Open, FileAccess.Read)) { String outName = ""; List <byte> decBytes = new List <byte>(); //get the name length int nameLength = inFile.ReadByte() ^ key.getKeyByte(); if (debug) { Console.WriteLine("Length of file name is: {0}", nameLength); } //get the name out of the file List <byte> byteNameRaw = new List <byte>(); List <byte> byteName = new List <byte>(); int saltStuff = inFile.ReadByte() ^ key.getKeyByte(); if (debug) { Console.WriteLine("Salt Byte is {0}", saltStuff); } int prefixLength = saltStuff % 16; int suffixLength = (saltStuff - (saltStuff % 16)) / 16; if (debug) { Console.WriteLine("Prefix and Suffix lengths: {0}, {1}", prefixLength, suffixLength); } for (int i = 0; i < nameLength + prefixLength + suffixLength; i++) { byteNameRaw.Add((byte)(inFile.ReadByte() ^ key.getKeyByte())); } //take only the filename out for (int i = 0; i < nameLength; i++) { byteName.Add(byteNameRaw[i + prefixLength]); } outName = Encoding.Unicode.GetString(byteName.ToArray()); if (debug) { Console.WriteLine("Extracted name is: {0}", outName); } //now get the rest of the file if (debug) { Console.WriteLine(("Writing to: " + Path.GetDirectoryName(path) + "\\" + outName + "\n")); } using (FileStream outFile = File.Open((Path.GetDirectoryName(path) + "\\" + outName), FileMode.Append)) { FileInfo inFileSize = new FileInfo(path); for (int i = 2 + prefixLength + nameLength + suffixLength; i < inFileSize.Length; i++) //fileToDecrypt.Length; i++) { outFile.WriteByte((byte)(inFile.ReadByte() ^ key.getKeyByte())); } } } File.Delete(path); key.resetKey(); if (debug) { sw.Stop(); Console.WriteLine("Elapsed time: {0}\n", sw.Elapsed); sw.Reset(); } } }
public void listPackage(keyIterator key, string path) { root = new DirectoryInfo(Path.GetDirectoryName(root.FullName)); Int64 fileIndex = 0; if (debug) { sw.Start(); } using (FileStream inFile = File.Open(path, FileMode.Open, FileAccess.Read)) { Int64 packSize = inFile.Length; //read in the checksum and compare byte[] check = new byte[64]; byte[] checksum = new byte[64]; for (int i = 0; i < 64; i++) { check[i] = (byte)(inFile.ReadByte() ^ key.getKeyByte()); } for (int i = 0; i < 64; i++) { checksum[i] = (byte)(inFile.ReadByte() ^ key.getKeyByte()); } check = SHA512.Create().ComputeHash(check); if (!check.SequenceEqual(checksum)) { Console.WriteLine("File {0} is not an encrypted file, or an incorrect key has been selected.", path); return; } else { Console.WriteLine("Listing {0}", path); } fileIndex += 128; while (fileIndex < packSize) { string outName = ""; List <byte> decBytes = new List <byte>(); //get the name length /* * Uint16 namelength | byte saltByteP | byte saltByteS | string saltedName (up to 260 chars + 512 salt) | Uint32 fileSize | byte[] file | <repeats> * 2 | 1 | 1 | up to 772 | 4 | up to 4GB | = 780 bytes */ //int nameLength = (int)(inFile.ReadByte() ^ key.getKeyByte()); byte[] nameLengthBytes = new byte[2]; for (int i = 0; i < 2; i++) { nameLengthBytes[i] = (byte)(inFile.ReadByte() ^ key.getKeyByte()); } fileIndex += 2; UInt16 nameLength = BitConverter.ToUInt16(nameLengthBytes, 0); if (debug) { Console.WriteLine("Length of file name is: {0}", nameLength); } //get the name out of the file List <byte> byteNameRaw = new List <byte>(); List <byte> byteName = new List <byte>(); int prefixLength = (inFile.ReadByte() ^ key.getKeyByte()); int suffixLength = (inFile.ReadByte() ^ key.getKeyByte()); fileIndex += 2; if (debug) { Console.WriteLine("Prefix and Suffix lengths: {0}, {1}", prefixLength, suffixLength); } for (int i = 0; i < nameLength + prefixLength + suffixLength; i++) { byteNameRaw.Add((byte)(inFile.ReadByte() ^ key.getKeyByte())); } fileIndex += nameLength + prefixLength + suffixLength; //take only the filename out for (int i = 0; i < nameLength; i++) { byteName.Add(byteNameRaw[i + prefixLength]); } outName = Encoding.Unicode.GetString(byteName.ToArray()); byte[] fileSizeBytes = new byte[4]; for (int i = 0; i < 4; i++) { fileSizeBytes[i] = (byte)(inFile.ReadByte() ^ key.getKeyByte()); } fileIndex += 4; UInt32 inFileSize = BitConverter.ToUInt32(fileSizeBytes, 0); Console.WriteLine("{0}: {1}", outName, MainClass.BytesToString(inFileSize)); //Attempt to create directory, just to be sure //Directory.CreateDirectory(Path.GetDirectoryName(root + "\\" + outName)); //now get the rest of the file inFile.Position += inFileSize; key.incrementBy(inFileSize); fileIndex += inFileSize; } } //File.Delete(path); if (debug) { sw.Stop(); Console.WriteLine("Elapsed time: {0}\n", sw.Elapsed); sw.Reset(); } key.resetKey(); }
public void appendPackage(keyIterator key, string path, string toAdd = null) { walkDirectory(); //scan all the files in the directory and find packages List <string> packages = new List <string>(); List <string> files = new List <string>(); int input = -1; bool addingFile = false; if (!MainClass.isFile(toAdd)) { addingFile = true; //This will eventually just direct to the file version } foreach (string s in fullNames) { if (debug) { Console.WriteLine(s); } if (isPackage(s, key)) { if (debug) { Console.WriteLine("Package found: {0}", s); } packages.Add(s); } } if (debug) { Console.WriteLine("Packages added"); } //if there is only one package, proceed //if there is more than one, prompt the user to select one if (packages.Count > 1) { Console.WriteLine("Found multiple packages:"); int i = 0; foreach (string package in packages) { i += 1; Console.WriteLine("{0} -> {1}", i, package); } Console.Write("Select package number to use (or 0 to exit): "); while (input != 0 && (input < packages.Count && input != 0)) { input = -1; input = Console.Read() - 48; //Changes input into the appropriate number if (input > packages.Count || input < 0) { if (debug) { Console.WriteLine("Selected package: {0}", input); } Console.Write("Invalid input, please enter a number between 1 and {0}, or 0 to exit: ", packages.Count); } } } else { input = 1; } if (debug) { Console.WriteLine("Selected package: {0}", input); } if (input == 0) { return; } string selectedPackage = packages[input - 1]; //check toAdd, if it's null, prompt if ok to add all files in root if (toAdd.Equals(null)) { Console.Write("No specific addition selected, ok to add all files in {0} (Y/n)?: ", path); while (Convert.ToChar(input) != 'Y' && Convert.ToChar(input) != 'n') { input = Console.Read(); if (Convert.ToChar(input) != 'Y' && Convert.ToChar(input) != 'n') { Console.Write("Invalid input, please enter Y or n: "); } } if (Convert.ToChar(input) == 'n') { return; } toAdd = root.FullName; } //if it's a directory, add all files in that directory //if it's a file, add that file if (MainClass.isFile(toAdd)) { files.Add(toAdd); //This will eventually just direct to the file version } else { files.AddRange(directoryBase.getFiles(new DirectoryInfo(toAdd))); } if (debug) { Console.WriteLine("Adding Directory: {0}", toAdd); Console.WriteLine("Files to add to archive:"); foreach (string s in files) { Console.WriteLine("{0}", s); } } //open the package, seek to the end using (FileStream package = new FileStream(selectedPackage, FileMode.Append)) { var salter = new RNGCryptoServiceProvider(); //iterate key by the file size key.incrementBy(package.Length); //encrypt the file and appends all the bytes of the result to the end /* * This bit should also probably be externalized */ foreach (string filePath in files) { if (debug) { Console.WriteLine("Adding file: {0}", filePath); } int retryMax = 3; while (retryMax > 0) { try { using (FileStream inFile = File.Open(filePath, FileMode.Open, FileAccess.Read)) { if (debug) { sw.Start(); } //first, get the file's name string name = filePath.Substring(root.FullName.Length + 1); //get the relative path Console.WriteLine("Encrypting " + name); //we also need the bytes of the name byte[] nameBytes = Encoding.Unicode.GetBytes(name); UInt16 nameLength = (UInt16)nameBytes.Length; //Should always be sub 255, most of the time if (debug) { Console.WriteLine("Name Length is: {0}", nameLength); } //generate a byte for the amount of salt that is to be produced byte saltByteP = 0, saltByteS = 255; //Kind of random? It's close enough for this foreach (byte b in nameBytes) { saltByteP = (byte)(saltByteP ^ b); saltByteS = (byte)(saltByteS ^ b); } if (debug) { Console.WriteLine("Salt Bytes are {0}, {1}", saltByteP, saltByteS); } byte[] prefix = new byte[saltByteP]; salter.GetNonZeroBytes(prefix); byte[] suffix = new byte[saltByteS]; salter.GetNonZeroBytes(suffix); //Put the salt on the ends of the name List <byte> saltedName = new List <byte>(); for (int i = 0; i < saltByteP; i++) { saltedName.Add(prefix[i]); } saltedName.AddRange(nameBytes); for (int i = 0; i < saltByteS; i++) { saltedName.Add(suffix[i]); } if (debug) { Console.WriteLine("Length of salted name is: " + saltedName.Count); } //get the length of the file as Uint32 UInt32 fileSize = (UInt32)(new FileInfo(filePath)).Length; //Create the "header" and write it List <byte> headerBytes = new List <byte>(); headerBytes.AddRange(BitConverter.GetBytes(nameLength)); headerBytes.Add(saltByteP); headerBytes.Add(saltByteS); headerBytes.AddRange(saltedName.ToArray()); headerBytes.AddRange(BitConverter.GetBytes(fileSize)); /* * Uint16 namelength | byte saltByteP | byte saltByteS | string saltedName (up to 260 chars + 512 salt) | Uint32 fileSize | byte[] file | <repeats> * 2 | 1 | 1 | up to 772 | 4 | up to 4GB | = 780 bytes */ //if (this.debug) Console.WriteLine(("Writing to: " + Path.GetDirectoryName(path) + "\\" + outName + "\n")); foreach (byte b in headerBytes) { package.WriteByte((byte)(b ^ key.getKeyByte())); } //Write in the rest of the file, byte by byte if (debug) { Console.WriteLine("Reading: {0}\\{1}", root.FullName, name); } //FileInfo inFileSize = new FileInfo(path); for (int i = 0; i < fileSize; i++) { package.WriteByte((byte)(inFile.ReadByte() ^ key.getKeyByte())); } } if (debug) { Console.WriteLine("Done!\n"); } File.Delete(filePath); //key.resetKey(); if (debug) { sw.Stop(); Console.WriteLine("Elapsed time: {0}\n", sw.Elapsed); sw.Reset(); } break; //exit the inner retry loop } catch (Exception e) { Console.WriteLine("Could not encrypt: {0}, reason: {1}", filePath, e.Message); if (retryMax == 0) { Console.WriteLine("Failed to encrypt file: {0}", filePath); Console.ReadKey(); } else { Console.WriteLine("Retrying in 3 seconds..."); retryMax -= 1; System.Threading.Thread.Sleep(3000); } } } if (!addingFile) { cleanRoot(); } } } }
public void encrypt(keyIterator key) { MD5 nameGen = MD5.Create(); //This is really yuge so I split it up List <byte> hashInfo = new List <byte>(); foreach (string s in fullNames) { hashInfo.AddRange(Encoding.Unicode.GetBytes(s)); } foreach (string s in fullDirs) { hashInfo.AddRange(Encoding.Unicode.GetBytes(s)); } string outName = DateTime.Today.ToString("d").Replace(@"/", "-") + "-" + BitConverter.ToString( nameGen.ComputeHash( hashInfo.ToArray() ) ).Replace("-", "").ToLower().Substring(0, 10); Console.WriteLine("Writing to pack: {0}\\{1}", root.FullName, outName); using (FileStream outFile = File.Open((root.FullName + "\\" + outName), FileMode.Append, FileAccess.Write)) { var salter = new RNGCryptoServiceProvider(); byte[] check = new byte[64]; salter.GetNonZeroBytes(check); byte[] checksum = SHA512.Create().ComputeHash(check); for (int i = 0; i < 64; i++) { //Console.Write("{0} ", check[i]); outFile.WriteByte((byte)(check[i] ^ key.getKeyByte())); } for (int i = 0; i < 64; i++) { //Console.Write("{0} ", checksum[i]); outFile.WriteByte((byte)(checksum[i] ^ key.getKeyByte())); } foreach (string path in fullNames) { //Possibly replace this lock with a custom function that waits until the file is accessible or a certain amount of time has passed int retryMax = 3; while (retryMax > 0) { try { using (FileStream inFile = File.Open(path, FileMode.Open, FileAccess.Read)) { if (debug) { sw.Start(); } //first, get the file's name string name = path.Substring(root.FullName.Length + 1); //get the relative path Console.WriteLine("Encrypting " + name); //we also need the bytes of the name byte[] nameBytes = Encoding.Unicode.GetBytes(name); UInt16 nameLength = (UInt16)nameBytes.Length; //Should always be sub 255, most of the time if (debug) { Console.WriteLine("Name Length is: {0}", nameLength); } //generate a byte for the amount of salt that is to be produced byte saltByteP = 0, saltByteS = 255; //Kind of random? It's close enough for this foreach (byte b in nameBytes) { saltByteP = (byte)(saltByteP ^ b); saltByteS = (byte)(saltByteS ^ b); } if (debug) { Console.WriteLine("Salt Bytes are {0}, {1}", saltByteP, saltByteS); } byte[] prefix = new byte[saltByteP]; salter.GetNonZeroBytes(prefix); byte[] suffix = new byte[saltByteS]; salter.GetNonZeroBytes(suffix); //Put the salt on the ends of the name List <byte> saltedName = new List <byte>(); for (int i = 0; i < saltByteP; i++) { saltedName.Add(prefix[i]); } saltedName.AddRange(nameBytes); for (int i = 0; i < saltByteS; i++) { saltedName.Add(suffix[i]); } if (debug) { Console.WriteLine("Length of salted name is: " + saltedName.Count); } //get the length of the file as Uint32 UInt32 fileSize = (UInt32)(new FileInfo(path)).Length; //Create the "header" and write it List <byte> headerBytes = new List <byte>(); headerBytes.AddRange(BitConverter.GetBytes(nameLength)); headerBytes.Add(saltByteP); headerBytes.Add(saltByteS); headerBytes.AddRange(saltedName.ToArray()); headerBytes.AddRange(BitConverter.GetBytes(fileSize)); /* * Uint16 namelength | byte saltByteP | byte saltByteS | string saltedName (up to 260 chars + 512 salt) | Uint32 fileSize | byte[] file | <repeats> * 2 | 1 | 1 | up to 772 | 4 | up to 4GB | = 780 bytes */ //if (this.debug) Console.WriteLine(("Writing to: " + Path.GetDirectoryName(path) + "\\" + outName + "\n")); foreach (byte b in headerBytes) { outFile.WriteByte((byte)(b ^ key.getKeyByte())); } //Write in the rest of the file, byte by byte if (debug) { Console.WriteLine("Reading: {0}\\{1}", root.FullName, name); } //FileInfo inFileSize = new FileInfo(path); for (int i = 0; i < fileSize; i++) { outFile.WriteByte((byte)(inFile.ReadByte() ^ key.getKeyByte())); } } if (debug) { Console.WriteLine("Done!\n"); } File.Delete(path); //key.resetKey(); if (debug) { sw.Stop(); Console.WriteLine("Elapsed time: {0}\n", sw.Elapsed); sw.Reset(); } break; //exit the inner retry loop } catch (Exception e) { Console.WriteLine("Could not encrypt: {0}, reason: {1}", path, e.Message); if (retryMax == 0) { Console.WriteLine("Failed to encrypt file: {0}", path); Console.ReadKey(); } else { Console.WriteLine("Retrying in 3 seconds..."); retryMax -= 1; System.Threading.Thread.Sleep(3000); } } } } } cleanRoot(); }
public static void Main(string[] args) { //First arg is always the executable name String[] cliargs = Environment.GetCommandLineArgs(); String hashPath = null; String encPath = null; String command = null; String appendPath = null; bool debugLog = false; bool decryptFile = false; if (cliargs.Length == 4) { command = cliargs[1]; if (Path.IsPathRooted(cliargs[2])) { hashPath = cliargs[2]; } else { hashPath = Directory.GetCurrentDirectory() + "\\" + cliargs[2]; } if (Path.IsPathRooted(cliargs[3])) { encPath = cliargs[3]; } else { encPath = Directory.GetCurrentDirectory() + "\\" + cliargs[3]; } } else if (cliargs.Length > 4) { command = cliargs[1]; if (Path.IsPathRooted(cliargs[2])) { hashPath = cliargs[2]; } else { hashPath = Directory.GetCurrentDirectory() + "\\" + cliargs[2]; } if (Path.IsPathRooted(cliargs[3])) { encPath = cliargs[3]; } else { encPath = Directory.GetCurrentDirectory() + "\\" + cliargs[3]; } //---------------------- if (!command.Equals("-a")) { debugLog = true; } else { if (Path.IsPathRooted(cliargs[4])) { appendPath = cliargs[4]; } else { appendPath = Directory.GetCurrentDirectory() + "\\" + cliargs[4]; } } } else { Console.WriteLine("Not enough args."); Environment.Exit(-1); //failure } //Console.WriteLine("Hash Path: {0}\nTarget Path: {1}", hashPath, encPath); Console.Write("\n"); directoryHasher hasher = new directoryHasher(new DirectoryInfo(hashPath)); //d.walkDirectory(); //create both the hash and a list of filenames in the hash /* * Console.WriteLine(d.getDirNames()); * foreach (string s in d.getDirNames()) * { * Console.WriteLine(s); * } */ keyIterator key = new keyIterator(hasher.createHash()); //key.resetKey(); if (isFile(encPath)) { decryptFile = true; } if (command.Equals("-e")) { //Console.WriteLine("Encryption mode"); directoryPacker packer = new directoryPacker(new DirectoryInfo(encPath), debugLog); //new directoryEncrypter(new System.IO.DirectoryInfo(encPath), debugLog); packer.walkDirectory(); packer.encrypt(key); } else if (command.Equals("-d")) { //Console.WriteLine("Decryption mode"); if (!decryptFile) { //Console.WriteLine("Directory Mode"); directoryUnpacker unpacker = new directoryUnpacker(new DirectoryInfo(encPath), debugLog); unpacker.walkDirectory(); unpacker.decrypt(key); } else { //Console.WriteLine("File Mode"); directoryUnpacker unpacker = new directoryUnpacker(new DirectoryInfo(encPath), debugLog); //no walk needed unpacker.decryptSingle(key, encPath); } } else if (command.Equals("-l")) { //Console.WriteLine("List Mode"); if (decryptFile) { //Console.WriteLine("Listing contents of package: {0}", encPath); packageManipulator manipulator = new packageManipulator(new DirectoryInfo(encPath), debugLog); //new directoryEncrypter(new System.IO.DirectoryInfo(encPath), debugLog); //e.walkDirectory(); manipulator.listPackage(key, encPath); } else { Console.WriteLine("No Package Selected"); } } else if (command.Equals("-a")) { if (!isFile(appendPath)) { Console.WriteLine("CURRENTLY CANNOT APPEND DIRECTORY"); } Console.WriteLine("WARNING: NO SAFETIES CURRENTLY IN PLACE TO PREVENT PACKAGE CORRUPTION"); packageManipulator manipulator = new packageManipulator(new DirectoryInfo(encPath), true); manipulator.appendPackage(key, encPath, appendPath); } else { Console.WriteLine("Invalid command '{0}'", command); Environment.Exit(-1); } Console.WriteLine("Finished!"); }
public void decrypt(keyIterator key) { /* * Add in a check to make sure this is actually decrypting a real encrypted file * */ foreach (string path in fullNames) //should only ever be one, hopefully { Int64 fileIndex = 0; if (debug) { sw.Start(); } using (FileStream inFile = File.Open(path, FileMode.Open, FileAccess.Read)) { Int64 packSize = inFile.Length; //read in the checksum and compare byte[] check = new byte[64]; byte[] checksum = new byte[64]; for (int i = 0; i < 64; i++) { check[i] = (byte)(inFile.ReadByte() ^ key.getKeyByte()); } for (int i = 0; i < 64; i++) { checksum[i] = (byte)(inFile.ReadByte() ^ key.getKeyByte()); } check = SHA512.Create().ComputeHash(check); if (!check.SequenceEqual(checksum)) { Console.WriteLine("File {0} is not an encrypted file, or an incorrect key has been selected.", path); continue; } else { Console.WriteLine("Decrypting {0}", path); } fileIndex += 128; while (fileIndex < packSize) { string outName = ""; List <byte> decBytes = new List <byte>(); //get the name length /* * Uint16 namelength | byte saltByteP | byte saltByteS | string saltedName (up to 260 chars + 512 salt) | Uint32 fileSize | byte[] file | <repeats> * 2 | 1 | 1 | up to 772 | 4 | up to 4GB | = 780 bytes */ //int nameLength = (int)(inFile.ReadByte() ^ key.getKeyByte()); byte[] nameLengthBytes = new byte[2]; for (int i = 0; i < 2; i++) { nameLengthBytes[i] = (byte)(inFile.ReadByte() ^ key.getKeyByte()); } fileIndex += 2; UInt16 nameLength = BitConverter.ToUInt16(nameLengthBytes, 0); if (debug) { Console.WriteLine("Length of file name is: {0}", nameLength); } //get the name out of the file List <byte> byteNameRaw = new List <byte>(); List <byte> byteName = new List <byte>(); int prefixLength = (inFile.ReadByte() ^ key.getKeyByte()); int suffixLength = (inFile.ReadByte() ^ key.getKeyByte()); fileIndex += 2; if (debug) { Console.WriteLine("Prefix and Suffix lengths: {0}, {1}", prefixLength, suffixLength); } for (int i = 0; i < nameLength + prefixLength + suffixLength; i++) { byteNameRaw.Add((byte)(inFile.ReadByte() ^ key.getKeyByte())); } fileIndex += nameLength + prefixLength + suffixLength; //take only the filename out for (int i = 0; i < nameLength; i++) { byteName.Add(byteNameRaw[i + prefixLength]); } outName = Encoding.Unicode.GetString(byteName.ToArray()); Console.WriteLine("Extracting {0}", outName); byte[] fileSizeBytes = new byte[4]; for (int i = 0; i < 4; i++) { fileSizeBytes[i] = (byte)(inFile.ReadByte() ^ key.getKeyByte()); } fileIndex += 4; UInt32 inFileSize = BitConverter.ToUInt32(fileSizeBytes, 0); //Attempt to create directory, just to be sure Directory.CreateDirectory(Path.GetDirectoryName(root + "\\" + outName)); //now get the rest of the file if (debug) { Console.WriteLine(("Writing to: " + Path.GetDirectoryName(path) + "\\" + outName + "\n")); } using (FileStream outFile = File.Open((Path.GetDirectoryName(path) + "\\" + outName), FileMode.Append)) { //FileInfo inFileSize = new FileInfo(path); for (int i = 0; i < inFileSize; i++) //fileToDecrypt.Length; i++) { outFile.WriteByte((byte)(inFile.ReadByte() ^ key.getKeyByte())); } } fileIndex += (int)inFileSize; if (debug) { Console.WriteLine("File index is {0}", fileIndex); Console.WriteLine("Length of extracted Data is {0}", 4 + byteNameRaw.Count + 4 + inFileSize); } } } File.Delete(path); if (debug) { sw.Stop(); Console.WriteLine("Elapsed time: {0}\n", sw.Elapsed); sw.Reset(); } key.resetKey(); } }