Method: XOR cipher - AtomCrafty/MajiroTools Wiki

Method: XOR cipher

An XOR cipher is a common, basic form of encryption that performs an XOR operation on each byte with another byte from a key.

In the Majiro engine, this encryption method is used by the following formats:

This encryption is performed on the bytecode/image data, and starts at keyOffset 0 (relative to the beginning of the data).

Implementation

This is a reciprocal cipher, meaning the same function is used to perform both encryption and decryption.

When the key index is beyond the bounds of the key length, it is wrapped back to the start.

Mjo script key

The [Mjo script](/AtomCrafty/MajiroTools/wiki/Format: Mjo script) cipher key is simply the raw bytes (in little-endian) of the [CRC-32 hash](/AtomCrafty/MajiroTools/wiki/Method: CRC hash) lookup table. See [here](/AtomCrafty/MajiroTools/wiki/Method: CRC hash#Tables) for code to generate Table32.

static byte[] MjoKey32 = Table32.SelectMany(
           BitConverter.GetBytes).ToArray();

public static void Crypt32(byte[] bytes, int keyOffset = 0) {
    for(int i = 0; i < bytes.Length; i++)
        bytes[i] ^= MjoKey32[(keyOffset + i) % MjoKey32.Length];
}

Rct image key

The [Rct image](/AtomCrafty/MajiroTools/wiki/Format: Rct image) cipher key adds an extra step of initializing the key with a text password. The text password is converted to a seed using Crc32, and that seed is then XOR'ed with every element in Table32 before conversion to raw bytes.

public static bytes[] InitKey32(byte[] text) {
    uint seed = Crc32(text);
    return Table32.Select(v => v^seed).SelectMany(
                 BitConverter.GetBytes).ToArray();
}

public static void Crypt32(byte[] bytes, byte[] key, int keyOffset = 0) {
    for(int i = 0; i < bytes.Length; i++)
        bytes[i] ^= key[(keyOffset + i) % key.Length];
}

Password location

The Rct image password is unique per-game, and is assigned by following syscall:

This syscall is generally found somewhere near the beginning of start.mjo, in the following form:

ldstr     "PICPASSWORD"
syscallp  $pic_key_set (1)
01 08     NN NN  SS[N]...
35 08     HH HH HH HH  01 00  <- search for this

Mjo script similarities

The [Mjo script](/AtomCrafty/MajiroTools/wiki/Format: Mjo script) cipher key can alternatively be created in the same fashion as Rct image keys.

This 0-byte password produces a seed of 0x0, which when XOR'ed against Table32, causes no additional changes.

static byte[] MjoKey32 = InitKey32(new byte[0]);

Notes

An interesting aspect of the Mjo script cipher key is that the first 4 bytes are always 0 (because the first CRC-32 table value is 0). When encountering encrypted data, the first 4 bytes (and reoccurring every 1024 bytes) will technically be unencrypted.


See also

External links