如何解码FPLY(Airplay Mirroring)DRM密钥

时间:2018-04-25 08:56:53

标签: macos aes drm airplay fairplay

我正在为Mac开发AirPlay Mirroring Server App(与AirServer相同),但我不知道如何解码从SETUP获得的“ekey”的值。

启动Airplay服务器

//Init Roap Server
[[NSNetService alloc] initWithDomain:@"local" type:@"_raop._tcp" name:@"" port:5000]
//TXTRecordData
"txtvers"="1",
"ch"= "2",
"cn"= "0,1,2,3",
"sr"= "44100",
 "ss"= "16",
"tp"= "UDP",
"et"= "0,1,3"
"md"= "0,1,2",
"pw"= "false",
 "vs"= "220.68",
"am"= "AppleTV3,2",
"ek"= "1",
"vn"= "65537",

//Init Airplay
[[NSNetService alloc] initWithDomain:@"local" type:@"_airplay._tcp"  name:@"" port:7000]
//TXTRecordData
"srcvers"= "220.68",
"model"= "AppleTV3,2",
"features"= "0x527FFFF7",
"deviceid"= "BC:1C:81:2F:7D:BF",
"vv"= "1",
"pw"= "0",
"flag"= "0x4",

数据传输

//Client to Server
GET /info RTSP/1.0
{ "Active-Remote" = 1553699736;  CSeq = 0; "Content-Length" = 70; "Content-Type" = "application/x-apple-binary-plist"; "DACP-ID" = 880572F7DB786729;"User-Agent" = "AirPlay/365.53";"X-Apple-ProtocolVersion" = 1;}
ContentData:{ qualifier =     ( txtAirPlay ); }

//Server to Client
RTSP/1.0 200 OK
{ CSeq = 0;"Content-Length" = 741;"Content-Type" = "application/x-apple-binary-plist";Server = "AirTunes/220.68";}
ContentData:{audioFormats =     ({audioInputFormats = 67108860;audioOutputFormats = 67108860;type = 100; },{audioInputFormats = 67108860;audioOutputFormats = 67108860;type = 101; });audioLatencies =     ({audioType = default;inputLatencyMicros = 3;outputLatencyMicros = 79;type = 100;},{audioType = default;inputLatencyMicros = 3;outputLatencyMicros = 79;type = 101;} );deviceID = "20:C9:D0:44:25:FD";displays =     ({features = 14;height = 960;heightPhysical = 0;heightPixels = 960;overscanned = 0;refreshRate = "59.999996";rotation = 0;width = 1280;widthPhysical = 0;widthPixels = 1280;});et = 0;features = 1384120311;keepAliveLowPower = 1;keepAliveSendStatsAsBody = 1;macAddress = "BC:1C:81:2F:7D:BF";model = "AppleTV3,2";name = "Record It";pw = 0;sourceVersion = "220.68";statusFlags = 68;vv = 1;}

//Client to Server
POST /fp-setup RTSP/1.0
{ "Active-Remote" = 3248110323;CSeq = 1; "Content-Length" = 16;"Content-Type" = "application/octet-stream";"DACP-ID" = B3DCE4E90AE68162;"User-Agent" = "AirPlay/365.53";"X-Apple-ET" = 32;}
ContentData:<46504c59 03010100 00000004 020003bb>
Description:FPLY 3 1 1 ...

//Server to Client
RTSP/1.0 200 OK
{CSeq = 1;Connection = "keep-alive";"Content-Length" = 142;"Content-Type" = "application/octet-stream";Date = "Wed, 25 Apr 2018 16:30:26 GMT+8";Server = "AirTunes/220.68";"X-Apple-ET" = 32;}
ContentData:<46504c59 03010200 00000082 02039001 e1727e0f 57f9f588 0db104a6 257a23f5 cfff1abb e1e93045 251afb97 eb9fc001 1ebe0f3a 81df5b69 1d76acb2 f7a5c708 e3d328f5 6bb39dbd e5f29c8a 17f48148 7e3ae863 c6783254 22e6f78e 166d18aa 7fd63625 8bce2872 6f661f73 8893ce44 311e4be6 c0535193 e5ef72e8 68623372 9c227d82 0c999445 d89246c8 c359>
Description:FPLY 3 1 2...

