Jeff Sharkey



iTunes DACP pairing hash is broken!

Last year I reverse engineered the iTunes DACP protocol and wrote an Android client that allowed you to remote control your iTunes desktop player from any Android device. (The code is open-sourced here, but I haven’t had the time to update it for quite awhile now.)

You might remember that there was a mysterious MD5 hash floating around the pairing process. Specifically, when you enter a pin code on the desktop iTunes client, it combines that code with the MDNS Pair value and hashes them. It then asks the device “does this match what you expected?” Because I wrote the Android client, I would naïvely always answer “yep, they match.”

Well, yesterday Michael Paul Bailey figured out the mystery behind that MD5 hash. :) I had tried bruteforcing various combinations of the pairing data, but never succeeded. It turns out that it boils down to just concatenating them together with the pin code digits separated by null characters.

He posted the full C++ code over on his blog, and I boiled it down to some spiffy Python here:

import StringIO, md5

pair = "4EA92B4292701F31"
passcode = "8222"
expected = "BEFF520F8280591AC0BBCB83B468FAA5"

merged = StringIO.StringIO()
merged.write(pair)
for c in passcode:
	merged.write(c)
	merged.write("\x00")

found = md5.new(merged.getvalue()).hexdigest()

print "expected =", expected
print "found    =", found.upper()
 

So what does this mean? Previously, we could write DACP clients easily because they could always return “yep, the MD5 matches” without even checking it. (This is why you could use any 4-digit pin code you wanted.)

Now, with this algorithm, we can do more than just check pin codes–we can write DACP servers that can pair with the original iPhone/iPod Remote app. For example, last year I wrote a DACP server for Amarok, but never got around to releasing it because the pairing process was very ugly. Now I need to find some time to polish and release it. :)