mirror of
https://github.com/Sneed-Group/pypush-plus-plus
synced 2024-12-23 19:32:29 -06:00
basic sms registration get auth cert
This commit is contained in:
parent
5d7fab9cdd
commit
d5faef2cbc
2 changed files with 102 additions and 9 deletions
|
@ -86,14 +86,15 @@ def get_auth_token(
|
|||
logger.debug(f"Got auth token for IDS: {auth_token}")
|
||||
return realm_user_id, auth_token
|
||||
|
||||
from hashlib import sha1
|
||||
|
||||
def _generate_csr(private_key: rsa.RSAPrivateKey) -> str:
|
||||
def _generate_csr(private_key: rsa.RSAPrivateKey, user_id: str) -> str:
|
||||
csr = (
|
||||
x509.CertificateSigningRequestBuilder()
|
||||
.subject_name(
|
||||
x509.Name(
|
||||
[
|
||||
x509.NameAttribute(NameOID.COMMON_NAME, random.randbytes(20).hex()),
|
||||
x509.NameAttribute(NameOID.COMMON_NAME, sha1(user_id.encode()).hexdigest()),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
@ -108,24 +109,21 @@ def _generate_csr(private_key: rsa.RSAPrivateKey) -> str:
|
|||
)
|
||||
|
||||
|
||||
# Gets an IDS auth cert for the given user id and auth token
|
||||
# Returns [private key PEM, certificate PEM]
|
||||
def get_auth_cert(user_id, token) -> KeyPair:
|
||||
BAG_KEY = "id-authenticate-ds-id"
|
||||
|
||||
def _authenticate_with_data(auth_data, endpoint_key, user_id) -> KeyPair:
|
||||
private_key = rsa.generate_private_key(
|
||||
public_exponent=65537, key_size=2048, backend=default_backend()
|
||||
)
|
||||
body = {
|
||||
"authentication-data": {"auth-token": token},
|
||||
"csr": b64decode(_generate_csr(private_key)),
|
||||
"authentication-data": auth_data,
|
||||
"csr": b64decode(_generate_csr(private_key, user_id)),
|
||||
"realm-user-id": user_id,
|
||||
}
|
||||
|
||||
body = plistlib.dumps(body)
|
||||
|
||||
r = requests.post(
|
||||
bags.ids_bag()[BAG_KEY],
|
||||
bags.ids_bag()[endpoint_key],
|
||||
#"https://profile.ess.apple.com/WebObjects/VCProfileService.woa/wa/authenticateDS",
|
||||
data=body,
|
||||
headers={"x-protocol-version": "1630"},
|
||||
|
@ -147,6 +145,16 @@ def get_auth_cert(user_id, token) -> KeyPair:
|
|||
cert.public_bytes(serialization.Encoding.PEM).decode("utf-8").strip(),
|
||||
)
|
||||
|
||||
def get_auth_cert(user_id: str, auth_token: str) -> KeyPair:
|
||||
return _authenticate_with_data({"auth-token": auth_token}, "id-authenticate-ds-id", user_id)
|
||||
|
||||
def get_phone_cert(phone_number: str, push_token: bytes, phone_signatures: list[bytes]) -> KeyPair:
|
||||
return _authenticate_with_data({"push-token": push_token,
|
||||
"sigs": phone_signatures},
|
||||
"id-authenticate-phone-number",
|
||||
"P:" + phone_number,
|
||||
)
|
||||
|
||||
|
||||
def get_handles(push_token, user_id: str, auth_key: KeyPair, push_key: KeyPair):
|
||||
BAG_KEY = "id-get-handles"
|
||||
|
|
85
sms_registration.py
Normal file
85
sms_registration.py
Normal file
|
@ -0,0 +1,85 @@
|
|||
import requests
|
||||
import random
|
||||
import apns
|
||||
import trio
|
||||
from base64 import b64decode, b64encode
|
||||
|
||||
import urllib3
|
||||
urllib3.disable_warnings()
|
||||
|
||||
PHONE_IP = "192.168.5.120"
|
||||
API_PORT = 8080
|
||||
|
||||
def register(push_token: bytes, gateway = "22223333") -> tuple[str, bytes]:
|
||||
"""Forwards a registration request to the phone and returns the phone number, signature for the provided push token"""
|
||||
token = push_token.hex().upper()
|
||||
req_id = random.randint(0, 2**32)
|
||||
sms = f"REG-REQ?v=3;t={token};r={req_id};"
|
||||
r = requests.get(f"http://{PHONE_IP}:{API_PORT}/register", params={"sms": sms, "gateway": gateway})
|
||||
|
||||
if r.text.split("?")[0] != "REG-RESP":
|
||||
raise Exception(f"Failed to register: {r.text}")
|
||||
#assert r.text.split("?")[0] == "REG-RESP"
|
||||
resp_params = r.text.split("?")[1]
|
||||
resp_params = resp_params.split(";")
|
||||
resp_params = {param.split("=")[0]: param.split("=")[1] for param in resp_params}
|
||||
assert resp_params["v"] == "3"
|
||||
assert resp_params["r"] == str(req_id)
|
||||
|
||||
signature = bytes.fromhex(resp_params["s"])
|
||||
|
||||
return resp_params["n"], signature
|
||||
|
||||
async def main():
|
||||
# Open test.json
|
||||
try:
|
||||
with open("test.json", "r") as f:
|
||||
test_json = f.read()
|
||||
import json
|
||||
test_json = json.loads(test_json)
|
||||
except FileNotFoundError:
|
||||
test_json = {}
|
||||
|
||||
creds = apns.PushCredentials(
|
||||
test_json.get("push_key", ""),
|
||||
test_json.get("push_cert", ""),
|
||||
b64decode(test_json["push_token"]) if "push_token" in test_json else b"",
|
||||
)
|
||||
|
||||
async with apns.APNSConnection.start(creds) as connection:
|
||||
connection.credentials
|
||||
#number, sig = register(connection.credentials.token)
|
||||
if "register_sig" not in test_json:
|
||||
try:
|
||||
number, sig = register(connection.credentials.token)
|
||||
test_json["register_sig"] = sig.hex()
|
||||
test_json["number"] = number
|
||||
except Exception as e:
|
||||
print(e)
|
||||
sig = None
|
||||
number = None
|
||||
else:
|
||||
sig = bytes.fromhex(test_json["register_sig"])
|
||||
number = test_json["number"]
|
||||
if sig is not None and number is not None:
|
||||
from ids import profile
|
||||
phone_auth_keypair = profile.get_phone_cert(number, connection.credentials.token, [sig])
|
||||
test_json["auth_key"] = phone_auth_keypair.key
|
||||
test_json["auth_cert"] = phone_auth_keypair.cert
|
||||
|
||||
out_json = {
|
||||
"push_key": creds.private_key,
|
||||
"push_cert": creds.cert,
|
||||
"push_token": b64encode(creds.token).decode("utf-8"),
|
||||
}
|
||||
test_json.update(out_json)
|
||||
|
||||
with open("test.json", "w") as f:
|
||||
import json
|
||||
f.write(json.dumps(test_json, indent=4))
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
trio.run(main)
|
Loading…
Reference in a new issue