//Client to Server
POST /fp-setup RTSP/1.0
{"Active-Remote" = 3248110323; CSeq = 2;"Content-Length" = 164; "Content-Type" = "application/octet-stream";"DACP-ID" = B3DCE4E90AE68162;"User-Agent" = "AirPlay/365.53";"X-Apple-ET" = 32;}
ContentData:<46504c59 03010300 00000098 038f1a9c ca3535b1 994b980e 4b746e4a 738943b9 1d2a0751 95b0888d 2c9bf700 a6995754 becf37e2 d5260eea 6b7337ac 257f9a31 818efd4c 3d0d71e8 76222f52 9a832d8f 7fce61d1 b6d55552 3cd1da7d 7cddde34 253a03f3 d1866f4e f942587c d863abd9 9c7c97e4 489ecd0e 6b4faf5b 3f8e4bd6 564c3dbe 55bd5c64 d509d2f3 ba21754c 5c604c51 6704846d 5f14fd5a 916348cc e7df54a4>
Description:FPLY 3 1 3 ...

//Server to Client
RTSP/1.0 200 OK
{ CSeq = 2; Connection = "keep-alive";  "Content-Length" = 32; "Content-Type" = "application/octet-stream"; Date = "Wed, 25 Apr 2018 16:30:26 GMT+8"; Server = "AirTunes/220.68"; "X-Apple-ET" = 32;}
ContentData:<46504c59 03010400 00000014 5c604c51 6704846d 5f14fd5a 916348cc e7df54a4>
Description:FPLY 3 1 4 ...

下一个SETUP请求将返回ekey(72字节)/ eiv(16字节)值。但我不知道如何将“ekey”的值解码为aesKey(16bytes)?

//Client to Server
SETUP rtsp://fe80::cf2:4fbd:43ee:caf2/12938411574340831071 RTSP/1.0
{ "Active-Remote" = 3248110323; CSeq = 3; "Content-Length" = 454; "Content-Type" = "application/x-apple-binary-plist"; "DACP-ID" = B3DCE4E90AE68162; "User-Agent" = "AirPlay/365.53";}
{ deviceID = "4C:57:CA:DB:12:B7";
    eiv = <42c6ae2a 3ee2b019 dc224f3e 0635c877>;
    ekey = <46504c59 01020100 0000003c 00000000 5df231d0 3b28e479 4d4e4411 f562788c 00000010 66e79650 b6327c4c 5ca0e829 ab2dbda8 13ce07c3 951e070f f2db29d2 78bd144e e8f9729a>;
    et = 32;
    macAddress = "4E:57:CA:DB:12:48"; model = "iPhone8,4"; name = "\U6731\U4e1c\U52c7\U7684 iPhone"; osBuildVersion = 15E216; sessionUUID = "B38E78C6-B663-475F-82E1-3E41D87E5BC5"; sourceVersion = "365.53"; timingPort = 59586; timingProtocol = NTP; }

接下来,初始化数据套接字,定时套接字,控制套接字。最后,通过上述 aeskey eiv 获取视频/音频数据的解码。

int left = 128;
unsigned int d_width = 0, d_height = 0, d_size = 0, d_type = 0;
char headdata[128];
int i;
const int MAX_BUF_SIZE = 4*1024*1024;
unsigned char *out_buffer = (unsigned char *)malloc(MAX_BUF_SIZE);
unsigned char *p_buffer = (unsigned char *)malloc(MAX_BUF_SIZE);

AES_KEY key;
AES_set_encrypt_key((const unsigned char*)aesKey.bytes, 128, &key);
while (1) {
    //read 128 bytes to headdata
    d_width  = *(int32_t*)&headdata[16];   //headdata[16] | (headdata[17] << 8) | (headdata[18] << 16) | (headdata[19] << 24);
    d_height = *(int32_t*)&headdata[20];   // headdata[20] | (headdata[21] << 8) | (headdata[22] << 16) | (headdata[23] << 24);
    d_size = *(int32_t*)&headdata[0]; //headdata[0] | (headdata[1] << 8)  | (headdata[2] << 16)  | (headdata[3] << 24);
    d_type = *(int16_t*)&headdata[4];  //& 0x3;
    //read d_size bytes to  p_buffer
     if (d_type == 1) {//Encode inc info
        //sps
        long sps_size = p_buffer[6] << 8 | p_buffer[7];
        NSMutableData* sps = [NSMutableData dataWithCapacity:sps_size];
         [sps appendBytes:&p_buffer[8] length:sps_size];
         //pps
         long pps_size = p_buffer[9+sps_size] << 8 | p_buffer[10+sps_size];
         NSMutableData* pps = [NSMutableData dataWithCapacity:pps_size];
         [pps appendBytes:&p_buffer[11+sps_size] length:pps_size];
         // setup up video decode with sps and pps
    } else if (d_type == 0) {//Video Data Info
         AES_ctr128_encrypt(p_buffer, out_buffer, d_size,
                                                   &key, (unsigned char*)eiv.bytes,
                                                   ecount, &num);
         //Decode Video Buffer User Video Decode
    }else if (d_type == 3) {//Heart beat

    } else if (d_type == 5) {

    }
}

0 个答案:

没有答案