juhovh / shairplay

Apple airplay and raop protocol server
Other
1.35k stars 228 forks source link

ios 9.3 POST /pair-setup,POST /pair-verify #61

Closed Jack-lx closed 6 years ago

Jack-lx commented 8 years ago

POST /pair-verify or /pair-setup,how to handle these seesion?

POST /pair-setup RTSP/1.0 Content-Length: 32 Content-Type: application/octet-stream CSeq: 0 DACP-ID: 82F0F5B508E73AF1 Active-Remote: 3453826074 User-Agent: AirPlay/280.32.2

-k8hS( aG

RTSP/1.0 200 OK CSeq: 0 Content-Length: 32 Audio-Jack-Status: connected; type=analog Server: AirTunes/230.33

y|XT^{W7zVSsoFzGt

POST /pair-verify RTSP/1.0 X-Apple-AbsoluteTime: 481732246 X-Apple-PD: 1 Content-Length: 68 Content-Type: application/octet-stream CSeq: 1 DACP-ID: 82F0F5B508E73AF1 Active-Remote: 3453826074 User-Agent: AirPlay/280.32.2

P(XGd^+a;5lmpH^-k8hS( aG

RTSP/1.0 200 OK CSeq: 1 Content-Length: 96 Audio-Jack-Status: connected; type=analog Server: AirTunes/230.33

^Ns`>shrPbg1xYy=L^Xne:|6OB#hi^9m-^O/S^lb

POST /pair-verify RTSP/1.0 X-Apple-AbsoluteTime: 481732247 X-Apple-PD: 1 Content-Length: 68 Content-Type: application/octet-stream CSeq: 2 DACP-ID: 82F0F5B508E73AF1 Active-Remote: 3453826074 User-Agent: AirPlay/280.32.2

j8~oY6>J?[X|2U|iWn

RTSP/1.0 200 OK CSeq: 2 Content-Length: 0 Audio-Jack-Status: connected; type=analog Server: AirTunes/230.33

yong253535551 commented 8 years ago

hi,if anybody known to deal with POST /pair-verify or /pair-setup session, please email to me my email:yong253535551@163.com

yong253535551 commented 8 years ago

hi, i find code that can deal with pair-setup https://github.com/AlfredHunter/WifiAirCleaner/tree/6b03b730aaa72d817cff426d2237966ce984d801/Demos/COM.Apple.HomeKit

anhhna commented 8 years ago

hi, im reseaching on AirPlay, I found when I publish AirPlay service with:

txt.append(26); txt.append("deviceid="); txt.append(GetMacAddress()); // supposed to be: 0: video, 1:Phone, 3: Volume Control, 4: HLS // 9: Audio, 10: ? (but important without it it fails) 11: Audio redundant txt.append(24); txt.append("features=0x5A7FFFF7,0x1E"); txt.append(10); txt.append("flags=0x44"); txt.append(17); txt.append("model=AppleTV3,2C"); txt.append(36); txt.append("pk=7f2f132f6f6f64fff4ff6f2fff3f42f51"); txt.append(14); txt.append("srcvers="AIRPLAY_SERVER_VERSION_STR); txt.append(4); txt.append("ch=2");

notice that the pk=7f2f132f6f6f64fff4ff6f2fff3f42f51. I guess it is the private key, with this key at the pair-verify step, iPhone send to my App the hex string (this hex string changed every the iPhone send to App): (1) 01000000418cd3e6d6d01e6f01259e2411e9a8aff4849bac4abcb9a005b4d637ee4d1122d192b65eac6e37b1465038f7d23ee1ad1728cad406d41f118d4005bf1c15fd55

and we need to send back the hex string: (2) 78ef4d6f63eb73c40781ab621a392b53c2d607c650eb0f52f81ab685d096a400f0610341a6dd4c59cc8f53dcf04305e691aa86ba1a658a0bc5df06b45ba3d7d9bfbd0275cfb0797838e0ee2bec882c8519b89d7518ec7318653ab64c372f9e25

but I dont know how to Decode (1) string iPhone send to app to (2) string, did you find the way to deal with the pair-verify session, plz share to me, thank you so much

jiam-marvell commented 8 years ago

@yong253535551 @anhhna I check the HomeKit stuff. It only deal with application/x-tlv8. Nothing about application/octet-stream. I have same issue which you mentioned above. And I don't know how to do next. Did you fix your issue ?

shahasachin commented 7 years ago

I am facing same issue, if anybody know the solution for how to decode or what string should we pass please let me know. Thank you in advance.

Jack-lx commented 7 years ago

@yong253535551 @anhhna @shahasachin @Derek0425 @vranki ,Did you fix this issue ?homekit can't resolve this!

shahasachin commented 7 years ago

@Jack-lx, Didn't get solution. Yes, configured homekit but didn't get any solution.

msobiepanek-uz commented 7 years ago

@Jack-lx have you found out how to handle setup and verify steps?

ViktoriiaKh commented 7 years ago

Hello everyone! @funtax has reverse-engineered the Apple TV Device Verification. Here is the link to his Java-library: AirPlayAuth. I believe this will help you to solve this issue.

funtax commented 7 years ago

There's also an implementation available in Python & ObjectiveC and C.

jvah commented 7 years ago

Thank you @ViktoriiaKh for letting me know, and huge thanks for @funtax for the work! It's a bit hectic right now but I'll try to find some time for this.

Logical-sh commented 7 years ago

@funtax It looks like your implementation is only for /setup-pair-pin | binary-plist which is not the requests servers seem to get from Mac OS X. Have you figured out anything about the /pair-setup with a content type of octetstream?

funtax commented 7 years ago

Hey @comwizz2, sadly not, I have only focused a this implementation (done by reverse-engineering another app) as this was required by mine.

robertoandrade commented 7 years ago

@funtax implementation's seems to do the client-side of the /pair-verify step, even though it doesn't handle the /pair-setup, I notice that responding with random 32 bytes (or echoing back the same input) gets you to the next step, which is the verify one. Given the data it sends on the setup is also sent on the verify (ie: last 32 bytes) I'm wondering what the response from the first is used for if at all, given the request for verify doesn't seem to use it (unless it's using that as the edDSA Auth Key).

Any clues as to what the official client checks on the response for the first pair-verify call (it looks like from that code it's expecting the first 32 bytes to be the server public key and the last 64 just some random blob used for the signature that is sent on the 3rd step, but how does it verify that either the public key or the signature blob have anything to do with either the response from /pair-setup or even the pk entry on the mDNS broadcast I'm still puzzled to find out.

funtax commented 7 years ago

@robertoandrade I sadly removed the part where the verification of the mDNS "pk"-value as it wasn't mandatory for my case. Renaming the library and moving code broke the history in IntelliJ. The code I reverse-engineered was developed in scrambled Javascript.

I tried to re-code it a bit into Java.. it won't compile but might help:

` // line 235 in https://github.com/funtax/AirPlayAuth/blob/master/src/main/java/eu/airaudio/airplay/auth/AirPlayAuth.java

   Cipher aesCtr128Encrypt = Cipher.getInstance("AES/CTR/NoPadding");

    aesCtr128Encrypt.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(sharedSecretSha512AesKey, "AES"), new IvParameterSpec(sharedSecretSha512AesIV));

   // start edit
    EdDSAEngine edDSAEngine = new EdDSAEngine();
    byte[] signatureForVerify = aesCtr128Encrypt.update(Arrays.copyOfRange(pairVerify1Response, 32, pairVerify1Response.length));
    byte[] messageToVerify = AuthUtils.concatByteArrays(atvPublicKey, randomPublicKey);
    byte[] thePKFromMdns = new byte[32]; // I think was from Base64 mdns[extras][pk]
    edDSAEngine.initVerify(thePKFromMdns);
    if (edDSAEngine.verifyOneShot(messageToVerify, signatureForVerify)) {
        System.out.println("Signature verification successful!");
    }

    // end edit

    edDSAEngine = new EdDSAEngine();
    edDSAEngine.initSign(authKey);`
robertoandrade commented 7 years ago

Ok, awesome @funtax thanks for sharing this.

I'm trying to decipher what are the last 64 bytes of that 96 byte response from the first pair-verify, but from your client code it's not clear if if it's the simple concatenation of the server public key with the client public key given they try to verify that was the message signed via the PK (assuming another Public Key) in the mDNS record.

robertoandrade commented 7 years ago

Ok, I figured it out, just needed to do the inverse on the server, sign the server curve public key + client curve public key with the EdDSA private key and decrypt it with the derived AES key from the shared secret composed from the server curve private key and the client curve public key.

Thanks a bunch @funtax for the information, this was a lifesaver!

funtax commented 7 years ago

I'm super-happy to read this @robertoandrade . Really great news and good to know that my stuff has helped you :)

htartisan commented 7 years ago

Anyone know of any example c/c++ code for handling /pair-setup and /pair-verify messages sent to the AirPlay server by a connected device??? (or if not, perhaps some sudo-code?)

I see some mention of Java code above, but I'm not fluent in Java, and not good at deciphering the logic.

funtax commented 7 years ago

Hey @htartisan, you mean the client-side that connects to the Apple TV/AirPlay-receiver?

htartisan commented 7 years ago

No. I am trying to write write code for an AirPlay "server" device, that would support AirPlay mirroring. I can't find any documentation on how to do this (even from Apple), or any example code.

So far, I have successfully created the Bonjour server entry, and I can see the data from the "/pair-setup" message coming into my server code. I do not know how to interpret the "octec-stream" data that is being sent, or how to create the appropriate response. Beyond that, I know that I need to handle the "/pair-verify" message (interpret it's data) and create the appropriate response to that as well.

I would be very helpful for any help that anyone can offer.

htartisan commented 7 years ago

NOTE: AirPlay "server" device = a device that is connected to a monitor/TV, that can receive AirPlay streams.

robertoandrade commented 7 years ago

Depending on what kind of streams you want to process on your AirPlay "server" (aka receiver in Apple's lingo), you don't need to handle the pairing requests @htartisan, are you trying to handle Screen Mirroring, Audio, Remote Media or all of those?

htartisan commented 7 years ago

Initially, I am just trying to get Screen Mirroring to work. I will probably want to get audio, and perhaps even video to work in the future, but if I can just get the Screen Mirroring to work, that would be a big victory.

robertoandrade commented 7 years ago

Yeah for that you don't need to handle the pair-setup/pair-verify calls (with the proper mDNS broadcast), you'll only need to do that for sure to handle remote video streams.

You may wanna take a look at the long discussion we've had on https://github.com/espes/Slave-in-the-Magic-Mirror/issues/12

htartisan commented 7 years ago

I'll look there. Thanks!

kcosmos4 commented 7 years ago

@robertoandrade @funtax Thank you.

I received a lot of help.

Starting with golang's Airplay mirroring server related code ... Https://github.com/Vluxe/nighthawk Https://github.com/philippe44/RAOP-Player Https://github.com/funtax/AirPlayAuth Https://github.com/espes/Slave-in-the-Magic-Mirror Https://github.com/robertoandrade/playfair

I succeeded in protocol processing and mirroring data decryption in iOS 7 and 8. In iOS 10.3.3, pair-verify succeeds, but does not solve the mirroring data decryption key problem. (If features are given as 0x2beff7, you can go to the next step, fp-setup, without pair-verify.)

Did you solve the key problem?

robertoandrade commented 7 years ago

heya @funtax I was looking at using advertise mode 0x5A7FFFF7 instead of 0x527FFFF7 which forces the pairing to occur and I noticed the AES Key the clients use to encrypt the data (mirroring/audio) is different than the one they use it without pairing.

I was wondering if in your AirAudio implementation (which doesn't seem to be open source from what I could tell) you had any hints as to how the shared secret using during the pairing is used later on to derive the AES Key to be used to encrypt the actual streams?

funtax commented 7 years ago

Hey @robertoandrade, I am sorry but I have no more knowledge about the usage of the encryption-keys. AirAudio + AirSpot do audio-transmission via the AirPlay/AirTunes-protocol and this uses a key that is used within all clients/servers: https://www.theiphonewiki.com/wiki/AirPlay#Encryption

gagakang commented 7 years ago

@kcosmos4 hi, i noticed that you have In iOS 10.3.3, pair-verify succeeds,can you tell me the detail information?thank u so much.

juhovh commented 6 years ago

To be more specific, the relevant code seems to be at https://github.com/phonegapX/AirPlay/blob/master/AirplayLibrary/AirPlay/lib/raop.c#L1288

I have been too preoccupied by other stuff lately, but I'm hoping I would have time to at least do some initial tests of integrating this to the main codebase.

Jerzha commented 6 years ago

Got it, I found the different in curve25519_donna-c64. Replace this file with your code, I pass the pair-verify.

@juhovh 哈哈,是啊。中国人歪点子多。

juhovh commented 6 years ago

Just out of curiosity, do you mean the if (basepoint == NULL) basepoint = kCurve25519BasePoint; line when you say the difference in curve25519_donna-c64?

Jerzha commented 6 years ago

Yep...

ghost commented 6 years ago

Hey guys,

Having issues on ios 11.3.

In airserver I see:

INFO pair-setup/pair-verify 0/pairverify 1 fp-setup 1 fp-setup 2 SETUP (no streams) INFO RECORD GET/SET PARAMETER (volume) SETUP (with streams)

My code works fine until the last setup. I don't get any second setup message at all. Do you have your code working on ios 11.3? Can you confirm the flow you see?

robertoandrade commented 6 years ago

@kam187 last I checked the flow is the same in 11.3, depending on what you're playing on the sender, you may even get a 3rd SETUP call (one for screen and one for audio).

ghost commented 6 years ago

Hmm, I wonder why I don't get the second setup. Does your code work with ios 11.3?

robertoandrade commented 6 years ago

yep, but my codebase is not related to this project at all.

ghost commented 6 years ago

Ok found the issue, i wasn't sending a 'name' and 'pk' in the info. Previously i had disabled pair-verify :) . Working now.

ghost commented 6 years ago

Ok another issue. It seems on ios11.3 it does not connect back to the event port. It works fine on lower versions.

ghost commented 6 years ago

Nevermind it's down to sending an error on my part.

Jerzha commented 6 years ago

@382517366 是的,但是curve25519_donna这个函数跟你网上下到的有一点点小区别

Jerzha commented 6 years ago

@382517366 我不是对着这个工程开发的。我是开发遇到问题点刚好看到这里在讨论才进来讨论的。你直接使用https://github.com/phonegapX/AirPlay 这套代码里的这个库就没问题的。

Jerzha commented 6 years ago

@382517366 恩,对的,我们也是用64写的,没问题的。

juhovh commented 6 years ago

Just to let you know, I have removed comments from notedit and modified references to his repo to point to phonegapX repo instead. It turns out the only reason notedit joined this discussion and cloned phonegapX's repository was to promote his proprietary SDK he is trying to sell, he has done no open source work on airplay protocol whatsoever.

juhovh commented 6 years ago

Just to let you all know again, I have just pushed to master the code that is able to handle POST /pair-setup and POST /pair-verify requests successfully, fp-setup is still not handled but I guess I'll throw in some similar solution to that than what foxsen had but with a bit different implementation.

juhovh commented 6 years ago

I have now committed a version of shairplay to master that allows receiving audio from iOS with the full /pair-setup, /pair-verify and /fp-setup handshake. It is using https://github.com/EstebanKubata/playfair library and is only enabled with --with-playfair configure flag, because the legal status of that library is unclear and it is GPLv3 therefore tainting the whole shairplay code. I have tested it to work with iOS 11.4.1 but it unfortunately does not work with iTunes because it uses a different version of fairplay. Hope this is helpful and have fun playing with it, closing this issue.

jmvermeulen commented 6 years ago

The chinese guys above seem to have cracked it! Trying to get their code running.

tishion commented 6 years ago

@jmvermeulen lol, there are so many product working correctly in China, if you pay me 10 thousands i will give you the code.

Kidding.

juhovh commented 6 years ago

@tishion thanks for the edit, without it your comment was a bit too close to reality to be funny

@jmvermeulen the code in the phonegapX repository is very Windows specific, I've already ported the key exchange and fairplay decryption parts, and shairplay compiled with --with-playfair is able to get working decryption keys for both screen mirroring and audio, just haven't got time to write the rest of it yet.