Calculating info_hash from UrlEncoded query string

1.3k views Asked by At

Basically, I'm building a small tracker for experimental purposes. I've gotten quite far, and am now working on the announce part.

What I really can't figure out is how I should decode the info_hash query string provided.

From the specification, it is a urlencoded 20-byte SHA1 hash, which made me write this code,

byte[] foo = Encoding.Default.GetBytes(HttpUtility.UrlDecode(infoHash));
string temp = "";

foreach (byte b in foo)
{
    temp += b.ToString("X");
}

Which gives 'temp' the following value,

5D3F3F3F3F5E3F3F3F153FE4033683F55693468

The first and last few characters are correct. This is the raw info_hash,

%5d%96%b6%f6%84%5e%ea%da%c5%15%c4%0e%403h%b9Ui4h

And this is what both uTorrent and my own tracker gives me as info_hash when generating it from the torrent file,

5D96B6F6845EEADAC515C40E403368B955693468

What am I doing wrong?

2

There are 2 answers

2
dtb On BEST ANSWER

UrlDecode returns a string, but a SHA1 hash doesn't make sense if interpreted as (ANSI) string.
You need to decode the input string directly to an byte array, without the roundtrip to a string.

var s = "%5d%96%b6%f6%84%5e%ea%da%c5%15%c4%0e%403h%b9Ui4h";

var ms = new MemoryStream();
for (var i = 0; i < s.Length; i++)
{
    if (s[i] == '%')
    {
        ms.WriteByte(
            byte.Parse(s.Substring(i + 1, 2), NumberStyles.AllowHexSpecifier));
        i += 2;
    }
    else if (s[i] < 128)
    {
        ms.WriteByte((byte)s[i]);
    }
}

byte[] infoHash = ms.ToArray();
string temp = BitConverter.ToString(infoHash);
// "5D-96-B6-F6-84-5E-EA-DA-C5-15-C4-0E-40-33-68-B9-55-69-34-68"
0
dtb On