Could somebody please explain the decryption algorith?

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
MrGrim
Posts: 11
Joined: 2003-03-29 18:12

Could somebody please explain the decryption algorith?

Post by MrGrim » 2003-03-29 18:19

Hi,

I've downloaded the source code and I've tried to understand it on my own, but I just couldn't. I've never read or written C++ before so it is really hard for me to understand what is going on. (I only know VB, Java and C# so far, but C++ is on my list)

I have also tried looking at the source code of Java Open DC but that uses a couple of text files and some other wierd stuff. :)

Could somebody please explain to me the algorithm, either in code that I can understand or even just in english? It would be mostly appreciated. :)

Thank you in advance

TasMan
Posts: 196
Joined: 2003-01-03 08:31
Location: Canada
Contact:

Post by TasMan » 2003-03-29 20:41

Are you talking about the lock to key decryption (that is the only thing I can think of....I don't think there is any encryption in DC other than that)

Well here's a nice VB6 solution

Code: Select all

Public Function LockToKey(ByRef Lck As String, ByVal n As Long) As String
  Dim aByte() As Byte, h As Integer, ub As Integer
  
  'n = 5 for hub and client locks
  
  h = InStrB(1, Lck, " ")
  If h Then Lck = LeftB$(Lck, h - 1)
  'The lock only continues to the first space (Pk= comes after)
  
  'Convert it to a byte array
  ub = Len(Lck) - 1
  ReDim aByte(ub) As Byte
  aByte = StrConv(Lck, vbFromUnicode)
  
  'The first character is handled differently from the others
  h = aByte(0) Xor aByte(ub) Xor aByte(ub - 1) Xor n
  h = ((h * 16) And 240) Or ((h \ 16) And 15)
  'Equivalent of bit shifting four to the left (* 2^4) and four to the right (\ 2^4)

  'Check for illegal characters
  Select Case h
    Case 0, 5, 36, 96, 124, 126
      LockToKey = "/%DCN" & RightB$("00" & h, 6) & "%/"
    Case Else
      LockToKey = Chr$(h)
  End Select
  
  'Now the rest of the characaters in the lock are handled the same
  For n = 1 To ub
    h = aByte(n) Xor aByte(n - 1)
    
    h = ((h * 16) And 240) Or ((h \ 16) And 15)
  
    Select Case h
      Case 0, 5, 36, 96, 124, 126
        LockToKey = LockToKey & "/%DCN" & RightB$("00" & h, 6) & "%/"
      Case Else
        LockToKey = LockToKey & Chr$(h)
    End Select
  Next
End Function
For more info, goto http://www.lwave.ca/shasta/protocol.html and scroll to the bottom (Appendix A).
Shadows Direct Connect Hub - Taking away the light from NMDCH, leaving only shadows.....

MrGrim
Posts: 11
Joined: 2003-03-29 18:12

Thank you

Post by MrGrim » 2003-03-30 04:44

That's the one. :) Thank you.

Brian
Posts: 31
Joined: 2003-04-04 13:28
Location: Ontario, Canada
Contact:

Post by Brian » 2003-04-04 13:30

That code for VB6 is that to decrypt or encrypt the DC key?

Moch
Posts: 71
Joined: 2003-03-21 22:29

Post by Moch » 2003-04-04 15:16

Brian, that code is to come up with the key. You could say it either way that code is decrypting/encrypting the lock to a key. The point is it is figuring out what key needs to be sent based on the lock given to it. hope that clarifys things hehe.

~Moch

Brian
Posts: 31
Joined: 2003-04-04 13:28
Location: Ontario, Canada
Contact:

Post by Brian » 2003-04-04 16:41

I've been programming in VB for about 5-6 years now i'm really good and stuff with encryption algorithims. But DC has confusedme for years now i can finally make my own personal client for DC

TasMan
Posts: 196
Joined: 2003-01-03 08:31
Location: Canada
Contact:

Post by TasMan » 2003-04-04 19:38

Hey great.....may be we can work together on some things. I'm making my own client, also in VB. Open source as well. Check out the link in my profile, if you'd like to check it out. Maybe you've got some suggestions that can help me out :)
Shadows Direct Connect Hub - Taking away the light from NMDCH, leaving only shadows.....

Brian
Posts: 31
Joined: 2003-04-04 13:28
Location: Ontario, Canada
Contact:

Post by Brian » 2003-04-04 20:05

Cool, i went to the siute its still kinda under construction tho

TasMan
Posts: 196
Joined: 2003-01-03 08:31
Location: Canada
Contact:

Post by TasMan » 2003-04-04 22:25

And will be for a long time :P

However if you clicked on the SourceForge link, you can download the latest version, etc. I've got the bulk of the features in now except for downloads/uploads/returning search results. I DO have downloading file lists in my current unreleased version, 0.04 though.
Shadows Direct Connect Hub - Taking away the light from NMDCH, leaving only shadows.....

Brian
Posts: 31
Joined: 2003-04-04 13:28
Location: Ontario, Canada
Contact:

Post by Brian » 2003-04-05 08:32

Yeah i downloaded it and looked over the code its a very stable code i can tell you that now

TasMan
Posts: 196
Joined: 2003-01-03 08:31
Location: Canada
Contact:

Post by TasMan » 2003-04-05 10:58

That means a lot to me, I assure you :)

