示例#1
0
        public void Decrypt(DirectoryInfo outputDirectory, bool fullyDecryptNcchContents)
        {
            foreach (ContentChunkRecord ccr in this.TMD.ContentChunkRecords)
            {
                if (!File.Exists($"{this.ContentDir.FullName}/{ccr.ID.ToString("x8")}"))
                {
                    continue;
                }

                using (FileStream inputFs = File.OpenRead($"{this.ContentDir.FullName}/{ccr.ID.ToString("x8")}"))
                {
                    using (Aes aes = Aes.Create())
                    {
                        aes.Key = this.Cryptor.NormalKey[(int)Keyslot.DecryptedTitleKey];
                        byte[] cindex = BitConverter.GetBytes(ccr.ContentIndex);
                        aes.IV      = (BitConverter.IsLittleEndian ? cindex.FReverse() : cindex).PadRight(0x00, 0x10);
                        aes.Padding = PaddingMode.Zeros;
                        aes.Mode    = CipherMode.CBC;


                        using (CryptoStream cs = new CryptoStream(File.Create($"{outputDirectory.FullName}/{ccr.ID.ToString("x8")}"), aes.CreateDecryptor(), CryptoStreamMode.Write))
                        {
                            inputFs.CopyTo(cs);
                            cs.FlushFinalBlock();
                        }
                    }
                }

                if (fullyDecryptNcchContents)
                {
                    FileStream decryptedLayer1Fs = File.Open($"{outputDirectory.FullName}/{ccr.ID.ToString("x8")}", FileMode.Open, FileAccess.ReadWrite);

                    using (NCCH ncch = new NCCH(decryptedLayer1Fs, this.Cryptor, this.SeedDb))
                    {
                        using (FileStream decryptedLayer2Fs = File.Create($"{outputDirectory.FullName}/{ccr.ID.ToString("x8")}_decrypted.{(ncch.Info.Flags.IsExecutable ? "cxi" : "cfa")}"))
                        {
                            ncch.Decrypt(decryptedLayer2Fs);
                        }
                    }
                }
            }

            File.Copy($"{this.ContentDir.FullName}/tmd", $"{outputDirectory.FullName}/tmd");
        }
示例#2
0
        public void Decrypt(FileStream outputStream, bool trim = true)
        {
            if (this.Cryptor == null || this.SeedDatabase == null)
            {
                throw new ArgumentException("Cannot decrypt without seed database or crypto engine.");
            }

            long size;

            if (!trim)
            {
                outputStream.SetLength(this.Info.ImageSize);
            }
            else
            {
                size = this.Info.Partitions[0].Offset;

                foreach (NCSDPartition partition in this.Info.Partitions)
                {
                    size += partition.Size;
                }

                outputStream.SetLength(size);
            }

            outputStream.Seek(0, SeekOrigin.Begin);

            MemoryMappedFile outputFile = Tools.LoadFileMapped(outputStream);

            using (MemoryMappedViewStream srcHeaderViewStream = this.NCSDMemoryMappedFile.CreateViewStream(0x0, this.Info.Partitions[0].Offset))
            {
                using (MemoryMappedViewStream destHeaderViewStream = outputFile.CreateViewStream(0x0, this.Info.Partitions[0].Offset))
                {
                    srcHeaderViewStream.CopyTo(destHeaderViewStream);
                }
            }

            foreach (NCSDPartition partition in this.Info.Partitions)
            {
                using (MemoryMappedViewStream destPartitionViewStream = outputFile.CreateViewStream(partition.Offset, partition.Size))
                {
                    NCCH ncch = new NCCH(this.NCSDMemoryMappedFile, partition.Offset, this.Cryptor, this.SeedDatabase);

                    ncch.Decrypt(outputFile);
                }
            }

            if (!trim)
            {
                NCSDPartition lastPartition = this.Info.Partitions.Last();

                long lastPosition = lastPartition.Offset + lastPartition.Size;

                using (MemoryMappedViewStream viewStream = outputFile.CreateViewStream(lastPosition, this.Info.ImageSize - lastPosition))
                {
                    while (viewStream.Position / 64 < viewStream.Length / 64)
                    {
                        byte[] buffer = new byte[64];

                        for (int i = 0; i < buffer.Length; i++)
                        {
                            buffer[i] = 0xFF;
                        }

                        viewStream.Write(buffer, 0, buffer.Length);
                    }
                }
            }
        }