more changes, including ability to look up facetime keys

This commit is contained in:
JJTech0130 2023-05-02 16:36:50 -04:00
parent ff20a7cb49
commit d8fc26bcb2
No known key found for this signature in database
GPG key ID: 23C92EBCCF8F93D6
2 changed files with 41 additions and 31 deletions

44
demo.py
View file

@ -46,7 +46,7 @@ def refresh_cert():
def create_connection(): def create_connection():
conn = apns.APNSConnection() conn = apns.APNSConnection()
token = conn.connect() token = conn.connect()
conn.filter(['com.apple.madrid']) #conn.filter(['com.apple.madrid'])
CONFIG['push'] = { CONFIG['push'] = {
'token': b64encode(token).decode(), 'token': b64encode(token).decode(),
'cert': conn.cert, 'cert': conn.cert,
@ -57,10 +57,10 @@ def create_connection():
def restore_connection(): def restore_connection():
conn = apns.APNSConnection(CONFIG['push']['key'], CONFIG['push']['cert']) conn = apns.APNSConnection(CONFIG['push']['key'], CONFIG['push']['cert'])
conn.connect(True, b64decode(CONFIG['push']['token'])) conn.connect(True, b64decode(CONFIG['push']['token']))
conn.filter(['com.apple.madrid']) #conn.filter(['com.apple.madrid', 'com.apple.private.alloy.facetime.multi'])
return conn return conn
def refresh_madrid_cert(): def refresh_ids_cert():
info = { info = {
"uri": "mailto:" + CONFIG["username"], "uri": "mailto:" + CONFIG["username"],
"user_id": CONFIG['user_id'], "user_id": CONFIG['user_id'],
@ -102,38 +102,44 @@ def refresh_madrid_cert():
) )
CONFIG["validation_data"] = validation_data CONFIG["validation_data"] = validation_data
madrid_cert = x509.load_der_x509_certificate( ids_cert = x509.load_der_x509_certificate(
resp["services"][0]["users"][0]["cert"] resp["services"][0]["users"][0]["cert"]
) )
madrid_cert = ( ids_cert = (
madrid_cert.public_bytes(serialization.Encoding.PEM).decode("utf-8").strip() ids_cert.public_bytes(serialization.Encoding.PEM).decode("utf-8").strip()
) )
CONFIG["madrid_cert"] = madrid_cert CONFIG["ids_cert"] = ids_cert
if not 'push' in CONFIG: if not 'push' in CONFIG:
print("No push conn") print("No existing APNs credentials, creating new ones...")
#print("No push conn")
conn = create_connection() conn = create_connection()
else: else:
print("restoring push conn") print("Restoring APNs credentials...")
conn = restore_connection() conn = restore_connection()
print("Connected to APNs!")
if not 'madrid_cert' in CONFIG: if not 'ids_cert' in CONFIG:
print("No madrid cert") print("No existing IDS certificate, creating new one...")
if not 'key' in CONFIG: if not 'key' in CONFIG:
print("No auth cert") print("No existing authentication certificate, creating new one...")
if not 'token' in CONFIG: if not 'token' in CONFIG:
print("No auth token") print("No existing authentication token, creating new one...")
refresh_token() refresh_token()
print("Got authentication token!")
refresh_cert() refresh_cert()
refresh_madrid_cert() print("Got authentication certificate!")
print("Got new madrid cert") refresh_ids_cert()
print("Doing lookup") print("Got IDS certificate!")
print(ids.lookup(conn, ['mailto:jjtech@jjtech.dev'], (CONFIG['key'], CONFIG['madrid_cert']), CONFIG['username']))
# This is the actual lookup!
print("Done") print("Looking up user...")
ids_keypair = ids.KeyPair(CONFIG['key'], CONFIG['ids_cert'])
resp = ids.lookup(conn, CONFIG['username'], ids_keypair, 'com.apple.madrid', ['mailto:textgpt@icloud.com'])
print("Got response!")
print(resp)
# Save config # Save config
with open("config.json", "w") as f: with open("config.json", "w") as f:

28
ids.py
View file

@ -11,17 +11,15 @@ from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding, rsa from cryptography.hazmat.primitives.asymmetric import padding, rsa
from cryptography.x509.oid import NameOID from cryptography.x509.oid import NameOID
from collections import namedtuple
import apns import apns
import bags import bags
import gsa import gsa
USER_AGENT = "com.apple.madrid-lookup [macOS,13.2.1,22D68,MacBookPro18,3]" USER_AGENT = "com.apple.madrid-lookup [macOS,13.2.1,22D68,MacBookPro18,3]"
# NOTE: The push token MUST be registered with the account for self-uri!
# This is an actual valid one for my account, since you can look it up anyway.
#PUSH_TOKEN = "5V7AY+ikHr4DiSfq1W2UBa71G3FLGkpUSKTrOLg81yk="
#SELF_URI = "mailto:jjtech@jjtech.dev"
KeyPair = namedtuple("KeyPair", ["key", "cert"])
# Nonce Format: # Nonce Format:
# 01000001876bd0a2c0e571093967fce3d7 # 01000001876bd0a2c0e571093967fce3d7
@ -80,17 +78,16 @@ def sign_payload(
# global_key, global_cert = load_keys() # global_key, global_cert = load_keys()
def _send_request(conn: apns.APNSConnection, bag_key: str, topic: str, body: bytes, keypair: KeyPair, username: str) -> bytes:
def _send_request(conn: apns.APNSConnection, bag_key: str, body: bytes, id_key: str, id_cert, username: str) -> bytes:
body = zlib.compress(body, wbits=16 + zlib.MAX_WBITS) body = zlib.compress(body, wbits=16 + zlib.MAX_WBITS)
push_token = b64encode(conn.token).decode() push_token = b64encode(conn.token).decode()
# Sign the request # Sign the request
signature, nonce = sign_payload(id_key, bag_key, "", push_token, body) signature, nonce = sign_payload(keypair.key, bag_key, "", push_token, body)
headers = { headers = {
"x-id-cert": id_cert.replace("-----BEGIN CERTIFICATE-----", "") "x-id-cert": keypair.cert.replace("-----BEGIN CERTIFICATE-----", "")
.replace("-----END CERTIFICATE-----", "") .replace("-----END CERTIFICATE-----", "")
.replace("\n", ""), .replace("\n", ""),
"x-id-nonce": b64encode(nonce).decode(), "x-id-nonce": b64encode(nonce).decode(),
@ -101,7 +98,7 @@ def _send_request(conn: apns.APNSConnection, bag_key: str, body: bytes, id_key:
"x-protocol-version": "1630", "x-protocol-version": "1630",
} }
print(headers) #print(headers)
req = { req = {
"cT": "application/x-apple-plist", "cT": "application/x-apple-plist",
@ -114,7 +111,7 @@ def _send_request(conn: apns.APNSConnection, bag_key: str, body: bytes, id_key:
"b": body, "b": body,
} }
conn.send_message("com.apple.madrid", plistlib.dumps(req, fmt=plistlib.FMT_BINARY)) conn.send_message(topic, plistlib.dumps(req, fmt=plistlib.FMT_BINARY))
resp = conn.wait_for_packet(0x0A) resp = conn.wait_for_packet(0x0A)
resp_body = apns._get_field(resp[1], 3) resp_body = apns._get_field(resp[1], 3)
@ -125,9 +122,16 @@ def _send_request(conn: apns.APNSConnection, bag_key: str, body: bytes, id_key:
return resp_body return resp_body
def lookup(conn: apns.APNSConnection, query: list[str], id_pair: tuple[str, str], self_user: str) -> any: # Performs an IDS lookup
# conn: an active APNs connection. must be connected and have a push token. will be filtered to the IDS topic
# self: the user's email address
# keypair: a KeyPair object containing the user's private key and certificate
# topic: the IDS topic to query
# query: a list of URIs to query
def lookup(conn: apns.APNSConnection, self: str, keypair: KeyPair, topic: str, query: list[str]) -> any:
conn.filter([topic])
query = {"uris": query} query = {"uris": query}
resp = _send_request(conn, "id-query", plistlib.dumps(query), id_pair[0], id_pair[1], self_user) resp = _send_request(conn, "id-query", topic, plistlib.dumps(query), keypair, self)
resp = plistlib.loads(resp) resp = plistlib.loads(resp)
resp = zlib.decompress(resp["b"], 16 + zlib.MAX_WBITS) resp = zlib.decompress(resp["b"], 16 + zlib.MAX_WBITS)
resp = plistlib.loads(resp) resp = plistlib.loads(resp)