Never had any "formal" training or the dike, so I take (too much?) pride in positive responses about my code.
Shadows Direct Connect Hub - Taking away the light from NMDCH, leaving only shadows.....

Brian
Posts: 31
Joined: 2003-04-04 13:28
Location: Ontario, Canada
Contact:

Post by Brian » 2003-04-05 14:00

I just started to make a DC-Bot for my hub and its going very well cept for a few bugs dealing with the op commands..well accually it wont speak or do anything just logs in thats it

MrGrim
Posts: 11
Joined: 2003-03-29 18:12

Hmmm

Post by MrGrim » 2003-04-08 10:38

Hmmmm this is a bit strange. Even though my program computes the same key as your VB6 code and the implementation of the Shasta hub

Your code:
Ãâ€

MrGrim
Posts: 11
Joined: 2003-03-29 18:12

Even more strange!

Post by MrGrim » 2003-04-08 10:49

Just tried ShadowDC out, it can connect perfectly fine! I really don't see what I am doing wrong here ...

GargoyleMT
DC++ Contributor
Posts: 3212
Joined: 2003-01-07 21:46
Location: .pa.us

Post by GargoyleMT » 2003-04-08 11:20

Maybe, if you're not doing so already, you can tcpdump / ethereal the packets and compare them byte by byte. Perhaps you're overlooking something that Shasta's hub isn't.

MrGrim
Posts: 11
Joined: 2003-03-29 18:12

Post by MrGrim » 2003-04-08 11:50

Thank you for the suggestion GargoyleMT, but I think I have located the problem. I downloaded the ShadowDC source code and stepped through the code (which btw is not the same as the VB6 code posted earlier in the thread).

