CIA: Difference between revisions
mNo edit summary |
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> | |||