예제 #1
0
        private int encryptData(FileStream ii, FileStream o, NPD npd, EDATData data, byte[] rifkey)
        {
            int numBlocks = (int)((data.getFileLen() + data.getBlockSize() - 1) / data.getBlockSize());

            byte[] expectedHashForFile  = new byte[numBlocks * 0x10];
            byte[] encryptedDataForFile = new byte[ii.Length + 0xF];

            // File Format:
            // ALL HASHES
            // Encrypted Data
            for (int i = 0; i < numBlocks; i++)
            {
                long offset;
                int  len;

                offset = i * data.getBlockSize();
                ii.Seek(offset, SeekOrigin.Begin);
                len = (int)(data.getBlockSize());
                if (i == numBlocks - 1)
                {
                    len = (int)(data.getFileLen() % (new BigInteger(data.getBlockSize())));
                }


                int realLen = len;
                len = (int)((uint)(len + 0x0F) & 0xFFFFFFF0);

                byte[] encryptedData = new byte[len];
                byte[] decryptedData = new byte[len];

                int toRead = realLen;
                while (toRead > 0)
                {
                    toRead -= ii.Read(decryptedData, realLen - toRead, toRead);
                }
                for (int ai = realLen; ai < len; ai++)
                {
                    decryptedData[ai] = 0x00;
                }

                byte[] key      = new byte[0x10];
                byte[] hash     = new byte[0x10];
                byte[] blockKey = calculateBlockKey(i, npd);

                ToolsImpl.aesecbEncrypt(rifkey, blockKey, 0, key, 0, blockKey.Length);
                ConversionUtils.arraycopy(key, 0, hash, 0, key.Length);
                int cryptoFlag = 0x2;
                int hashFlag   = 0x02;

                AppLoaderReverse a             = new AppLoaderReverse();
                byte[]           iv            = npd.getDigest();
                byte[]           generatedHash = new byte[0x10];
                a.doAll(hashFlag, cryptoFlag, decryptedData, 0, encryptedData, 0, decryptedData.Length, key, iv, hash, generatedHash, 0);
                ConversionUtils.arraycopy(encryptedData, 0, encryptedDataForFile, offset, len);
                ConversionUtils.arraycopy(generatedHash, 0, expectedHashForFile, i * 0x10, 0x10);
            }
            byte[] EDATAVersion = ConversionUtils.getByteArray("4D6164652062792052325220546F6F6C");
            o.Write(expectedHashForFile, 0, expectedHashForFile.Length);
            o.Write(encryptedDataForFile, 0, encryptedDataForFile.Length - 0xf);
            o.Write(EDATAVersion, 0, EDATAVersion.Length);
            return(STATUS_OK);
        }
예제 #2
0
        /* KDSBEST START */
        public int encryptFile(String inFile, String outFile, byte[] devKLic, byte[] keyFromRif, byte[] contentID, byte[] flags, byte[] type, byte[] version)
        {
            FileStream fin = File.Open(inFile, FileMode.Open);

            //  MemoryMappedFile fin1 = MemoryMappedFile.CreateFromFile(inFile, FileMode.Open);
            NPD[]      ptr = new NPD[1]; //Ptr to Ptr
            FileStream o   = File.Open(outFile, FileMode.Create);

            string[] fn  = o.Name.Split('\\');
            byte[]   npd = writeValidNPD(fn[fn.Length - 1], devKLic, ptr, fin, contentID, flags, version, type);
            o.Write(npd, 0, npd.Length);
            byte[] buffer = new byte[4];
            // FLAGS
            buffer[0] = 0x00;
            buffer[1] = 0x00;
            buffer[2] = 0x00;
            buffer[3] = 0x00;
            o.Write(buffer, 0, 4);

            // blocksize 0x00004000
            buffer[2] = 0x40;
            o.Write(buffer, 0, 4);
            long len = fin.Length;

            byte[] lenBuf  = BitConverter.GetBytes(len);
            byte[] rLenBuf = new byte[8];
            for (int i = 0; i < 8; i++)
            {
                rLenBuf[i] = 0x00;
            }
            for (int i = 0; i < lenBuf.Length; i++)
            {
                rLenBuf[7 - i] = lenBuf[i];
            }
            o.Write(rLenBuf, 0, 8);

            // Fill the rest 0x10 bytes with dummy we generate the metasection hash later!
            // the bytes till 0x100 are unknown
            buffer[0] = 0x00;
            while (o.Length < 0x100)
            {
                o.Write(buffer, 0, 1);
            }

            EDATData data = new EDATData();

            data.flags     = 0x00000000;
            data.blockSize = 0x00004000;
            data.fileLen   = new BigInteger(len);
            byte[] rifkey   = getKey(ptr[0], data, devKLic, keyFromRif); //Obtain the key for decryption (result of sc471 or sdatkey)
            int    hashFlag = 0x00000002;


            encryptData(fin, o, ptr[0], data, rifkey);

            o.Seek(0x90, SeekOrigin.Begin);
            AppLoader aa = new AppLoader();

            aa.doInit(hashFlag, 0x00000001, new byte[0x10], new byte[0x10], rifkey);

            int sectionSize = ((data.getFlags() & FLAG_COMPRESSED) != 0) ? 0x20 : 0x010; //BUG??? What about FLAG0x20??
            //Determine the metadatasection total len
            int numBlocks = (int)((data.getFileLen() + data.getBlockSize() - 11) / data.getBlockSize());

            int readed     = 0;
            int baseOffset = 0x100;
            //baseOffset +=  modifier; //There is an unknown offset to add to the metadatasection... value seen 0
            long remaining = sectionSize * numBlocks;

            while (remaining > 0)
            {
                int lenToRead = (HEADER_MAX_BLOCKSIZE > remaining) ? (int)remaining : HEADER_MAX_BLOCKSIZE;
                o.Seek(baseOffset + readed, SeekOrigin.Begin);
                byte[] content = new byte[lenToRead];
                byte[] ooo     = new byte[lenToRead];
                o.Read(content, 0, content.Length);
                aa.doUpdate(content, 0, ooo, 0, lenToRead);
                readed    += lenToRead;
                remaining -= lenToRead;
            }
            byte[] headerHash = new byte[0x10];
            aa.doFinalButGetHash(headerHash);
            o.Seek(0x90, SeekOrigin.Begin);
            o.Write(headerHash, 0, headerHash.Length);

            // Header Complete

            // Generate Header Hash
            o.Seek(0, SeekOrigin.Begin);
            byte[] header       = new byte[0xA0];
            byte[] headerODummy = new byte[0xA0];
            o.Read(header, 0, header.Length);
            AppLoaderReverse a = new AppLoaderReverse();

            byte[] generatedHash = new byte[0x10];
            bool   result        = a.doAll(hashFlag, 0x00000001, header, 0, headerODummy, 0, header.Length, new byte[0x10], new byte[0x10], rifkey, generatedHash, 0);

            o.Seek(0xA0, SeekOrigin.Begin);
            o.Write(generatedHash, 0, generatedHash.Length);


            //KDSBest We don't know the DATA 0xB0 to 0x100!!!

            while (o.Length < 0x100)
            {
                o.Write(buffer, 0, 1);
            }


            o.Close();
            fin.Close();
            return(STATUS_OK);
        }