For the lock key:
nOAUDpO*0v=e694+&\fUKe>>N[V2m_<w8Mt5, Pk=[YABBA-0.9.70]U2

ShadowDC's response is:
'àACóV¡d´…5ð�ñ�§£3áâµ/%DCN000%/Q�Fõ#6´ôW“‘

My response is:
'àACóV¡d´?5ð�ñ�¢?áâµ/%DCN000%/Q�Fõ#6´ôW??

Instead of §£ my response has ¢? and instead of ' at the end mine has ? ... what on earth?? Anyway, here is the code (C#), maybe somebody can spot the mistake. :(

Code: Select all


		public static string GetValidationKey(string lockString) {
			// The lock command is of the format "$Lock <lock> Pk=<pk>" and we are only interested in <lock>
			lockString = lockString.Substring(0, lockString.IndexOf(" "));
			// The lock string as a byte array
			byte[] lockAsBytes = System.Text.UTF8Encoding.UTF8.GetBytes(lockString);
			// The string builder that will build the validation key
			StringBuilder validationKeyBuilder = new StringBuilder();
			// A temporary byte variable used to keep all the intermediate states of the validation key's bytes
			int byteAsInt;			

			// The first key character is calculated from the first lock character and the last two lock characters and 5
			byteAsInt = lockAsBytes[0] ^ lockAsBytes[lockAsBytes.Length - 1] ^ lockAsBytes[lockAsBytes.Length - 2] ^ 5;
			// Every character in the key must be nibble-swapped
			byteAsInt = ((byteAsInt << 4) & 240) | ((byteAsInt >> 4) & 15);
			/*byteAsInt = (byteAsInt / 16) ^ (byteAsInt * 16);
			while (byteAsInt > 255) {
				byteAsInt -= 256;
			}*/

			// Append it to the response
			AppendByte(byteAsInt, ref validationKeyBuilder);

			// Except for the first, each <key> character is computed from the corresponding <lock> character and the one before it
			for (int i = 1; i < lockAsBytes.Length; i++) {
				byteAsInt = lockAsBytes[i] ^ lockAsBytes[i -1];
				// Every character in the key must be nibble-swapped
				byteAsInt = ((byteAsInt << 4) & 240) | ((byteAsInt >> 4) & 15);
				/*byteAsInt = (byteAsInt / 16) ^ (byteAsInt * 16);
				while (byteAsInt > 255) {
					byteAsInt -= 256;
				}*/

				// Append it to the response
				AppendByte(byteAsInt, ref validationKeyBuilder);
			}

			return validationKeyBuilder.ToString();
		}


Moch
Posts: 71
Joined: 2003-03-21 22:29

Post by Moch » 2003-04-08 13:01

The code that I can see computating the key looks good... but here is my impession of what is going wrong. A. you are converting the bytes into UTF8 encoding.. This might not be the snag, but when you do this encoding does it ignore the most significant 8th bit when it returns the bytes?

Also another thing to be watch out for.. you are doing a .ToString() this may also cause the significant bit to be ignored depending on the encoding.

I think what you need to do is just use the raw array of bytes (without doing any kind of conversion them) and then send the key back as an array of bytes, not by converting it back into a string and then sending it.

Even if that isn't the problem... let me know what you did!
~Moch

TasMan
Posts: 196
Joined: 2003-01-03 08:31
Location: Canada
Contact:

Post by TasMan » 2003-04-08 13:33

Welll...that's the newer version of my lock to key MrGrim....it's about 10-15% faster than the old one. It's the one I use in 0.04 (unreleased as of yet).
Shadows Direct Connect Hub - Taking away the light from NMDCH, leaving only shadows.....

MrGrim
Posts: 11
Joined: 2003-03-29 18:12

Post by MrGrim » 2003-04-08 14:51

You were right Moch, I skipped the parsing to and from strings and now everything works. Does this mean that I can't use any type of character encoding?

Anyway, thank you all for your help!

MrGrim
Posts: 11
Joined: 2003-03-29 18:12

No edit button?:(

Post by MrGrim » 2003-04-08 15:01

Spoken too soon, still doesn't work. :oops: :(

Moch
Posts: 71
Joined: 2003-03-21 22:29

Post by Moch » 2003-04-08 16:05

When you use character encoding to and from and to again, you could lose some of the bits if that encoding does not require them. I think this is what is happenning (even though you say it still doesn't work). aDe made a nice vb prog that allows you put in a lock and it will print the key back (ASCII and in Hex). If he could be so kind as to post a link so everyone can use that prog it would definetly help people like you debug your code.

I think though, for now, you should get that data into a char *array and parse through it just like in good ol' C. It seems like the C# Objects are getting in your way here.

~Moch

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

Post by Gumboot » 2003-04-08 16:21

The problem is definately the character encoding. You may not realize this, but you are doing at least 2 character encoding conversions.
1: UTF8.GetBytes() (converting the lock string to a byte array)
2: Your network send code (converting the key string to a byte array)

You need to use the character encoding "System.Text.Encoding.Default" (IIRC) for both of these conversions.

MrGrim
Posts: 11
Joined: 2003-03-29 18:12

Post by MrGrim » 2003-04-08 17:43

Thank you very much for your continious help. :) I will try your suggestions out as soon as I get a chance and I will let you know.

MrGrim
Posts: 11
Joined: 2003-03-29 18:12

Post by MrGrim » 2003-04-08 17:54

Both of you were absolutely right. It was indeed the encoding and switching to System.Text.Encoding.Default solved the problem.

Again, thank you very much for your help; much appreciated.

Locked