Skip to content

Commit

Permalink
Merge pull request #1 from ssuchanowski/new-apple-auth
Browse files Browse the repository at this point in the history
Update base.py
  • Loading branch information
ssuchanowski authored Nov 6, 2024
2 parents 622cd16 + 18987a4 commit 8db2771
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 17 deletions.
80 changes: 63 additions & 17 deletions pyicloud/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
from re import match
import http.cookiejar as cookielib
import getpass
import srp
import base64
import hashlib

from pyicloud.exceptions import (
PyiCloudFailedLoginException,
Expand Down Expand Up @@ -212,15 +215,7 @@ def __init__(
verify=True,
client_id=None,
with_family=True,
china_mainland=False,
):
# If the country or region setting of your Apple ID is China mainland.
# See https://support.apple.com/en-us/HT208351
if china_mainland:
self.AUTH_ENDPOINT = "https://idmsa.apple.com.cn/appleauth/auth"
self.HOME_ENDPOINT = "https://www.icloud.com.cn"
self.SETUP_ENDPOINT = "https://setup.icloud.com.cn/setup/ws/1"

if password is None:
password = get_password_from_keyring(apple_id)

Expand Down Expand Up @@ -314,13 +309,6 @@ def authenticate(self, force_refresh=False, service=None):
if not login_successful:
LOGGER.debug("Authenticating as %s", self.user["accountName"])

data = dict(self.user)

data["rememberMe"] = True
data["trustTokens"] = []
if self.session_data.get("trust_token"):
data["trustTokens"] = [self.session_data.get("trust_token")]

headers = self._get_auth_headers()

if self.session_data.get("scnt"):
Expand All @@ -329,9 +317,67 @@ def authenticate(self, force_refresh=False, service=None):
if self.session_data.get("session_id"):
headers["X-Apple-ID-Session-Id"] = self.session_data.get("session_id")

class SrpPassword():
def __init__(self, password: str):
self.password = password

def set_encrypt_info(self, salt: bytes, iterations: int, key_length: int):
self.salt = salt
self.iterations = iterations
self.key_length = key_length

def encode(self):
password_hash = hashlib.sha256(self.password.encode('utf-8')).digest()
return hashlib.pbkdf2_hmac('sha256', password_hash, salt, iterations, key_length)

srp_password = SrpPassword(self.user["password"])
srp.rfc5054_enable()
srp.no_username_in_x()
usr = srp.User(self.user["accountName"], srp_password, hash_alg=srp.SHA256, ng_type=srp.NG_2048)

uname, A = usr.start_authentication()

data = {
'a': base64.b64encode(A).decode(),
'accountName': uname,
'protocols': ['s2k', 's2k_fo']
}

try:
response = self.session.post("%s/signin/init" % self.AUTH_ENDPOINT, data=json.dumps(data),
headers=headers)
response.raise_for_status()
except PyiCloudAPIResponseException as error:
msg = "Failed to initiate srp authentication."
raise PyiCloudFailedLoginException(msg, error) from error

body = response.json()

salt = base64.b64decode(body['salt'])
b = base64.b64decode(body['b'])
c = body['c']
iterations = body['iteration']
key_length = 32
srp_password.set_encrypt_info(salt, iterations, key_length)

m1 = usr.process_challenge(salt, b)
m2 = usr.H_AMK

data = {
"accountName": uname,
"c": c,
"m1": base64.b64encode(m1).decode(),
"m2": base64.b64encode(m2).decode(),
"rememberMe": True,
"trustTokens": [],
}

if self.session_data.get("trust_token"):
data["trustTokens"] = [self.session_data.get("trust_token")]

try:
self.session.post(
"%s/signin" % self.AUTH_ENDPOINT,
"%s/signin/complete" % self.AUTH_ENDPOINT,
params={"isRememberMeEnabled": "true"},
data=json.dumps(data),
headers=headers,
Expand Down Expand Up @@ -395,7 +441,7 @@ def _validate_token(self):

def _get_auth_headers(self, overrides=None):
headers = {
"Accept": "*/*",
"Accept": "application/json, text/javascript",
"Content-Type": "application/json",
"X-Apple-OAuth-Client-Id": "d39ba9916b7251055b22c7f910e2ea796ee65e98b2ddecea8f5dde8d9d1a815d",
"X-Apple-OAuth-Client-Type": "firstPartyAuth",
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ keyrings.alt>=3.5.2
click>=7.1.2
tzlocal>=4.0
certifi>=2020.6.20
srp=1.0.22

0 comments on commit 8db2771

Please sign in to comment.