very messy experiments in facetime links

This commit is contained in:
JJTech0130 2023-09-16 13:03:59 -04:00
parent 2960b7c63c
commit 7396445afe
No known key found for this signature in database
GPG key ID: 23C92EBCCF8F93D6
5 changed files with 114 additions and 11 deletions

View file

@ -6,6 +6,7 @@ from subprocess import PIPE, Popen
from rich.logging import RichHandler
import apns
import ids.facetime
import ids
import imessage
@ -80,6 +81,7 @@ async def main():
CONFIG["id"] = {
"key": user._id_keypair.key,
"cert": user._id_keypair.cert,
"ft_cert": user._facetime_cert,
}
CONFIG["auth"] = {
"key": user._auth_keypair.key,
@ -96,6 +98,8 @@ async def main():
with open("config.json", "w") as f:
json.dump(CONFIG, f, indent=4)
await ids.facetime.provision_alias(user)
im = imessage.iMessageUser(conn, user)
# Send a message to myself

View file

@ -66,7 +66,7 @@ class IDSUser:
self.ec_key, self.rsa_key will be set to a randomly gnenerated EC and RSA keypair
if they are not already set
"""
cert = identity.register(
certs = identity.register(
b64encode(self.push_connection.credentials.token),
self.handles,
self.user_id,
@ -75,7 +75,8 @@ class IDSUser:
self.encryption_identity,
validation_data,
)
self._id_keypair = _helpers.KeyPair(self._auth_keypair.key, cert)
self._id_keypair = _helpers.KeyPair(self._auth_keypair.key, certs["com.apple.madrid"])
self._facetime_cert = certs["com.apple.private.alloy.facetime.multi"]
def restore_identity(self, id_keypair: _helpers.KeyPair):
self._id_keypair = id_keypair
@ -104,7 +105,8 @@ class IDSUser:
(rsa_key := encryption.get("rsa_key")) and
(signing_key := encryption.get("ec_key")) and
(cert := id.get("cert")) and
(key := id.get("key"))
(key := id.get("key")) and
(ft_cert := id.get("ft_cert"))
):
self.encryption_identity = identity.IDSIdentity(
encryption_key=rsa_key,
@ -113,6 +115,8 @@ class IDSUser:
id_keypair = _helpers.KeyPair(key, cert)
self.restore_identity(id_keypair)
self._facetime_cert = ft_cert
else:
logging.info("Registering new identity...")
import emulated.nac
@ -124,4 +128,3 @@ class IDSUser:
async def lookup(self, uris: list[str], topic: str = "com.apple.madrid") -> Any:
return await query.lookup(self.push_connection, self.current_handle, self._id_keypair, uris, topic)

62
ids/facetime.py Normal file
View file

@ -0,0 +1,62 @@
from ids import IDSUser
import logging
logger = logging.getLogger("ids")
import plistlib
from ids._helpers import PROTOCOL_VERSION, KeyPair, parse_key, serialize_key
from ids.signing import add_auth_signature, armour_cert, add_id_signature, add_push_signature
import requests
from base64 import b64decode, b64encode
async def provision_alias(user: IDSUser):
# <?xml version="1.0" encoding="UTF-8"?>
# <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
# <plist version="1.0">
# <dict>
# <key>attributes</key>
# <dict>
# <key>allowedServices</key>
# <dict>
# <key>com.apple.private.alloy.facetime.multi</key>
# <array/>
# </dict>
# <key>expiry-epoch-seconds</key>
# <real>1726418686.6028981</real>
# <key>featureId</key>
# <string>Gondola</string>
# </dict>
# <key>operation</key>
# <string>create</string>
# </dict>
import time
logger.debug(f"Adding new temp alias")
body = {
"attributes": {
"allowedServices": {
"com.apple.private.alloy.facetime.multi": []
},
# Unix timestamp in seconds, with decimal places, for 1 year from now
"expiry-epoch-seconds": time.time() + 31536000,
"featureId": "Gondola"
},
"operation": "create"
}
body = plistlib.dumps(body)
headers = {
"x-protocol-version": PROTOCOL_VERSION,
# "x-auth-user-id-0": user.user_id,
"x-id-self-uri": "mailto:testu3@icloud.com"
}
#add_auth_signature(headers, body, "id-register", user._auth_keypair, user._push_keypair, b64encode(user.push_connection.credentials.token), 0)
add_push_signature(headers, body, "id-provision-alias", user._push_keypair, b64encode(user.push_connection.credentials.token))
add_id_signature(headers, body, "id-provision-alias", user._id_keypair, b64encode(user.push_connection.credentials.token))
r = requests.post(
"https://identity.ess.apple.com/WebObjects/TDIdentityService.woa/wa/provisionAlias",
headers=headers,
data=body,
verify=False,
)
r = plistlib.loads(r.content)
print(r)

View file

@ -151,8 +151,29 @@ def register(
"user-id": user_id,
}
],
},
{
"capabilities": [{"flags": 1, "name": "Invitation", "version": 1}],
"service": "com.apple.private.alloy.facetime.multi",
"sub-services": [],
"users": [
{
"client-data": {
"public-message-identity-key": identity.encode(),
"public-message-identity-version": 2,
"supports-avless": True,
"supports-co": True,
"supports-gft-calls": True,
"supports-gft-errors": True,
"supports-modern-gft": True,
"supports-self-one-to-one-invites": True,
},
"uris": uris,
"user-id": user_id,
}
],
},
],
"validation-data": b64decode(validation_data),
}
@ -185,4 +206,9 @@ def register(
if not "cert" in r["services"][0]["users"][0]:
raise Exception(f"No cert in response: {r}")
return armour_cert(r["services"][0]["users"][0]["cert"])
return {
"com.apple.madrid": armour_cert(r["services"][0]["users"][0]["cert"]),
"com.apple.private.alloy.facetime.multi": armour_cert(r["services"][1]["users"][0]["cert"])
}
#return armour_cert(r["services"][0]["users"][0]["cert"])

View file

@ -90,11 +90,7 @@ def add_auth_signature(
push_token: str,
auth_number=None,
):
push_sig, push_nonce = _sign_payload(push_key.key, bag_key, "", push_token, body)
headers["x-push-sig"] = push_sig
headers["x-push-nonce"] = b64encode(push_nonce)
headers["x-push-cert"] = dearmour(push_key.cert)
headers["x-push-token"] = push_token
add_push_signature(headers, body, bag_key, push_key, push_token)
auth_sig, auth_nonce = _sign_payload(auth_key.key, bag_key, "", push_token, body)
auth_postfix = "-" + str(auth_number) if auth_number is not None else ""
@ -102,6 +98,18 @@ def add_auth_signature(
headers["x-auth-nonce" + auth_postfix] = b64encode(auth_nonce)
headers["x-auth-cert" + auth_postfix] = dearmour(auth_key.cert)
def add_push_signature(
headers: dict,
body: bytes,
bag_key: str,
push_key: KeyPair,
push_token: str
):
push_sig, push_nonce = _sign_payload(push_key.key, bag_key, "", push_token, body)
headers["x-push-sig"] = push_sig
headers["x-push-nonce"] = b64encode(push_nonce)
headers["x-push-cert"] = dearmour(push_key.cert)
headers["x-push-token"] = push_token
def add_id_signature(
headers: dict,