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> |