示例#1
0
        internal byte[] GetEntryHash(int entryindex)
        {
            if (entryindex >= PFDEntries.entries.Count)
            {
                throw new Exception("entryindex is out of bounds");
            }
            PFDEntry ent               = PFDEntries.entries[entryindex];
            ulong    tableindex        = CalculateHashTableEntryIndex(ent.file_name);
            ulong    currententryindex = PFDHashTable.entries[(int)tableindex];

            if (currententryindex < PFDHashTable.num_reserved)
            {
                var sha1     = new HMACSHA1(realkey);
                var hashdata = new List <byte>();
                while (currententryindex < PFDHashTable.num_reserved)
                {
                    ent = PFDEntries.entries[(int)currententryindex];
                    hashdata.AddRange(ent.HashData);
                    currententryindex = ent.additional_index;
                }
                sha1.ComputeHash(hashdata.ToArray());
                hashdata.Clear();
                return(sha1.Hash);
            }
            return(null);
        }
示例#2
0
        /// <summary>Decrypts System.IO.Stream into a Byte Array</summary>
        /// <param name="stream">
        /// the input stream of the file that is located inside the Param.PFD Entries
        /// </param>
        /// <param name="entryname">the name of the entry that the stream belongs to</param>
        /// <returns>byte array of the decrypted file</returns>
        public byte[] Decrypt(Stream stream, string entryname)
        {
            if (SecureFileID == null || SecureFileID.Length != 16)
            {
                DoProgress(
                    (SecureFileID == null
                        ? "SecureFileID needed to preform the encryption!"
                        : "SecureFileID is not valid! length must be 16 bytes long (128bit)"), MessageType.Error);
                return(null);
            }
            var ent   = new PFDEntry();
            var found = false;

            foreach (var t in PFDEntries.entries)
            {
                if (t.file_name.ToLower() == entryname.ToLower())
                {
                    ent   = t;
                    found = true;
                    break;
                }
            }
            if (!found)
            {
                throw new Exception("entryname does not exist inside the initialized Param.PFD");
            }
            if (!stream.CanRead || !stream.CanWrite)
            {
                throw new Exception("Unable to Access stream");
            }

            /*
             * This is currently disabled, since I got a lot of false-positives.
             * if (!ValidEntryHash(stream, entryname, false))
             *  throw new Exception(
             *      "Encrypted data seems to be invalid, a validated file is required for this operation");
             */

            var size = AlignedSize((int)stream.Length);

            DoProgress("Allocating memory (" + size + " bytes)..", MessageType.Info);
            var data = new byte[size];

            stream.Seek(0, SeekOrigin.Begin);
            stream.Read(data, 0, data.Length);
            DoProgress("Allocating decryption key..", MessageType.Info);
            var key = GetEntryKey(ent);

            DoProgress("Decrypting data (" + size + " bytes)..", MessageType.Info);
            data = Functions.Decrypt(key, data, size);
            if (data == null)
            {
                throw new Exception("Unable to decrypt data");
            }
            DoProgress("Free memory..", MessageType.Info);
            key = null;
            DoProgress("Resizing data to its original size..", MessageType.Info);
            Array.Resize(ref data, (int)ent.file_size);
            return(data);
        }
示例#3
0
 public int EncryptAllFiles(string root)
 {
     try
     {
         int encrypted = 0;
         for (int i = 0; i < PFDEntries.entries.Count; i++)
         {
             PFDEntry t = PFDEntries.entries[i];
             if (t.file_name.ToLower() == "param.sfo")
             {
                 continue;
             }
             string filepath = root + "\\" + t.file_name;
             if (File.Exists(filepath))
             {
                 if (!ValidEntryHash(filepath, false))
                 {
                     if (Encrypt(filepath))
                     {
                         if (!ValidEntryHash(filepath, true))
                         {
                             return(-1);
                         }
                         encrypted++;
                     }
                 }
             }
         }
         return(encrypted);
     }
     catch
     {
         return(-1);
     }
 }
