From 2d730200a2743bd92d5015d005573b3e91a2d8de Mon Sep 17 00:00:00 2001 From: "sgunderson@bigfoot.com" <> Date: Sun, 21 Feb 2010 02:31:11 +0100 Subject: [PATCH] Initial commit. --- decrypt.c | 45 ++++++ ice.c | 422 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ice.h | 30 ++++ lookup.pl | 136 ++++++++++++++++++ lookup.sh | 5 + 5 files changed, 638 insertions(+) create mode 100644 decrypt.c create mode 100644 ice.c create mode 100644 ice.h create mode 100644 lookup.pl create mode 100755 lookup.sh diff --git a/decrypt.c b/decrypt.c new file mode 100644 index 0000000..4e43133 --- /dev/null +++ b/decrypt.c @@ -0,0 +1,45 @@ +#include +#include +#include "ice.h" + +#define SIZE 24169 + +//#define OVERRIDE "\x2D\x21\xDD\x71\x7A\x8F\xD8\x68\xF4\xFF\x01\x85\x36\xD2\x7B\x00\x85\xAE\x78\xA9\xA4\xF9\xB6\xC0\x4E\xD6\x39\xC6\x7D\x27\xF0\xD4" +//#define OVERRIDE "\x2D\x21\xDD\x71\x7A\x8F\xD8\x68\xF4\xFF\x01\x85\x36\xD2\x7B\x00\x85\xAE\x78\xA9\xA4\xF9\xB6\xC0\xC9\xB5\x42\xD3\xF2\x80\x4F\xEF" +//#define OVERRIDE "\x02\xC0\xD0\x66\x8E\x80\x12\x00\x58\xC9\x51\x24\x7D\x1A\xFA\x17\x3A\x64\xC9\xFB\xEC\xD2\xF2\x04\x5A\x18\xEC\xF7\x63\x52\x87\x8E\x9E\xEE\xD5\x1D\x5E\x07\x13\xBD\x30\xDA\x82\xD9\xAF\x85\x48\x07\x46\x21\xF7\x22\x35\x1C\x00\x88\x2F\xD9\x60\xD3\x05\x08\x49\x5A\x4C\x48\x51\x65\xE5\x9A\xFD\x1A\x7C\x8F\x7B\xAB\xF6\x8A\xBF\x2B\xBA\x68\x6D\x0B\xC6\x2B\x6A\x69\x39\x2B\xD8\x24\x30\xE1\xDF\x77\xAF\xEF\xF5\x05\x79\x07\xD2\x66\xC0\x76\x50\x7D\x54\x1F\x3D\xF4\x59\xF6\x15\x64\x7C\x8A\x00\x18\x46\x72\xDD\xAA\x63\xF7\x3D\x0E\x72\x75\x30\xC8\x69\x90\xDE\xF9" +//#define OVERRIDE "\xF1\x36\x0E\x2D\x9D\x9F\xB8\x98\xE7\x43\xED\x6C\xEF\x4E\xAB\xB8" +//#define OVERRIDE "\x2D\x21\xDD\x71\x7A\x8F\xD8\x68\xF4\xFF\x01\x85\x36\xD2\x7B\x00\x85\xAE\x78\xA9\xA4\xF9\xB6\xC0\x4E\xD6\x39\xC6\x7D\x27\xF0\xD4" +//#define OVERRIDE "\xF1\xA1\xC0\x23\xBF\xF8\x94\x77\xF7\x86\x51\x7C\x0C\x39\x09\xB0" +//#define OVERRIDE "\x2D\x21\xDD\x71\x7A\x8F\xD8\x68\xF4\xFF\x01\x85\x36\xD2\x7B\x00\x85\xAE\x78\xA9\xA4\xF9\xB6\xC0\x4E\xD6\x39\xC6\x7D\x27\xF0\xD4" +//#define OVERRIDE "\x3B\xF6\xCC\x26\x9B\xE4\x5F\xCB\x1F\x82\x6C\x2E\xD5\xE4\x77\x3B" +//#define OVERRIDE "\x80\xF9\x72\xA5\x94\x52\xF4\xC8\xE0\x96\xF4\x27\x6B\xA9\x15\x49" +//#define OVERRIDE "\x72\x11\xC5\x95\xDC\xFF\x32\x0C\x78\x48\x85\x50\x10\xE2\x79\x2C" +//#define OVERRIDE "\xF1\xA1\xC0\x23\xBF\xF8\x94\x77\xF7\x86\x51\x7C\x0C\x39\x09\xB0" +#define OVERRIDE "\xC9\x91\xCC\x4E\xFD\x1A\xC7\xD2" + +#ifdef OVERRIDE +#undef SIZE +#define SIZE (sizeof(OVERRIDE)-1) +#endif + +unsigned char keymat[] = { 0x5C, 0x09, 0xD8, 0x3A, 0x2A, 0x3A, 0x47, 0x8A }; + +int main(int argc, char **argv) +{ + FILE *amr = fopen(argv[1], "rb"); + unsigned char in[SIZE], out[SIZE]; + int i; + ICE_KEY *key = ice_key_create(1); //? + ice_key_set(key, keymat); + +#ifdef OVERRIDE + memcpy(in, OVERRIDE, SIZE); +#else + fread(in, SIZE, 1, amr); +#endif + + for (i = 0; i < SIZE; i += 8) { + ice_key_decrypt(key, in + i, out + i); + } + fwrite(out, SIZE, 1, stdout); +} diff --git a/ice.c b/ice.c new file mode 100644 index 0000000..32d0e67 --- /dev/null +++ b/ice.c @@ -0,0 +1,422 @@ +/* + * Implementation of the ICE encryption algorithm. + * + * Written by Matthew Kwan - July 1996 + */ + +#include "ice.h" +#include +#include + + + /* Structure of a single round subkey */ +typedef unsigned long ICE_SUBKEY[3]; + + + /* Internal structure of the ICE_KEY structure */ +struct ice_key_struct { + int ik_size; + int ik_rounds; + ICE_SUBKEY *ik_keysched; +}; + + /* The S-boxes */ +static unsigned long ice_sbox[4][1024]; +static int ice_sboxes_initialised = 0; + + + /* Modulo values for the S-boxes */ +static const int ice_smod[4][4] = { + {333, 313, 505, 369}, + {379, 375, 319, 391}, + {361, 445, 451, 397}, + {397, 425, 395, 505}}; + + /* XOR values for the S-boxes */ +static const int ice_sxor[4][4] = { + {0x83, 0x85, 0x9b, 0xcd}, + {0xcc, 0xa7, 0xad, 0x41}, + {0x4b, 0x2e, 0xd4, 0x33}, + {0xea, 0xcb, 0x2e, 0x04}}; + + /* Expanded permutation values for the P-box */ +static const unsigned long ice_pbox[32] = { + 0x00000001, 0x00000080, 0x00000400, 0x00002000, + 0x00080000, 0x00200000, 0x01000000, 0x40000000, + 0x00000008, 0x00000020, 0x00000100, 0x00004000, + 0x00010000, 0x00800000, 0x04000000, 0x20000000, + 0x00000004, 0x00000010, 0x00000200, 0x00008000, + 0x00020000, 0x00400000, 0x08000000, 0x10000000, + 0x00000002, 0x00000040, 0x00000800, 0x00001000, + 0x00040000, 0x00100000, 0x02000000, 0x80000000}; + + /* The key rotation schedule */ +static const int ice_keyrot[16] = { + 0, 1, 2, 3, 2, 1, 3, 0, + 1, 3, 2, 0, 3, 1, 0, 2}; + + +/* + * Galois Field multiplication of a by b, modulo m. + * Just like arithmetic multiplication, except that additions and + * subtractions are replaced by XOR. + */ + +static unsigned int +gf_mult ( + register unsigned int a, + register unsigned int b, + register unsigned int m +) { + register unsigned int res = 0; + + while (b) { + if (b & 1) + res ^= a; + + a <<= 1; + b >>= 1; + + if (a >= 256) + a ^= m; + } + + return (res); +} + + +/* + * Galois Field exponentiation. + * Raise the base to the power of 7, modulo m. + */ + +static unsigned long +gf_exp7 ( + register unsigned int b, + unsigned int m +) { + register unsigned int x; + + if (b == 0) + return (0); + + x = gf_mult (b, b, m); + x = gf_mult (b, x, m); + x = gf_mult (x, x, m); + return (gf_mult (b, x, m)); +} + + +/* + * Carry out the ICE 32-bit P-box permutation. + */ + +static unsigned long +ice_perm32 ( + register unsigned long x +) { + register unsigned long res = 0; + register const unsigned long *pbox = ice_pbox; + + while (x) { + if (x & 1) + res |= *pbox; + pbox++; + x >>= 1; + } + + return (res); +} + + +/* + * Initialise the ICE S-boxes. + * This only has to be done once. + */ + +static void +ice_sboxes_init (void) +{ + register int i; + + for (i=0; i<1024; i++) { + int col = (i >> 1) & 0xff; + int row = (i & 0x1) | ((i & 0x200) >> 8); + unsigned long x; + + x = gf_exp7 (col ^ ice_sxor[0][row], ice_smod[0][row]) << 24; + ice_sbox[0][i] = ice_perm32 (x); + + x = gf_exp7 (col ^ ice_sxor[1][row], ice_smod[1][row]) << 16; + ice_sbox[1][i] = ice_perm32 (x); + + x = gf_exp7 (col ^ ice_sxor[2][row], ice_smod[2][row]) << 8; + ice_sbox[2][i] = ice_perm32 (x); + + x = gf_exp7 (col ^ ice_sxor[3][row], ice_smod[3][row]); + ice_sbox[3][i] = ice_perm32 (x); + } +} + + +/* + * Create a new ICE key. + */ + +ICE_KEY * +ice_key_create ( + int n +) { + ICE_KEY *ik; + + if (!ice_sboxes_initialised) { + ice_sboxes_init (); + ice_sboxes_initialised = 1; + } + + if ((ik = (ICE_KEY *) malloc (sizeof (ICE_KEY))) == NULL) + return (NULL); + + if (n < 1) { + ik->ik_size = 1; + ik->ik_rounds = 8; + } else { + ik->ik_size = n; + ik->ik_rounds = n * 16; + } + + if ((ik->ik_keysched = (ICE_SUBKEY *) malloc (ik->ik_rounds + * sizeof (ICE_SUBKEY))) == NULL) { + free (ik); + return (NULL); + } + + return (ik); +} + + +/* + * Destroy an ICE key. + * Zero out the memory to prevent snooping. + */ + +void +ice_key_destroy ( + ICE_KEY *ik +) { + int i, j; + + if (ik == NULL) + return; + + for (i=0; iik_rounds; i++) + for (j=0; j<3; j++) + ik->ik_keysched[i][j] = 0; + + ik->ik_rounds = ik->ik_size = 0; + + if (ik->ik_keysched != NULL) + free (ik->ik_keysched); + + free (ik); +} + + +/* + * The single round ICE f function. + */ + +static unsigned long +ice_f ( + register unsigned long p, + const ICE_SUBKEY sk +) { + unsigned long tl, tr; /* Expanded 40-bit values */ + unsigned long al, ar; /* Salted expanded 40-bit values */ + + /* Left half expansion */ + tl = ((p >> 16) & 0x3ff) | (((p >> 14) | (p << 18)) & 0xffc00); + + /* Right half expansion */ + tr = (p & 0x3ff) | ((p << 2) & 0xffc00); + + /* Perform the salt permutation */ + /* al = (tr & sk[2]) | (tl & ~sk[2]); */ + /* ar = (tl & sk[2]) | (tr & ~sk[2]); */ + al = sk[2] & (tl ^ tr); + ar = al ^ tr; + al ^= tl; + + al ^= sk[0]; /* XOR with the subkey */ + ar ^= sk[1]; + + /* S-box lookup and permutation */ + return (ice_sbox[0][al >> 10] | ice_sbox[1][al & 0x3ff] + | ice_sbox[2][ar >> 10] | ice_sbox[3][ar & 0x3ff]); +} + + +/* + * Encrypt a block of 8 bytes of data with the given ICE key. + */ + +void +ice_key_encrypt ( + const ICE_KEY *ik, + const unsigned char *ptext, + unsigned char *ctext +) { + register int i; + register unsigned long l, r; + + l = (((unsigned long) ptext[0]) << 24) + | (((unsigned long) ptext[1]) << 16) + | (((unsigned long) ptext[2]) << 8) | ptext[3]; + r = (((unsigned long) ptext[4]) << 24) + | (((unsigned long) ptext[5]) << 16) + | (((unsigned long) ptext[6]) << 8) | ptext[7]; + + for (i = 0; i < ik->ik_rounds; i += 2) { + l ^= ice_f (r, ik->ik_keysched[i]); + r ^= ice_f (l, ik->ik_keysched[i + 1]); + } + + for (i = 0; i < 4; i++) { + ctext[3 - i] = r & 0xff; + ctext[7 - i] = l & 0xff; + + r >>= 8; + l >>= 8; + } +} + + +/* + * Decrypt a block of 8 bytes of data with the given ICE key. + */ + +void +ice_key_decrypt ( + const ICE_KEY *ik, + const unsigned char *ctext, + unsigned char *ptext +) { + register int i; + register unsigned long l, r; + + l = (((unsigned long) ctext[0]) << 24) + | (((unsigned long) ctext[1]) << 16) + | (((unsigned long) ctext[2]) << 8) | ctext[3]; + r = (((unsigned long) ctext[4]) << 24) + | (((unsigned long) ctext[5]) << 16) + | (((unsigned long) ctext[6]) << 8) | ctext[7]; + + for (i = ik->ik_rounds - 1; i > 0; i -= 2) { + l ^= ice_f (r, ik->ik_keysched[i]); + r ^= ice_f (l, ik->ik_keysched[i - 1]); + } + + for (i = 0; i < 4; i++) { + ptext[3 - i] = r & 0xff; + ptext[7 - i] = l & 0xff; + + r >>= 8; + l >>= 8; + } +} + + +/* + * Set 8 rounds [n, n+7] of the key schedule of an ICE key. + */ + +static void +ice_key_sched_build ( + ICE_KEY *ik, + unsigned short *kb, + int n, + const int *keyrot +) { + int i; + + for (i=0; i<8; i++) { + register int j; + register int kr = keyrot[i]; + ICE_SUBKEY *isk = &ik->ik_keysched[n + i]; + + for (j=0; j<3; j++) + (*isk)[j] = 0; + + for (j=0; j<15; j++) { + register int k; + unsigned long *curr_sk = &(*isk)[j % 3]; + + for (k=0; k<4; k++) { + unsigned short *curr_kb = &kb[(kr + k) & 3]; + register int bit = *curr_kb & 1; + + *curr_sk = (*curr_sk << 1) | bit; + *curr_kb = (*curr_kb >> 1) | ((bit ^ 1) << 15); + } + } + } +} + + +/* + * Set the key schedule of an ICE key. + */ + +void +ice_key_set ( + ICE_KEY *ik, + const unsigned char *key +) { + int i; + + if (ik->ik_rounds == 8) { + unsigned short kb[4]; + + for (i=0; i<4; i++) + kb[3 - i] = (key[i*2] << 8) | key[i*2 + 1]; + + ice_key_sched_build (ik, kb, 0, ice_keyrot); + return; + } + + for (i = 0; i < ik->ik_size; i++) { + int j; + unsigned short kb[4]; + + for (j=0; j<4; j++) + kb[3 - j] = (key[i*8 + j*2] << 8) | key[i*8 + j*2 + 1]; + + ice_key_sched_build (ik, kb, i*8, ice_keyrot); + ice_key_sched_build (ik, kb, ik->ik_rounds - 8 - i*8, + &ice_keyrot[8]); + } +} + + +/* + * Return the key size, in bytes. + */ + +int +ice_key_key_size ( + const ICE_KEY *ik +) { + return (ik->ik_size * 8); +} + + +/* + * Return the block size, in bytes. + */ + +int +ice_key_block_size ( + const ICE_KEY *ik +) { + return (8); +} diff --git a/ice.h b/ice.h new file mode 100644 index 0000000..4810490 --- /dev/null +++ b/ice.h @@ -0,0 +1,30 @@ +/* + * Header file for the ICE encryption library. + * + * Written by Matthew Kwan - July 1996 + */ + +#ifndef _ICE_H +#define _ICE_H + +typedef struct ice_key_struct ICE_KEY; + +#if __STDC__ +#define P_(x) x +#else +#define P_(x) () +#endif + +extern ICE_KEY *ice_key_create P_((int n)); +extern void ice_key_destroy P_((ICE_KEY *ik)); +extern void ice_key_set P_((ICE_KEY *ik, const unsigned char *k)); +extern void ice_key_encrypt P_((const ICE_KEY *ik, + const unsigned char *ptxt, unsigned char *ctxt)); +extern void ice_key_decrypt P_((const ICE_KEY *ik, + const unsigned char *ctxt, unsigned char *ptxt)); +extern int ice_key_key_size P_((const ICE_KEY *ik)); +extern int ice_key_block_size P_((const ICE_KEY *ik)); + +#undef P_ + +#endif diff --git a/lookup.pl b/lookup.pl new file mode 100644 index 0000000..465c683 --- /dev/null +++ b/lookup.pl @@ -0,0 +1,136 @@ +#! /usr/bin/perl +use LWP::UserAgent; +use HTTP::Request; +use IPC::Open2; +use XML::DOM; +use POSIX; + +my $ua = LWP::UserAgent->new; +push(@LWP::Protocol::http::EXTRA_SOCK_OPTS, SendTE => 0); +$ua->agent('Dalvik/1.2.0 (Linux; U; Android Froyo Build/MASTER)'); + +my $requestid = recognize($ua, $ARGV[0]); +lookup($ua, $requestid); + +sub recognize { + my ($ua, $filename) = @_; + my $amr; + { + local $/ = undef; + $amr = `cat $filename`; + } + + my @parts = ( + language => make_part('en_US'), + service => make_part('cn=CH,cn=V3,cn=SmartClub,cn=ShazamiD,cn=services'), + applicationIdentifier => make_encrypted_string('ShazamId_SmartPhone_Gamma__1.2'), + deviceId => make_encrypted_string('1234567812345678'), + deviceModel => make_encrypted_string('Nexus_One'), + userAgent => make_encrypted_string('Mozilla/5.0_(Linux;_U;_Android_1.0;_en-us;_generic)_AppleWebKit/525.10+_(KHTML,_like_Gecko)_Version/3.0.4_Mobile_Safari/523.12.2'), + tagDate => make_encrypted_string(POSIX::strftime("%Y-%m-%dT%H:%M:%S", localtime)), + cryptToken => make_encrypted_string('A220B36F'), + sample => make_encrypted_part($amr, 'janet.3gp.amr', 'application/octet-stream'), + ); + + my $res = $ua->post( + 'http://goog.shazamid.com/orbit/DoRecognition1', + \@parts, + 'content-language' => 'en_US', + 'Content_Type' => 'multipart/form-data; boundary=A3r_ISAAC_eQeY2Bh'); + + if (!$res->is_success) { + die $res->status_line; + } + + my $parser = XML::DOM::Parser->new; + my $doc = $parser->parse($res->content); + my $ids = $doc->getElementsByTagName("requestId"); + if ($ids->getLength == 0) { + print "Didn't recognize song\n"; + exit; + } + return $ids->item(0)->getAttribute('id'); +} + +sub lookup { + my ($ua, $requestid) = @_; + + my @parts = ( + language => make_part('en_US'), + service => make_part('cn=CH,cn=V3,cn=SmartClub,cn=ShazamiD,cn=services'), + applicationIdentifier => make_encrypted_string('ShazamId_SmartPhone_Gamma__1.2'), + deviceId => make_encrypted_string('1234567812345678'), + deviceModel => make_encrypted_string('Nexus_One'), + userAgent => make_encrypted_string('Mozilla/5.0_(Linux;_U;_Android_1.0;_en-us;_generic)_AppleWebKit/525.10+_(KHTML,_like_Gecko)_Version/3.0.4_Mobile_Safari/523.12.2'), + requestId => make_encrypted_string($requestid), + coverartSize => make_encrypted_string('304'), + artistartX => make_encrypted_string('81'), + artistartY => make_encrypted_string('0'), + cryptToken => make_encrypted_string('A220B36F'), + ); + + my $res = $ua->post( + 'http://goog.shazamid.com/orbit/RequestResults1', + \@parts, + 'content-language' => 'en_US', + 'Content_Type' => 'multipart/form-data; boundary=A3r_ISAAC_eQeY2Bh'); + + if (!$res->is_success) { + die $res->status_line; + } + + my $parser = XML::DOM::Parser->new; + my $doc = $parser->parse($res->content); + my $tracks = $doc->getElementsByTagName("track"); + if ($tracks->getLength == 0) { + print "Didn't recognize song\n"; + exit; + } + my $track = $tracks->item(0); + my $title = $track->getElementsByTagName("ttitle")->item(0)->getFirstChild->getData; + my $artist = $track->getElementsByTagName("tartist")->item(0)->getFirstChild->getData; + + print "$title,$artist\n"; +} + +sub make_part { + my ($content, $filename, $mime_type) = @_; + if (defined($mime_type)) { + return [ undef, $filename, 'Content' => $content, 'Content-Type' => $mime_type ]; + } else { + return [ undef, $filename, 'Content' => $content ]; + } +} + +sub make_encrypted_string { + my ($content, $filename, $mime_type) = @_; + if (length($content) % 8 == 0) { + $content .= "\0\0\0\0\0\0\0\0"; + } + my $enc = '#0x' . join("", map { sprintf "%02X", $_ } (unpack("W*", encrypt($content)))); + return make_part($enc, $filename, $mime_type); +} + +sub make_encrypted_part { + my ($content, $filename, $mime_type) = @_; + my $enc = encrypt($content); + return make_part($enc, $filename, $mime_type); +} + +sub encrypt { + my $content = shift; + my $blocks = (length($content) + 7) / 8; + my $ret = ""; + local $/ = undef; + + $pid = open2(\*CHLD_OUT, \*CHLD_IN, './encrypt-ice'); + for my $i (0..($blocks-1)) { + my $block = substr($content, 8*$i, 8); + print CHLD_IN $block; + } + + close CHLD_IN; + $ret = ; + close CHLD_OUT; + return $ret; +} diff --git a/lookup.sh b/lookup.sh new file mode 100755 index 0000000..ac99286 --- /dev/null +++ b/lookup.sh @@ -0,0 +1,5 @@ +#! /bin/sh +rm -f shazam.wav shazam.amr +mplayer -really-quiet -vc null -vo null -endpos 15 -ao pcm:fast:file=shazam.wav "$1" +ffmpeg -i shazam.wav -ab 12.2k -ac 1 -ar 8000 shazam.amr >& /dev/null +perl lookup.pl shazam.amr -- 2.39.2