(BitTorrent-related) binary "string" to hexadecimal?

S

Shanti Braford

Hello,

Let's say one were "hypothetically", and that's a big hypothetical
there, writing a BitTorrent tracker in ruby...


Quick Synopsis: I've got the SHA1 hexdigest of a .torrent metainfo file
saved on the server.

Clients connect to the tracker and send the 'info_hash' param; this is
the raw SHA1 digest (not stored in hex).

I'm trying to lookup the hexdigest (of known torrents) with the incoming
'info_hash' param, which is a binary "String" (ruby class wise).

So..

For our example below ('foo' is not a valid bencoded string but it makes
it easy to demonstrate in this example):
digest_str = Digest::SHA1.hexdigest('foo')
# => "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"

Next up we're trying to write the /announce portion of the BitTorrent
tracker.

The 'info_hash' param comes through as an escaped binary representation
of the info_hash (not hex).

To replicate what's going on from the Client end, I've done the
following:

digest = Digest::SHA1.digest('foo')
# => "\v?ǵ????]\r?<[?uڊ3"

The torrent client then escapes the digest for transmission over http
wire:

digest_escaped = CGI::escape(digest)
# => "%0B%EE%C7%B5%EA%3F%0F%DB%C9%5D%0D%D4%7F%3C%5B%C2u%DA%8A3"

Back on my end, of course I can first CGI unescape this:

digest = CGI::unescape(params[:info_hash)
# => "\v?ǵ????]\r?<[?uڊ3"

So my $1,000,000 question :) How in ruby do we get from
"\v?ǵ????]\r?<[?uڊ3" to "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" ?

I am aware of a workaround: store the initial SHA1 digest of the torrent
in binary from in MySQL. I'm more comfortable working with strings, and
haven't dealt with storing binary data in MySQL... but I'll take a look
at that option if there's no easy way to go from ruby binary
representation to hex.

Anyone have any ideas or pointers?

- Shanti

ps. this is written in rails but the question takes place more at the
ruby level, so I figured this forum would be more fitting to ask in!
 
J

Joshua Bassett

Hi Shanti,
I still have no clue what a "hex nibble" is but it does the trick in a
pinch! =)

A "hex nibble" is half a byte represented in hexadecimal. In other
words, a byte (8 bits) is made up of two (4 bit) nibbles (a most
significant and a least significant) and in hexadecimal numbering each
nibble corresponds to a hexadecimal digit.

For example, the byte 0xFE (1111 1110) is composed of two nibbles: F
(1111), the most significant, and E (1110), the least significant.

The ruby function digest.unpack('H*') unpacks the binary string "digest"
into a string of hex bytes with the most significant nibble written
before the least significant.

Hope that makes things a bit clearer for you.

Josh
 
K

Konrad Meyer

--nextPart1419135.RkJO9yV2Cq
Content-Type: text/plain;
charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Quoth Shanti Braford:
Ok in case anyone is curious, this seems to work...
=20
digest_hex =3D digest.unpack('H*')
# =3D> "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"
=20
http://www.ruby-doc.org/core/classes/String.html#M000775
=20
I still have no clue what a "hex nibble" is but it does the trick in a=20
pinch! =3D)

Each character in a string from SHA1.digest() is single byte ranging from=
0=20
to 255. What you want to do is take each byte, and break it into the most=20
significant 4 bits and the least significant 4 bits, and represent each of=
=20
these as a hex nibble. Hence, your "0beece..." string will be twice as long=
,=20
but has the benefit of being human readable (or matching the protocol :D).

#unpack("H*") is doing what you want, and I'd say it is *not* just a quic=
k=20
hack, but a valid solution to your problem. Good luck and happy rubying.

HTH,
=2D-=20
Konrad Meyer <[email protected]> http://konrad.sobertillnoon.com/

--nextPart1419135.RkJO9yV2Cq
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQBHJ+LDCHB0oCiR2cwRAinFAJwLR/jTe3q1HQBOIe6PorPuITBHKgCgoeSI
wJFBCARgc2iAzHuefBXuxC8=
=7J93
-----END PGP SIGNATURE-----

--nextPart1419135.RkJO9yV2Cq--
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top