<Introduction / Contents>

Appendix A: Converting a Lock into a Key

As part of the initial negotiation between the client and hub, the hub sends a $Lock <lock> Pk=<pk> command and the client must respond with a $Key <key> command. Until the DCN encoding, which we'll discuss last, the <key> has exactly as many characters as the <lock>.

Except for the first, each key character is computed from the corresponding lock character and the one before it. If the first character has index 0 and the lock has a length of len then:

for (i = 1; i < len; i++)
	key[i] = lock[i] xor lock[i-1];

The first key character is calculated from the first lock character and the last two lock characters:

key[0] = lock[0] xor lock[len-1] xor lock[len-2] xor 5

Next, every character in the key must be nibble-swapped:

for (i = 0; i < len; i++)
	key[i] = ((key[i]<<4) & 240) | ((key[i]>>4) & 15)

Finally, the characters with the decimal ASCII values of 0, 5, 36, 96, 124, and 126 cannot be sent to the server. Each character with this value must be substituted with the string /%DCN000%/, /%DCN005%/, /%DCN036%/, /%DCN096%/, /%DCN124%/, or /%DCN126%/, respectively. The resulting string is the key to be sent to the server.

If your programming language of choice doesn't have xor or shift operations on characters, convert them to integers. If it doesn't have a bit shift at all, then x << y = x*(2**y) and x >> y = x/(2**y) for all integers x and y (** is the exponent operation or "to the power of"). Be sure to use unsigned values everywhere and do not do sign extension. Shift operations always lose the high or low bit (they are not roll operations!). The & (and) and | (or) operations are all logical, not boolean (eg. 6 & 13 = 4, not 1).

When the hub connects to the hublist, it must undergo a similar Lock/Key negotiation. The <key> calculation is the same, but the special number 5 in the second step is replaced with the following value is not computed from the hub's listening port, but rather the random outgoing port that the winsock selects. localport:

((localport>>8) + (localport & 255)) & 255