<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://wiki.swganh.org/index.php?action=history&amp;feed=atom&amp;title=Packet%3AEncryption</id>
		<title>Packet:Encryption - Revision history</title>
		<link rel="self" type="application/atom+xml" href="https://wiki.swganh.org/index.php?action=history&amp;feed=atom&amp;title=Packet%3AEncryption"/>
		<link rel="alternate" type="text/html" href="https://wiki.swganh.org/index.php?title=Packet:Encryption&amp;action=history"/>
		<updated>2026-04-07T02:15:05Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.26.4</generator>

	<entry>
		<id>https://wiki.swganh.org/index.php?title=Packet:Encryption&amp;diff=1670&amp;oldid=prev</id>
		<title>Snow at 00:42, 9 December 2006</title>
		<link rel="alternate" type="text/html" href="https://wiki.swganh.org/index.php?title=Packet:Encryption&amp;diff=1670&amp;oldid=prev"/>
				<updated>2006-12-09T00:42:45Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;SWG uses a XOR Mask encryption based off the value of the CRCSeed exhanged in the Session Reply packet. &lt;br /&gt;
All the data between the SOE Opcode and CRC value are encrypted. &lt;br /&gt;
If the packet does not contain any SOE Protocol, it is encrypted between the 1st byte and the CRC value. XOR is a simple bitwise &lt;br /&gt;
operation on 2 numbers, know as an exclusive-or, when ONLY 1 bit is 1, results in a 1. This is it's truth table.&lt;br /&gt;
&lt;br /&gt;
A  B     C&lt;br /&gt;
0  0     0&lt;br /&gt;
0  1     1&lt;br /&gt;
1  0     1&lt;br /&gt;
1  1     0&lt;br /&gt;
&lt;br /&gt;
For more information on the XOR operator, use Google.&lt;br /&gt;
&lt;br /&gt;
Here are code samples of the Encrypt() and Decrypt() functions.&lt;br /&gt;
&lt;br /&gt;
//PROTOTYPES&lt;br /&gt;
&lt;br /&gt;
void Decrypt(char *pData,unsigned short nLength, unsigned int nCrcSeed);&lt;br /&gt;
void Encrypt(char *pData,unsigned short nLength,unsigned int nCRCSeed);&lt;br /&gt;
&lt;br /&gt;
//DECRYPT&lt;br /&gt;
&lt;br /&gt;
void Decrypt(char *pData,unsigned short nLength,unsigned int nCrcSeed)&lt;br /&gt;
{&lt;br /&gt;
    nLength-=4;&lt;br /&gt;
    unsigned int *Data = (unsigned int*)(pData+2);&lt;br /&gt;
    short block_count = (nLength / 4);&lt;br /&gt;
    short byte_count = (nLength % 4);&lt;br /&gt;
    unsigned int itemp;&lt;br /&gt;
    for(short count = 0;count&amp;lt;block_count;count++)&lt;br /&gt;
    {&lt;br /&gt;
        itemp = *Data;&lt;br /&gt;
        *Data ^= nCrcSeed;&lt;br /&gt;
        nCrcSeed = itemp;&lt;br /&gt;
        Data++;&lt;br /&gt;
    }&lt;br /&gt;
    pData = (char*)Data;&lt;br /&gt;
    for(short count = 0;count&amp;lt;byte_count;count++)&lt;br /&gt;
    {&lt;br /&gt;
        *pData ^= nCrcSeed;&lt;br /&gt;
        pData++;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//ENCRYPT&lt;br /&gt;
&lt;br /&gt;
void Encrypt(char *pData, unsigned short nLength,unsigned int nCrcSeed)&lt;br /&gt;
{&lt;br /&gt;
    nLength-=4;&lt;br /&gt;
    unsigned int *Data = (unsigned int*)(pData+2);&lt;br /&gt;
    short block_count = (nLength / 4);&lt;br /&gt;
    short byte_count = (nLength % 4);&lt;br /&gt;
    unsigned int itemp;&lt;br /&gt;
    for(short count = 0;count&amp;lt;block_count;count++)&lt;br /&gt;
    {&lt;br /&gt;
        *Data ^= nCrcSeed;&lt;br /&gt;
        nCrcSeed = *Data;&lt;br /&gt;
        Data++;&lt;br /&gt;
    }&lt;br /&gt;
    pData = (char*)Data;&lt;br /&gt;
    for(short count = 0;count&amp;lt;byte_count;count++)&lt;br /&gt;
    {&lt;br /&gt;
        *pData ^= (char)nCrcSeed;&lt;br /&gt;
        pData++;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Encryption Explained:&lt;br /&gt;
&lt;br /&gt;
It begins by adjusting the pointer and data length to exclude the SOE Opcode and CRC Value at the beginning and end of the packet.&lt;br /&gt;
Then the number of &amp;quot;blocks&amp;quot; or 4 byte chunks of data are calculated. Then a remainder of bytes are calculated. &lt;br /&gt;
The algorithm uses a for loop to go through each chunk, &lt;br /&gt;
and then each remaining byte of the packet to encrypt/decrypt.&lt;br /&gt;
The algorithm stats off by using the CRCSeed as the first mask value to do the XOR operation against.&lt;br /&gt;
For encryption, the resulted data is then set as the new mask. For decryption, the original data is copied, &lt;br /&gt;
then the XOR operation occures, and the &lt;br /&gt;
copy of the encrypted data is set as the new mask.&lt;br /&gt;
This recurses for EACH &amp;quot;block&amp;quot; of data.&lt;br /&gt;
When it gets down to the remainder, the first byte of the last mask is XOR'd against each individual remaining byte until the process &lt;br /&gt;
becomes completed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following is a step by step example on an arbitrarily made-up packet.&lt;br /&gt;
&lt;br /&gt;
00 09 00 01 00 02 AB 43 E3 D5 00 FF 00 11 45 32 76 43 D4 F1 00 AB CD&lt;br /&gt;
&lt;br /&gt;
First we know the first 2 bytes are the SOE opcode 0x09 (data on channel 00) So we ignore this as we need it to identify the packet.&lt;br /&gt;
We also ignore the last two because it is for the CRC value. The remainder is what needs to be encrypted (or decrypted in another case).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Say our Key is (1D 4E 32 87)&lt;br /&gt;
this will also act as our first mask.&lt;br /&gt;
&lt;br /&gt;
So, taking the first 4 bytes after the SOE opcode (00 01 00 02)&lt;br /&gt;
00 01 00 02 XOR&lt;br /&gt;
1D 4E 32 87&lt;br /&gt;
-------------&lt;br /&gt;
1D 4F 32 85&lt;br /&gt;
&lt;br /&gt;
So the beginning of the new packet is 00 09 1D 4F 32 85&lt;br /&gt;
Now we take the result as our new mask and xor the next 4 bytes&lt;br /&gt;
AB 43 E3 D5 XOR&lt;br /&gt;
1D 4F 32 85&lt;br /&gt;
-------------&lt;br /&gt;
B6 0C D1 50&lt;br /&gt;
&lt;br /&gt;
New packet so far: 00 09 1D 4F 32 85 B6 0C D1 50&lt;br /&gt;
New mask: B6 0C D1 50&lt;br /&gt;
00 FF 00 11 XOR&lt;br /&gt;
B6 0C D1 50&lt;br /&gt;
------------&lt;br /&gt;
B6 F3 D1 41&lt;br /&gt;
&lt;br /&gt;
New packet so far:  00 09 1D 4F 32 85 B6 0C D1 50 B6 F3 D1 41&lt;br /&gt;
New mask: B6 F3 D1 41&lt;br /&gt;
45 32 76 43 XOR&lt;br /&gt;
B6 F3 D1 41&lt;br /&gt;
-------------&lt;br /&gt;
F3 C1 A7 02&lt;br /&gt;
&lt;br /&gt;
New packet so far: 00 09 1D 4F 32 85 B6 0C D1 50 B6 F3 D1 41 F3 C1 A7 02&lt;br /&gt;
New mask: F3 C1 A7 02&lt;br /&gt;
&lt;br /&gt;
Now that we are out of full 4 byte blocks, we xor each last byte with the first byte in our “key” &lt;br /&gt;
&lt;br /&gt;
D4 F1 00 XOR   This is done in a separate loop, and per byte, so D4 xor F3, then F1 &lt;br /&gt;
F3 F3 F3       xor F3, then 0E xor F3. And the results are all appended to our packet&lt;br /&gt;
---------             &lt;br /&gt;
27 02 F3&lt;br /&gt;
&lt;br /&gt;
Final Encrypted Packet: 00 09 1D 4F 32 85 B6 0C D1 50 B6 F3 D1 41 F3 C1 A7 02 27 02 F3 AB CD&lt;br /&gt;
&lt;br /&gt;
Decryption would be the reverse of the encryption process.&lt;br /&gt;
Encryption is applied AFTER Compression, but BEFORE a CRC value is appended.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
VERY IMPORTANT NOTE:&lt;br /&gt;
 After the discovery of stand-alone SWG Packets (Outside of SOE protocol), the encryption and decryption algorithms &lt;br /&gt;
have a slight difference in how they adjust for the CRC/SOE opcode. Stand alone SWG Packets are encrypted between the &lt;br /&gt;
first byte and the CRC value. SOE protocol'd packets are encrypted between the SOE Opcode(2nd byte) and the CRC value.&lt;br /&gt;
The actual code should account for this however the explaination will not. &lt;br /&gt;
TODO:Update the Code - Xeno&lt;/div&gt;</summary>
		<author><name>Snow</name></author>	</entry>

	</feed>