示例#4
0
 /// <summary>Encrypt a specified System.IO.Stream to a byte array</summary>
 /// <param name="stream">Input System.IO.Stream of the file to encrypt</param>
 /// <param name="entryname">the name of the entry inside the PARAM.PFD</param>
 /// <returns>a byte array of theencrypted stream</returns>
 public byte[] Encrypt(Stream stream, string entryname)
 {
     if (SecureFileID == null || SecureFileID.Length != 16)
     {
         DoProgress(
             (SecureFileID == null
                 ? "SecureFileID needed to preform the encryption!"
                 : "SecureFileID is not valid! length must be 16 bytes long (128bit)"), MessageType.Error);
         return(null);
     }
     if (ValidEntryHash(stream, entryname, false))
     {
         DoProgress("File already valid, same data will be returned instead", MessageType.Info);
         var data = new byte[stream.Length];
         stream.Seek(0, SeekOrigin.Begin);
         stream.Read(data, 0, data.Length);
         return(data);
     }
     else
     {
         var ent   = new PFDEntry();
         var found = false;
         foreach (var t in PFDEntries.entries)
         {
             if (t.file_name.ToLower() == entryname.ToLower())
             {
                 ent   = t;
                 found = true;
                 break;
             }
         }
         if (!found)
         {
             throw new Exception("entryname does not exist inside the initialized Param.PFD");
         }
         if (!stream.CanRead || !stream.CanWrite)
         {
             throw new Exception("Unable to Access stream");
         }
         ent.file_size = (ulong)stream.Length;
         stream.Seek(0, SeekOrigin.Begin);
         var size = AlignedSize((int)stream.Length);
         DoProgress("Allocating memory (" + size + " bytes)..", MessageType.Info);
         var data = new byte[size];
         DoProgress("Reading stream into memory..", MessageType.Info);
         stream.Read(data, 0, (int)stream.Length);
         DoProgress("Allocating encryption key..", MessageType.Info);
         var key = GetEntryKey(ent);
         DoProgress("Encrypting Data (" + size + "bytes)..", MessageType.Info);
         data = Functions.Encypt(key, data, data.Length);
         if (data == null)
         {
             throw new Exception("Unable to decrypt data");
         }
         DoProgress("Free allocated memory..", MessageType.Info);
         key = null;
         return(data);
     }
 }
