Key calc problems

Technical discussion about the NMDC and <a href="http://dcpp.net/ADC.html">ADC</A> protocol. The NMDC protocol is documented in the <a href="http://dcpp.net/wiki/">Wiki</a>, so feel free to refer to it.

Moderator: Moderators

Locked
tomsec
Posts: 3
Joined: 2003-07-06 14:08

Key calc problems

Post by tomsec » 2003-07-06 14:19

Hi

I've been trying to create a dc client in c#, but I can't get the key correct :D (Looks like this is a common problem :P ) The differences between my key and the one nmdc creates are only slightly different, as these examples show:

$Lock jqEXj)Y<aj6-[*Upz2yg+kXJhl?<a+n)@[=dT=SVQ8DV%K/Sbkl8KLV7(9
$Key ç±CÑ#4Vհűg÷R „´áÄ3!"@50Õ¤Tt–±f•–æPp–Ç!7æFÇ?pE7p¡ñ
Calc: ç±CÑ#4Vհűg÷R &#132;´áÄ3!"@50Õ¤Tt&#150;±f&#149;&#150;æPp&#150;Ç!7æFÇ?pE7p¡ñ

and

Lock: Sending_key_isn't_neccessary,_key_won't_be_checked.
Key: �c° �p?ƒCà�bc¡Ñ�5²°/%DCN096%//%DCN000%//%DCN096%/a/%DCN000%/!1°U7Cà�b‚?�5²Óp£Ã°�/%DCN096%/€à¤
Calc: �c° �p?&#131;Cà�bc¡Ñ&#148;5²°/%DCN096%//%DCN000%//%DCN096%/a/%DCN000%/!1°U7Cà�b&#130;?&#148;5²Óp£Ã°�/%DCN096%/&#128;à¤

$Lock and $Key are sniffed, Calc is my key. I have ripped the source code from the protocol found at http://www.1stleg.com/Download/Document ... dix_A.html and ported it to c#.

Any suggestions to what I can do to get the key correct? When I connect to a nmdc hub I get kicked and temp banned, I suppose this is because the key is incorrect? Any help would be appreciated!

Tom

My implementation looks like this:

Code: Select all

public string CreateKey (string Lock) 
{
	
	const int MAX_CHARS_IN_KEY = 256 ;
	char [] key = new char [MAX_CHARS_IN_KEY] ;
	char [] charlock ;
	charlock = Lock.ToCharArray () ;

	int length = Lock.Length ;
	StringBuilder sKey = new StringBuilder (MAX_CHARS_IN_KEY) ;

	// Calculating chars in key
	for (int i = 1; i < length; i++)
	{
		key[i] = (char) ((int) charlock[i] ^ (int) charlock[i-1]);
	}

	// Calculating first char in key
	key[0] = (char) ((int) charlock[0] ^ (int) charlock[length-1] ^ (int) charlock[length-2] ^ 5) ;
	
	// Nibble-swap every char in key
	for (int i = 0; i < length; i++) 
	{
		key[i] = (char) ((( (int) key[i]<<4) & 240) | (( (int) key[i]>>4) & 15)) ;
	}

	// DCN encoding special chars
	for (int i = 0; i < length; i++) 
	{
		switch (key [i]) 
		{
			case (char) 0:
				sKey.Append ("/%DCN000%/") ;
				break ;

			case (char) 5:
				sKey.Append ("/%DCN005%/") ;
				break ;

			case (char) 36:
				sKey.Append ("/%DCN036%/") ;
				break ;

			case (char) 96:
				sKey.Append ("/%DCN096%/") ;
				break ;

			case (char) 124:
				sKey.Append ("/%DCN124%/") ;
				break ;
			
			case (char) 126:
				sKey.Append ("/%DCN126%/") ;
				break ;

			default:
				sKey.Append (key[i]) ;
				break ;
		} ;
	}

	return sKey.ToString () ;
}
[/list]

tomsec
Posts: 3
Joined: 2003-07-06 14:08

ps

Post by tomsec » 2003-07-06 14:31

I see that in the calculated keys there are some "&#150" and similar, these are not in my original keys, looks like the forum message parser or something changed some of the values?

Tom

Gumboot
Posts: 22
Joined: 2003-01-15 20:08
Location: New Zealand

Post by Gumboot » 2003-07-07 00:24

Mine. Tested and it works.

Code: Select all

/// <summary>
/// Computes the $Key respnse to a given $Lock command.
/// </summary>
/// <param name="lockStr">The Lock string in the middle of "$Lock (.*) Pk=".</param>
/// <param name="xorKey">0x05 for a connection from a client to a hub,
/// or (localPort+(localPort>>8))&0xFF for a connection from a hub
/// to the hublist.</param>
/// <returns>The string that should be passed back to the hub as part of
/// the $Key command.</returns>
public static string DecodeLock(string lockStr, int xorKey)
{
	if (lockStr.Length < 3)
		throw new ArgumentException("lockStr must be at least three characters long.", "lockStr");

	StringBuilder key = new StringBuilder();
	for (int i = 0; i < lockStr.Length; i ++)
	{
		// Each key byte is the xor of the corresponding lock byte
		// and the one before it, nibble-swapped (that's why the 
		// first is special).
		int curr = (int) lockStr[i];
		int prev;
		if (i == 0)
			prev = (int) lockStr[lockStr.Length - 2] ^
					(int) lockStr[lockStr.Length - 1] ^
					xorKey;
		else
			prev = (int) lockStr[i-1];
		int keyChar = SwapNibbles(curr ^ prev);

		if (Array.IndexOf(new int[] { 0, 5, 36, 96, 124, 126 }, keyChar) != -1)
			// Do /%DCNxxx%/ transformation.
			key.AppendFormat("/%DCN{0:D3}%/", keyChar);
		else
			key.Append((char) keyChar);
	}

	return key.ToString();
}

// Swaps the lower and upper nibbles in x.
public static int SwapNibbles(int x)
{
	return ((x << 4) & 0xF0) | ((x >> 4) & 0x0F);
}

tomsec
Posts: 3
Joined: 2003-07-06 14:08

Post by tomsec » 2003-07-07 08:50

Thanks for your reply Gumboot :D Your code generates the same keys as mine, and I get the same small errors, I really wonder what the reason could be, especially if it works on your pc...

Gumboot
Posts: 22
Joined: 2003-01-15 20:08
Location: New Zealand

Post by Gumboot » 2003-07-07 16:14

Your code generates the same keys as mine, and I get the same small errors, I really wonder what the reason could be, especially if it works on your pc...
In that case, it's probably a problem with your character encoding. You should be using the default encoding, ie. System.Text.Encoding.Default, to convert the string into binary.

Locked