CIA: Difference between revisions

3dsguy (talk | contribs)
mNo edit summary
Xcution (talk | contribs)
No edit summary
Line 98: Line 98:


Obviously this section is not present in TWL CIA files.
Obviously this section is not present in TWL CIA files.
== Title Key Encryption ==
The unencrypted Title Key is used to encrypt the data in a CIA. The encrypted Title Key of a CIA can be found at offset 0x1BF in a CIA's Ticket.
Each Title Key is encrypted with AES-CBC.
To encrypt an unencrypted title key, you need:
* Common key (as byte array)
* Title ID (as ulong)
* (and of course the unencrypted title key you want to encrypt) (as byte array)
The title ID encryption process starts by converting the ulong (Title ID) into a byte array using by retrieving the bytes of the Title ID using BitConverter.GetBytes().
If the converted bytes (title ID) are in Little Endian, reverse those bytes. (in C# it would be Array.Reverse(byte_array_from_bitconverter))
This process makes the Title Key encryption IV.
Next, after you've gotten your Title Key's IV, you can start your cryptography transformation. Using AESManaged, where:
Key  = Common Key
IV  = the byte array found in the conversion process above
Mode = CipherMode.CBC
Create the encryptor (AesManaged.CreateEncryptor(key, iv)) where the key and IV are both the same as above.
Then, create a CryptoStream and a MemoryStream. The Crypto stream should start with the arguments (memorystream, aes_transform_from_above, CryptoStreamMode.Write).
Write to the CryptoStream where buffer=unencrypted_titlekey, offset=0, and count=the length of the unencrypted title key.
Use FlushFinalBlock() on the CryptoStream.
Finally, then, the encrypted title key will be available from your memory
stream. (to output the calculated encrypted title key as a byte array, you can use memorystream.ToArray(), for example)
Example function: (C#)
<pre>
        public static byte[] EncryptMyTitleKey(byte[] commonKey, byte[] titleKey, ulong titleId)
        {
            byte[] titleidasbytes = new byte[0x10];
            for (int i = 0; i < 0x10; i++)
            {
                titleidasbytes[i] = 0;
            }
            byte[] bitBytes = BitConverter.GetBytes(titleId);
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(bitBytes);
            }
            bitBytes.CopyTo(titleidasbytes, 0);
            ICryptoTransform transform = new AesManaged { Key = commonKey, IV = titleidasbytes, Mode = CipherMode.CBC }.CreateEncryptor(commonKey, titleidasbytes);
            MemoryStream memstream = new MemoryStream();
            CryptoStream cryptostream = new CryptoStream(memstream, transform, CryptoStreamMode.Write);
            cryptostream.Write(titleKey, 0, titleKey.Length);
            cryptostream.FlushFinalBlock();
            return memstream.ToArray();
        }
</pre>