Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing a torrent file - hash info. (Erlang)

I'm trying to come up with the correct url-encoded info hash to send to the tracker in order to get the peers list.

For testing, I tried parsing the torrent in this url.

After opening the file, manually cut the info dictionary piece and SHA1-hash it's value I get this binary value:

<<84,124,15,255,155,171,156,168,91,46,204,24,249,116,110, 139,202,167,163,54>>

The ASCII string retrieved from the latter binary value is 788f590f28a799cc1009a9b780b649fd6f0a2e91, and it's the same value mentioned in the site.

So let's assume everything is correct until now (isn't it?).

After encoding the binary value using the url-encoding function below I get T%7c%0f%ff%9b%ab%9c%a8%5b.%cc%18%f9tn%8b%ca%a7%a36 , which is not even close to the correct urlencoded value that I should send to the tracker. (I get a not-found error message when I send this to the tracker, plus, it's not matched to the value I see using wireshark which is x%8fY%0f%28%a7%99%cc%10%09%a9%b7%80%b6I%fdo%0a.%91 ).

The URL Encoding function I'm using:

encode(<<Bin:20/binary-unit:8>>)->
    %io:format("~p~n", [binary_to_list(Bin)]),
    encode(binary_to_list(Bin));
encode(List) -> do_encode(List).

do_encode([])-> [];
do_encode([H|T]) when H>=$a, H=<$z ->
    [H| encode(T)];
do_encode([H|T]) when H>=$A, H=<$Z ->
    [H| encode(T)];
do_encode([H|T]) when H>=$0, H=<$9 ->
    [H| encode(T)];
do_encode([H|T]) when H==$- ->
    [H| encode(T)];
do_encode([H|T]) when H==$. ->
    [H|do_encode(T)];
do_encode([H|T]) when H==$* ->
    [H|do_encode(T)];
do_encode([H|T]) ->
     to_hex(H) ++ encode(T).

hex(N) when N < 10 ->
    $0+N;
hex(N) when N >= 10, N < 16 ->
    $a+(N-10).
to_hex(N) when N < 256 ->
    [$%, hex(N div 16), hex(N rem 16)].

Is the function above wrong? I'm a kind of a newbie when it comes to raw-data handling. so help/ideas are much appreciated! Thanks!

like image 667
Taher Avatar asked Nov 06 '22 06:11

Taher


2 Answers

Note that URL-encoding is already available in erlang (albeit well hidden).

1> B = <<84,124,15,255,155,171,156,168,91,46,204,24,249,116,110, 139,202,167,163,54>>.
<<84,124,15,255,155,171,156,168,91,46,204,24,249,116,110,
2> L = erlang:binary_to_list(B).
[84,124,15,255,155,171,156,168,91,46,204,24,249,116,110,139,
 202,167,163,54]
3> edoc_lib:escape_uri(L).
"T%7c%f%c3%bf%c2%9b%c2%ab%c2%9c%c2%a8%5b.%c3%8c%18%c3%b9tn%c2%8b%c3%8a%c2%a7%c2%a36"

It yields the same result as yours.

like image 92
Zed Avatar answered Nov 15 '22 19:11

Zed


Your problem is not with your encoder but with your initial guess on the data. The String we have is "788f590f28a799cc1009a9b780b649fd6f0a2e91", so we write a little bit of Erlang code to convert this to its binary representation as a list:

part([]) ->  [];
part([U,L | R]) ->
    [{list_to_integer([U], 16),
      list_to_integer([L], 16)} | part(R)].

Now, asking in a prompt gives:

([email protected])16> etorrent_utils:build_encoded_form_rfc1738([U*16+L || {U,L} <- foo:part("788f590f28a799cc1009a9b780b649fd6f0a2e91")]).
"x%8FY%0F%28%A7%99%CC%10%09%A9%B7%80%B6I%FDo%0A.%91"

Matching the expected. You should check that your manual picking of the infohash and its SHA1 calculation works as you expect it to work. Because your SHA1 binary does not match it.

like image 23
I GIVE CRAP ANSWERS Avatar answered Nov 15 '22 19:11

I GIVE CRAP ANSWERS