Saturday, June 20, 2009

iTunes Remote pairing code

If you have an iPhone or iPod Touch, you are probably familiar with the iTunes Remote app. It allows you to control iTunes from a really well designed application. I have recently been working on reverse engineering the communication so that I can use the same remote to control other media applications like Boxee and XBMC. There are a number of other projects doing similar things (stereo).

The communication has not been difficult to decode. It is a variation of the previously reverse-engineered DAAP communication used by iTunes sharing. It's referred to as DACP. If you are looking for information about this protocol, Jeffrey Sharkey has done an excellent job of documenting his efforts in creating a Google Android implementation of the iTunes Remote (Android DACP Remote Control).

Before you can use the iPhone as a remote, there is a pairing process which occurs between the server and the remote. There is a good discussion of the pairing process by mycroes (Pairing the Itunes Remote app with your own server). The one part that is missing is how iTunes generates the pairing code which it sends back to the iPhone. I have finally, with a fair bit of effort, been able to decode the value.

The pairing code is generated by a hash algorithm I was able to lift and modify from the xine source code. The algorithm takes two arguments. The first is the Pair parameter in the _touch-remote._tcp zeroconf record (refer to mycroes's article). The Pair parameter is a 16 character hexadecimal string. The second is the four digit passcode provided by the remote which must be sent back by iTunes (or the custom server).

These two parameters can be passed to the function provided below. The result is a 32 character hexadecimal string which is returned back to the remote application in the form of a GET request.

Since this code was modified from GPL source code (xine), it is also protected by the GPL. Feel free to use this code for whatever you want. All I ask is that you give me proper attribution. Also, I would love to hear what you have done with it, so please let me know if you use it for a cool project.

With no further ado, here's the source.


std::string itunes_pairingcode( std::string passcode, std::string pair )
{
// initialize the param array
char param[64];
::memset( param, 0, 64 );
param[56] = '\xc0';
param[24] = '\x80';

// set the pair value
::strncpy( param, pair.c_str(), 16 );

// copy the pair code
::strncpy( param+16, passcode.c_str(), 4 );
param[22] = param[19];
param[20] = param[18];
param[18] = param[17];
param[19] = param[17] = 0;

// initialize a, b, c, d
uint32_t a = 0x67452301;
uint32_t b = 0xefcdab89;
uint32_t c = 0x98badcfe;
uint32_t d = 0x10325476;

a = ((b & c) | (~b & d)) + (*(uint32_t*)(param+0x00)) + a - 0x28955B88;
a = ((a << 0x07) | (a >> 0x19)) + b;
d = ((a & b) | (~a & c)) + (*(uint32_t*)(param+0x04)) + d - 0x173848AA;
d = ((d << 0x0c) | (d >> 0x14)) + a;
c = ((d & a) | (~d & b)) + (*(uint32_t*)(param+0x08)) + c + 0x242070DB;
c = ((c << 0x11) | (c >> 0x0f)) + d;
b = ((c & d) | (~c & a)) + (*(uint32_t*)(param+0x0c)) + b - 0x3E423112;
b = ((b << 0x16) | (b >> 0x0a)) + c;
a = ((b & c) | (~b & d)) + (*(uint32_t*)(param+0x10)) + a - 0x0A83F051;
a = ((a << 0x07) | (a >> 0x19)) + b;
d = ((a & b) | (~a & c)) + (*(uint32_t*)(param+0x14)) + d + 0x4787C62A;
d = ((d << 0x0c) | (d >> 0x14)) + a;
c = ((d & a) | (~d & b)) + (*(uint32_t*)(param+0x18)) + c - 0x57CFB9ED;
c = ((c << 0x11) | (c >> 0x0f)) + d;
b = ((c & d) | (~c & a)) + (*(uint32_t*)(param+0x1c)) + b - 0x02B96AFF;
b = ((b << 0x16) | (b >> 0x0a)) + c;
a = ((b & c) | (~b & d)) + (*(uint32_t*)(param+0x20)) + a + 0x698098D8;
a = ((a << 0x07) | (a >> 0x19)) + b;
d = ((a & b) | (~a & c)) + (*(uint32_t*)(param+0x24)) + d - 0x74BB0851;
d = ((d << 0x0c) | (d >> 0x14)) + a;
c = ((d & a) | (~d & b)) + (*(uint32_t*)(param+0x28)) + c - 0x0000A44F;
c = ((c << 0x11) | (c >> 0x0f)) + d;
b = ((c & d) | (~c & a)) + (*(uint32_t*)(param+0x2C)) + b - 0x76A32842;
b = ((b << 0x16) | (b >> 0x0a)) + c;
a = ((b & c) | (~b & d)) + (*(uint32_t*)(param+0x30)) + a + 0x6B901122;
a = ((a << 0x07) | (a >> 0x19)) + b;
d = ((a & b) | (~a & c)) + (*(uint32_t*)(param+0x34)) + d - 0x02678E6D;
d = ((d << 0x0c) | (d >> 0x14)) + a;
c = ((d & a) | (~d & b)) + (*(uint32_t*)(param+0x38)) + c - 0x5986BC72;
c = ((c << 0x11) | (c >> 0x0f)) + d;
b = ((c & d) | (~c & a)) + (*(uint32_t*)(param+0x3c)) + b + 0x49B40821;
b = ((b << 0x16) | (b >> 0x0a)) + c;

a = ((b & d) | (~d & c)) + (*(uint32_t*)(param+0x04)) + a - 0x09E1DA9E;
a = ((a << 0x05) | (a >> 0x1b)) + b;
d = ((a & c) | (~c & b)) + (*(uint32_t*)(param+0x18)) + d - 0x3FBF4CC0;
d = ((d << 0x09) | (d >> 0x17)) + a;
c = ((d & b) | (~b & a)) + (*(uint32_t*)(param+0x2c)) + c + 0x265E5A51;
c = ((c << 0x0e) | (c >> 0x12)) + d;
b = ((c & a) | (~a & d)) + (*(uint32_t*)(param+0x00)) + b - 0x16493856;
b = ((b << 0x14) | (b >> 0x0c)) + c;
a = ((b & d) | (~d & c)) + (*(uint32_t*)(param+0x14)) + a - 0x29D0EFA3;
a = ((a << 0x05) | (a >> 0x1b)) + b;
d = ((a & c) | (~c & b)) + (*(uint32_t*)(param+0x28)) + d + 0x02441453;
d = ((d << 0x09) | (d >> 0x17)) + a;
c = ((d & b) | (~b & a)) + (*(uint32_t*)(param+0x3c)) + c - 0x275E197F;
c = ((c << 0x0e) | (c >> 0x12)) + d;
b = ((c & a) | (~a & d)) + (*(uint32_t*)(param+0x10)) + b - 0x182C0438;
b = ((b << 0x14) | (b >> 0x0c)) + c;
a = ((b & d) | (~d & c)) + (*(uint32_t*)(param+0x24)) + a + 0x21E1CDE6;
a = ((a << 0x05) | (a >> 0x1b)) + b;
d = ((a & c) | (~c & b)) + (*(uint32_t*)(param+0x38)) + d - 0x3CC8F82A;
d = ((d << 0x09) | (d >> 0x17)) + a;
c = ((d & b) | (~b & a)) + (*(uint32_t*)(param+0x0c)) + c - 0x0B2AF279;
c = ((c << 0x0e) | (c >> 0x12)) + d;
b = ((c & a) | (~a & d)) + (*(uint32_t*)(param+0x20)) + b + 0x455A14ED;
b = ((b << 0x14) | (b >> 0x0c)) + c;
a = ((b & d) | (~d & c)) + (*(uint32_t*)(param+0x34)) + a - 0x561C16FB;
a = ((a << 0x05) | (a >> 0x1b)) + b;
d = ((a & c) | (~c & b)) + (*(uint32_t*)(param+0x08)) + d - 0x03105C08;
d = ((d << 0x09) | (d >> 0x17)) + a;
c = ((d & b) | (~b & a)) + (*(uint32_t*)(param+0x1c)) + c + 0x676F02D9;
c = ((c << 0x0e) | (c >> 0x12)) + d;
b = ((c & a) | (~a & d)) + (*(uint32_t*)(param+0x30)) + b - 0x72D5B376;
b = ((b << 0x14) | (b >> 0x0c)) + c;

a = (b ^ c ^ d) + (*(uint32_t*)(param+0x14)) + a - 0x0005C6BE;
a = ((a << 0x04) | (a >> 0x1c)) + b;
d = (a ^ b ^ c) + (*(uint32_t*)(param+0x20)) + d - 0x788E097F;
d = ((d << 0x0b) | (d >> 0x15)) + a;
c = (d ^ a ^ b) + (*(uint32_t*)(param+0x2c)) + c + 0x6D9D6122;
c = ((c << 0x10) | (c >> 0x10)) + d;
b = (c ^ d ^ a) + (*(uint32_t*)(param+0x38)) + b - 0x021AC7F4;
b = ((b << 0x17) | (b >> 0x09)) + c;
a = (b ^ c ^ d) + (*(uint32_t*)(param+0x04)) + a - 0x5B4115BC;
a = ((a << 0x04) | (a >> 0x1c)) + b;
d = (a ^ b ^ c) + (*(uint32_t*)(param+0x10)) + d + 0x4BDECFA9;
d = ((d << 0x0b) | (d >> 0x15)) + a;
c = (d ^ a ^ b) + (*(uint32_t*)(param+0x1c)) + c - 0x0944B4A0;
c = ((c << 0x10) | (c >> 0x10)) + d;
b = (c ^ d ^ a) + (*(uint32_t*)(param+0x28)) + b - 0x41404390;
b = ((b << 0x17) | (b >> 0x09)) + c;
a = (b ^ c ^ d) + (*(uint32_t*)(param+0x34)) + a + 0x289B7EC6;
a = ((a << 0x04) | (a >> 0x1c)) + b;
d = (a ^ b ^ c) + (*(uint32_t*)(param+0x00)) + d - 0x155ED806;
d = ((d << 0x0b) | (d >> 0x15)) + a;
c = (d ^ a ^ b) + (*(uint32_t*)(param+0x0c)) + c - 0x2B10CF7B;
c = ((c << 0x10) | (c >> 0x10)) + d;
b = (c ^ d ^ a) + (*(uint32_t*)(param+0x18)) + b + 0x04881D05;
b = ((b << 0x17) | (b >> 0x09)) + c;
a = (b ^ c ^ d) + (*(uint32_t*)(param+0x24)) + a - 0x262B2FC7;
a = ((a << 0x04) | (a >> 0x1c)) + b;
d = (a ^ b ^ c) + (*(uint32_t*)(param+0x30)) + d - 0x1924661B;
d = ((d << 0x0b) | (d >> 0x15)) + a;
c = (d ^ a ^ b) + (*(uint32_t*)(param+0x3c)) + c + 0x1fa27cf8;
c = ((c << 0x10) | (c >> 0x10)) + d;
b = (c ^ d ^ a) + (*(uint32_t*)(param+0x08)) + b - 0x3B53A99B;
b = ((b << 0x17) | (b >> 0x09)) + c;

a = ((~d | b) ^ c) + (*(uint32_t*)(param+0x00)) + a - 0x0BD6DDBC;
a = ((a << 0x06) | (a >> 0x1a)) + b;
d = ((~c | a) ^ b) + (*(uint32_t*)(param+0x1c)) + d + 0x432AFF97;
d = ((d << 0x0a) | (d >> 0x16)) + a;
c = ((~b | d) ^ a) + (*(uint32_t*)(param+0x38)) + c - 0x546BDC59;
c = ((c << 0x0f) | (c >> 0x11)) + d;
b = ((~a | c) ^ d) + (*(uint32_t*)(param+0x14)) + b - 0x036C5FC7;
b = ((b << 0x15) | (b >> 0x0b)) + c;
a = ((~d | b) ^ c) + (*(uint32_t*)(param+0x30)) + a + 0x655B59C3;
a = ((a << 0x06) | (a >> 0x1a)) + b;
d = ((~c | a) ^ b) + (*(uint32_t*)(param+0x0C)) + d - 0x70F3336E;
d = ((d << 0x0a) | (d >> 0x16)) + a;
c = ((~b | d) ^ a) + (*(uint32_t*)(param+0x28)) + c - 0x00100B83;
c = ((c << 0x0f) | (c >> 0x11)) + d;
b = ((~a | c) ^ d) + (*(uint32_t*)(param+0x04)) + b - 0x7A7BA22F;
b = ((b << 0x15) | (b >> 0x0b)) + c;
a = ((~d | b) ^ c) + (*(uint32_t*)(param+0x20)) + a + 0x6FA87E4F;
a = ((a << 0x06) | (a >> 0x1a)) + b;
d = ((~c | a) ^ b) + (*(uint32_t*)(param+0x3c)) + d - 0x01D31920;
d = ((d << 0x0a) | (d >> 0x16)) + a;
c = ((~b | d) ^ a) + (*(uint32_t*)(param+0x18)) + c - 0x5CFEBCEC;
c = ((c << 0x0f) | (c >> 0x11)) + d;
b = ((~a | c) ^ d) + (*(uint32_t*)(param+0x34)) + b + 0x4E0811A1;
b = ((b << 0x15) | (b >> 0x0b)) + c;
a = ((~d | b) ^ c) + (*(uint32_t*)(param+0x10)) + a - 0x08AC817E;
a = ((a << 0x06) | (a >> 0x1a)) + b;
d = ((~c | a) ^ b) + (*(uint32_t*)(param+0x2c)) + d - 0x42C50DCB;
d = ((d << 0x0a) | (d >> 0x16)) + a;
c = ((~b | d) ^ a) + (*(uint32_t*)(param+0x08)) + c + 0x2AD7D2BB;
c = ((c << 0x0f) | (c >> 0x11)) + d;
b = ((~a | c) ^ d) + (*(uint32_t*)(param+0x24)) + b - 0x14792C6F;
b = ((b << 0x15) | (b >> 0x0b)) + c;

a += 0x67452301;
b += 0xefcdab89;
c += 0x98badcfe;
d += 0x10325476;

// switch to little endian
a = ((a&0xff000000)>>24) + ((a&0xff0000)>>8) + ((a&0xff00)<<8) + ((a&0xff)<<24);
b = ((b&0xff000000)>>24) + ((b&0xff0000)>>8) + ((b&0xff00)<<8) + ((b&0xff)<<24);
c = ((c&0xff000000)>>24) + ((c&0xff0000)>>8) + ((c&0xff00)<<8) + ((c&0xff)<<24);
d = ((d&0xff000000)>>24) + ((d&0xff0000)>>8) + ((d&0xff00)<<8) + ((d&0xff)<<24);

// write the pairing id and return it
char retval[33];
snprintf( retval, sizeof(retval), "%0X%0X%0X%0X", a, b, c, d );
return retval;
}

Monday, April 20, 2009

Teabagging the White House

By now, I suspect you have all heard of these anti-tax protests staged around the country on April 15th. For the benefit of posterity, I will give a brief synopsis. With the passing of the recent stimulus package of about $800 billion, Republicans are furious. To air their grievances, they have turned to the street and organized a nation-wide protest to decry the massive increase in taxes brought on by the stimulus package. They have chosen to refer to themselves as a tea party, in order to hearken back to Boston Tea Party of the revolution.

For starters, I don't know who it was that came up with the name of tea parties for these recent anti-tax protests, but I want to thank whoever it was. You have given us liberals a gift. Mocking you has never been so easy. These teabagging jokes just write themselves. The last time you gave us such a comedic gift of this quality, a lawyer was pulling BBs out of his face.

I love that they try to connect themselves to the Boston Tea Party. Republicans are trying to connect the current state of the nation with the state of pre-revolution America. Any grade-schooler can tell you the battle cry of the original tea partiers, "No taxation without representation!" But does that refer to the current state of America? Are Republicans being taxed without representation? They would have you think they are, but the answer is obviously no. In fact there are two problems with that claim.

The first problem with the above statement is the claim that we are being taxed. That is the most bizarre element of this whole circus. Taxes have not gone up. In fact, I just got my pay check for the last half of March. Guess what. My taxes went down. The stimulus package contained about $300 billion in tax cuts. Those were put in to appease the Republicans, who still refused to vote for it as a complete block. So, I'm not sure whose taxes you are protesting, not mine apparently.

Last I checked, Republicans still have the right to vote. The fact that more Americans disagree with them today than agree with them does not change the fact that they still have representation. Over the last eight years I watched as the leader made decision after decision that made me sick to my stomach. Did Democrats lack representation? No. We simply lacked control. That is the situation you are currently in. You mucked up government so bad that people decided that they had had enough and voted you guys out of office. Apparently though, your idea of being represented is that my viewpoint (and the views of the majority of America) be relegated to the dustbin. Ahhh... sounds like the Bush years.

It's illuminating to consider how Republicans considered protesters just a few years back. When Republicans were in power, anyone who voiced any sort of dissent were considered anti-American. I can't count the number of times I was personally called anti-American because I had the audacity to voice my disagreement with the current administration. According to Republicans of the past eight years, the First Ammendment provides all Americans the right to freely speak in favor of the Executive branch.

Well, the tables have certainly changed, haven't they? Your man is no longer in power, and the value of dissent has completely changed in your eyes as a result. Whereas you once considered dissent to be anti-American, you now have pundits like O'Reilly and Hannity extolling the great patriotic fervor of those protesting. How is it that when you disagree with the government you are patriotic, but when I do the same thing I am anti-American?!

I would like to state categorically that I believe peaceful public dissent to be a wonderful thing. It is a hallmark of a free nation. Although I think that these tea parties are ridiculous, I wholeheartedly encourage Americans who feel disenfranchised by Obama's presidency to let their voice be heard. Please keep it up. Protesting is not anti-American. Quite the contrary, it's one of the most American activities that exists.

The funniest part of this whole anti-American rhetoric is how there have been a number of tea parties where secession was advocated. This was especially the case in Texas, where even the governor tipped his hat to the seditious talk. So, let me get this right. If I believe that we should stop sending our children to die in Iraq, I am anti-American. But, if you advocate seceding, you are a patriot. In the words of my brother, "The party of Lincoln certainly has come full circle, hasn't it?"

Sunday, March 22, 2009

Translation Telephone

A friend recently sent me a list of phrases. They were all cliches that she had entered into an online translator then had it translate again and again and again. The results were generally pretty far from the original. I decided to create an automated version of the above. What follows below is just that. Enter in a phrase and click 'start'. The phrase will begin being translated between random languages and you can see how quickly it gets mutilated.

Translation Telephone
Original:
  Current:
 
  Current (English):