示例#5
0
        /// <summary>
        ///     Encrypts specified filepath
        /// </summary>
        /// <param name="filepath">the filepath to encrypt, file must be in the same directory as the PARAM.PFD</param>
        /// <returns>true if file is succesfully encrypted</returns>
        public bool Encrypt(string filepath)
        {
            try
            {
                if (!File.Exists(filepath))
                {
                    DoProgress(filepath + " Does not exist!", MessageType.Error);
                    return(false);
                }
                string name = new FileInfo(filepath).Name;
                if (!EntryExists(name))
                {
                    DoProgress("There is no \"" + name + "\" inside the PARAM.PFD Entries!", MessageType.Error);
                    return(false);
                }
                DoProgress("Initializing file stream..", MessageType.Info);
                byte[] data = null;
                using (FileStream fs = File.Open(filepath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
                {
                    for (int i = 0; i < PFDEntries.entries.Count; i++)
                    {
                        if (PFDEntries.entries[i].file_name.ToLower() == name.ToLower())
                        {
                            PFDEntry t = PFDEntries.entries[i];
                            t.file_size           = (ulong)fs.Length;
                            PFDEntries.entries[i] = t;
                            break;
                        }
                    }

                    data = Encrypt(fs, name);
                    //DoProgress("Rehashing PARAM.PFD..", MessageType.Info);
                    //bool x = ValidEntryHash(fs, name, true) && ValidFileCID(true) && ValidDHKCID2(true) && ValidBottomHash(true);
                    fs.Dispose();
                }
                if (data == null)
                {
                    return(false);
                }
                DoProgress("Writing Encrypted data to : " + filepath, MessageType.Info);
                File.WriteAllBytes(filepath, data);
                DoProgress(name + " is succesfully encrypted", MessageType.Info);
                return(true);
            }
            catch (Exception ex)
            {
                DoProgress(ex.Message, MessageType.Error);
                return(false);
            }
        }
示例#6
0
        internal byte[] GetEntryHashKey(PFDEntry entry, int hashindex)
        {
            switch (entry.file_name.ToLower())
            {
            case "param.sfo":
                return(GenerateHashkeyForSFO(hashindex));

            case "tropsys.dat":
                return(Functions.GetStaticKey("tropsys_dat_key"));

            case "tropusr.dat":
                return(Functions.GetStaticKey("tropusr_dat_key"));

            case "troptrns.dat":
                return(Functions.GetStaticKey("troptrns_dat_key"));

            case "tropconf.sfm":
                return(Functions.GetStaticKey("tropconf_sfm_key"));

            default:
                return(GerateHashKeyForSecureFileID(SecureFileID));
            }
        }
示例#7
0
        internal void Init(Stream input)
        {
            DoProgress("Initializing Param.PFD stream..", MessageType.Info);
            using (var br = new BinaryReader(input))
            {
                PFDHeader.magic = br.ReadUInt64().SwapByteOrder();
                if (PFDHeader.magic != 0x50464442ul)
                {
                    DoProgress("Invalid PFD File!", MessageType.Error);
                    throw new Exception("Invalid PFD File!");
                }
                PFDHeader.version = br.ReadUInt64().SwapByteOrder();
                if (PFDHeader.version != 3ul && PFDHeader.version != 4ul)
                {
                    DoProgress("Unsupported PFD version!", MessageType.Error);
                    throw new Exception("Unsupported PFD version!");
                }
                DoProgress("Allocating Header Data..", MessageType.Info);
                pfdheaderkey = br.ReadBytes(16);
                var header = br.ReadBytes(64);
                header = Functions.DecryptWithPortability(pfdheaderkey, header, header.Length);
                PFDSignature.bottom_hash = new byte[20];
                Array.Copy(header, 0, PFDSignature.bottom_hash, 0, 20);
                PFDSignature.top_hash = new byte[20];
                Array.Copy(header, 20, PFDSignature.top_hash, 0, 20);
                PFDSignature.hash_key = new byte[20];
                Array.Copy(header, 40, PFDSignature.hash_key, 0, 20);
                PFDSignature.padding = new byte[4];
                Array.Copy(header, 60, PFDSignature.padding, 0, 4);
                header = null;

                if (PFDHeader.version == 4ul)
                {
                    realkey = Functions.GetHMACSHA1(Functions.GetStaticKey("keygen_key"), PFDSignature.hash_key, 0, 20);
                }
                else
                {
                    realkey = PFDSignature.hash_key;
                }
                DoProgress("Reading Entries..", MessageType.Info);
                PFDHashTable.capacity     = br.ReadUInt64().SwapByteOrder();
                PFDHashTable.num_reserved = br.ReadUInt64().SwapByteOrder();
                PFDHashTable.num_used     = br.ReadUInt64().SwapByteOrder();
                PFDHashTable.entries      = new List <ulong>();
                DoProgress("Reading table capicity (" + PFDHashTable.capacity + " entries)..", MessageType.Info);
                for (ulong i = 0; i < PFDHashTable.capacity; i++)
                {
                    PFDHashTable.entries.Add(br.ReadUInt64().SwapByteOrder());
                }

                PFDEntries.entries = new List <PFDEntry>();
                DoProgress("Reading used tables (" + PFDHashTable.num_used + " entries)..", MessageType.Info);
                for (ulong i = 0; i < PFDHashTable.num_used; i++)
                {
                    var x = new PFDEntry
                    {
                        additional_index = br.ReadUInt64().SwapByteOrder(),
                        file_name        = Encoding.ASCII.GetString(br.ReadBytes(65)).Replace("\0", ""),
                        __padding_0      = br.ReadBytes(7),
                        key         = br.ReadBytes(64),
                        file_hashes = new List <byte[]>()
                    };
                    for (var j = 0; j < 4; j++)
                    {
                        x.file_hashes.Add(br.ReadBytes(20));
                    }
                    x.__padding_1 = br.ReadBytes(40);
                    x.file_size   = br.ReadUInt64().SwapByteOrder();
                    PFDEntries.entries.Add(x);
                }
                var offset =
                    (long)
                    ((ulong)(br.BaseStream.Position) + (0x110 * (PFDHashTable.num_reserved - PFDHashTable.num_used)));
                br.BaseStream.Position        = offset;
                PFDEntrySignatureTable.hashes = new List <byte[]>();
                DoProgress("Reading file table hashes (" + PFDHashTable.capacity + " entries)..", MessageType.Info);
                for (ulong i = 0; i < PFDHashTable.capacity; i++)
                {
                    PFDEntrySignatureTable.hashes.Add(br.ReadBytes(20));
                }
                br.Close();
            }
        }
示例#8
0
        internal byte[] GetEntryKey(PFDEntry entry)
        {
            var key = GetEntryHashKey(entry, 0);

            return(Functions.DecryptWithPortability(key, entry.key, entry.key.Length));
        }
        internal void Init(Stream input)
        {
            DoProgress("Initializing Param.PFD stream..", MessageType.Info);
            using (var br = new BinaryReader(input))
            {
                PFDHeader.magic = br.ReadUInt64().SwapByteOrder();
                if (PFDHeader.magic != 0x50464442ul)
                {
                    DoProgress("Invalid PFD File!", MessageType.Error);
                    throw new Exception("Invalid PFD File!");
                }
                PFDHeader.version = br.ReadUInt64().SwapByteOrder();
                if (PFDHeader.version != 3ul && PFDHeader.version != 4ul)
                {
                    DoProgress("Unsupported PFD version!", MessageType.Error);
                    throw new Exception("Unsupported PFD version!");
                }
                DoProgress("Allocating Header Data..", MessageType.Info);
                pfdheaderkey = br.ReadBytes(16);
                byte[] header = br.ReadBytes(64);
                header = Functions.DecryptWithPortability(pfdheaderkey, header, header.Length);
                PFDSignature.bottom_hash = new byte[20];
                Array.Copy(header, 0, PFDSignature.bottom_hash, 0, 20);
                PFDSignature.top_hash = new byte[20];
                Array.Copy(header, 20, PFDSignature.top_hash, 0, 20);
                PFDSignature.hash_key = new byte[20];
                Array.Copy(header, 40, PFDSignature.hash_key, 0, 20);
                PFDSignature.padding = new byte[4];
                Array.Copy(header, 60, PFDSignature.padding, 0, 4);
                header = null;

                if (PFDHeader.version == 4ul)
                    realkey = Functions.GetHMACSHA1(Functions.GetStaticKey("keygen_key"), PFDSignature.hash_key, 0, 20);
                else
                    realkey = PFDSignature.hash_key;
                DoProgress("Reading Entries..", MessageType.Info);
                PFDHashTable.capacity = br.ReadUInt64().SwapByteOrder();
                PFDHashTable.num_reserved = br.ReadUInt64().SwapByteOrder();
                PFDHashTable.num_used = br.ReadUInt64().SwapByteOrder();
                PFDHashTable.entries = new List<ulong>();
                DoProgress("Reading table capicity (" + PFDHashTable.capacity + " entries)..", MessageType.Info);
                for (ulong i = 0; i < PFDHashTable.capacity; i++)
                    PFDHashTable.entries.Add(br.ReadUInt64().SwapByteOrder());

                PFDEntries.entries = new List<PFDEntry>();
                DoProgress("Reading used tables (" + PFDHashTable.num_used + " entries)..", MessageType.Info);
                for (ulong i = 0; i < PFDHashTable.num_used; i++)
                {
                    var x = new PFDEntry();
                    x.additional_index = br.ReadUInt64().SwapByteOrder();
                    x.file_name = Encoding.ASCII.GetString(br.ReadBytes(65)).Replace("\0", "");
                    x.__padding_0 = br.ReadBytes(7);
                    x.key = br.ReadBytes(64);
                    x.file_hashes = new List<byte[]>();
                    for (int j = 0; j < 4; j++)
                        x.file_hashes.Add(br.ReadBytes(20));
                    x.__padding_1 = br.ReadBytes(40);
                    x.file_size = br.ReadUInt64().SwapByteOrder();
                    PFDEntries.entries.Add(x);
                }
                var offset =
                    (long)
                        ((ulong) (br.BaseStream.Position) + (0x110*(PFDHashTable.num_reserved - PFDHashTable.num_used)));
                br.BaseStream.Position = offset;
                PFDEntrySignatureTable.hashes = new List<byte[]>();
                DoProgress("Reading file table hashes (" + PFDHashTable.capacity + " entries)..", MessageType.Info);
                for (ulong i = 0; i < PFDHashTable.capacity; i++)
                    PFDEntrySignatureTable.hashes.Add(br.ReadBytes(20));
                br.Close();
            }
        }
 internal byte[] GetEntryKey(PFDEntry entry)
 {
     byte[] key = GetEntryHashKey(entry, 0);
     return Functions.DecryptWithPortability(key, entry.key, entry.key.Length);
 }
 internal byte[] GetEntryHashKey(PFDEntry entry, int hashindex)
 {
     switch (entry.file_name.ToLower())
     {
         case "param.sfo":
             return GenerateHashkeyForSFO(hashindex);
         case "tropsys.dat":
             return Functions.GetStaticKey("tropsys_dat_key");
         case "tropusr.dat":
             return Functions.GetStaticKey("tropusr_dat_key");
         case "troptrns.dat":
             return Functions.GetStaticKey("troptrns_dat_key");
         case "tropconf.sfm":
             return Functions.GetStaticKey("tropconf_sfm_key");
         default:
             return GerateHashKeyForSecureFileID(SecureFileID);
     }
 }
 /// <summary>
 ///     Encrypt a specified System.IO.Stream to a byte array
 /// </summary>
 /// <param name="stream">Input System.IO.Stream of the file to encrypt</param>
 /// <param name="entryname">the name of the entry inside the PARAM.PFD</param>
 /// <returns>a byte array of theencrypted stream</returns>
 public byte[] Encrypt(Stream stream, string entryname)
 {
     if (SecureFileID == null || SecureFileID.Length != 16)
     {
         DoProgress(
             (SecureFileID == null
                 ? "SecureFileID needed to preform the encryption!"
                 : "SecureFileID is not valid! length must be 16 bytes long (128bit)"), MessageType.Error);
         return null;
     }
     if (ValidEntryHash(stream, entryname, false))
     {
         DoProgress("File already valid, same data will be returned instead", MessageType.Info);
         var data = new byte[stream.Length];
         stream.Seek(0, SeekOrigin.Begin);
         stream.Read(data, 0, data.Length);
         return data;
     }
     else
     {
         var ent = new PFDEntry();
         bool found = false;
         foreach (PFDEntry t in PFDEntries.entries)
         {
             if (t.file_name.ToLower() == entryname.ToLower())
             {
                 ent = t;
                 found = true;
                 break;
             }
         }
         if (!found)
             throw new Exception("entryname does not exist inside the initialized Param.PFD");
         if (!stream.CanRead || !stream.CanWrite)
             throw new Exception("Unable to Access stream");
         ent.file_size = (ulong) stream.Length;
         stream.Seek(0, SeekOrigin.Begin);
         int size = AlignedSize((int) stream.Length);
         DoProgress("Allocating memory (" + size + " bytes)..", MessageType.Info);
         var data = new byte[size];
         DoProgress("Reading stream into memory..", MessageType.Info);
         stream.Read(data, 0, (int) stream.Length);
         DoProgress("Allocating encryption key..", MessageType.Info);
         byte[] key = GetEntryKey(ent);
         DoProgress("Encrypting Data (" + size + "bytes)..", MessageType.Info);
         data = Functions.Encypt(key, data, data.Length);
         if (data == null)
             throw new Exception("Unable to decrypt data");
         DoProgress("Free allocated memory..", MessageType.Info);
         key = null;
         return data;
     }
 }
        /// <summary>
        ///     Decrypts System.IO.Stream into a Byte Array
        /// </summary>
        /// <param name="stream">the input stream of the file that is located inside the Param.PFD Entries</param>
        /// <param name="entryname">the name of the entry that the stream belongs to</param>
        /// <returns>byte array of the decrypted file</returns>
        public byte[] Decrypt(Stream stream, string entryname)
        {
            if (SecureFileID == null || SecureFileID.Length != 16)
            {
                DoProgress(
                    (SecureFileID == null
                        ? "SecureFileID needed to preform the encryption!"
                        : "SecureFileID is not valid! length must be 16 bytes long (128bit)"), MessageType.Error);
                return null;
            }
            var ent = new PFDEntry();
            bool found = false;
            foreach (PFDEntry t in PFDEntries.entries)
                if (t.file_name.ToLower() == entryname.ToLower())
                {
                    ent = t;
                    found = true;
                    break;
                }
            if (!found)
                throw new Exception("entryname does not exist inside the initialized Param.PFD");
            if (!stream.CanRead || !stream.CanWrite)
                throw new Exception("Unable to Access stream");

            if (!ValidEntryHash(stream, entryname, false))
                throw new Exception(
                    "Encrypted data seems to be invalid, a validated file is required for this operation");

            int size = AlignedSize((int) stream.Length);
            DoProgress("Allocating memory (" + size + " bytes)..", MessageType.Info);
            var data = new byte[size];
            stream.Seek(0, SeekOrigin.Begin);
            stream.Read(data, 0, data.Length);
            DoProgress("Allocating decryption key..", MessageType.Info);
            byte[] key = GetEntryKey(ent);
            DoProgress("Decrypting data (" + size + " bytes)..", MessageType.Info);
            data = Functions.Decrypt(key, data, size);
            if (data == null)
                throw new Exception("Unable to decrypt data");
            DoProgress("Free memory..", MessageType.Info);
            key = null;
            DoProgress("Resizing data to its original size..", MessageType.Info);
            Array.Resize(ref data, (int) ent.file_size);
            return data;
        }