New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TEST: New device registration method #106
Labels
Comments
import base64
import gzip
import hashlib
import hmac
import json
import secrets
import uuid
from datetime import datetime
from io import BytesIO
from typing import Union
import httpx
from pyaes import AESModeOfOperationCBC, Encrypter, Decrypter
USER_AGENT = "AmazonWebView/GoodreadsForIOS App/4.0.1/iOS/15.4.1/iPhone"
class FrcCookieCipher:
FRC_SIG_SALT: bytes = b"HmacSHA256"
FRC_AES_SALT: bytes = b"AES/CBC/PKCS7Padding"
SIGNATURE_LENGTH: int = 8
def __init__(self, password: Union[str, bytes]) -> None:
if isinstance(password, str):
password = password.encode()
self.aes_key = self._get_key(password, self.FRC_AES_SALT)
self.sig_key = self._get_key(password, self.FRC_SIG_SALT)
def _get_key(self, password, salt: bytes) -> bytes:
return hashlib.pbkdf2_hmac("sha1", password, salt, 1000, 16)
def encrypt(self, plaintext: Union[str, bytes, dict]) -> str:
if isinstance(plaintext, dict):
plaintext = json.dumps(plaintext)
if isinstance(plaintext, str):
plaintext = plaintext.encode()
compressed = gzip.compress(plaintext)
iv = secrets.token_bytes(16)
cipher = Encrypter(AESModeOfOperationCBC(self.aes_key, iv))
ciphertext = cipher.feed(compressed) + cipher.feed()
signature = hmac.new(self.sig_key, iv + ciphertext, hashlib.sha256).digest()
return base64.b64encode(
b"\0" + signature[:self.SIGNATURE_LENGTH] + iv + ciphertext
).decode()
def decrypt(self, frc: str, verify_signature: bool = True) -> Union[dict, bytes]:
pad = (4 - len(frc) % 4) * "="
frc = BytesIO(base64.b64decode(frc + pad))
frc.seek(1) # the first byte is always 0, skip them
signature = frc.read(self.SIGNATURE_LENGTH)
iv = frc.read(16)
ciphertext = frc.read()
if verify_signature:
assert self._verify_signature(signature, iv, ciphertext) is True, "Signature missmatch"
decipher = Decrypter(AESModeOfOperationCBC(self.aes_key, iv))
plaintext = decipher.feed(ciphertext) + decipher.feed()
decompressed = gzip.decompress(plaintext)
try:
return json.loads(decompressed)
except json.JSONDecodeError:
return decompressed
def _verify_signature(self, signature, iv, ciphertext) -> bool:
new_signature = hmac.new(self.sig_key, iv + ciphertext, hashlib.sha256).digest()
return signature == new_signature[:self.SIGNATURE_LENGTH]
def register(username, password, domain):
url = f"https://api.amazon.{domain}/auth/register"
device_serial = secrets.token_hex(16).upper()
frc = {
'ApplicationVersion': '3.56.2',
'DeviceOSVersion': 'iOS/15.5',
'ScreenWidthPixels': '428',
'TimeZone': '+01:00',
'ScreenHeightPixels': '926',
'ApplicationName': 'Audible',
'DeviceJailbroken': False,
'DeviceLanguage': 'de-DE',
'DeviceFingerprintTimestamp': round(datetime.utcnow().timestamp()) * 1000,
'ThirdPartyDeviceId': str(uuid.uuid4()).upper(),
'DeviceName': 'iPhone',
'Carrier': 'Vodafone.de'
}
frc = FrcCookieCipher(device_serial).encrypt(frc)
headers = {
"x-amzn-identity-auth-domain": f"api.amazon.{domain}",
"User-Agent": USER_AGENT,
"Accept-Encoding": "gzip",
"Accept": "application/json",
"Accept-Language": "en-DE",
"Accept-Charset": "utf-8"
}
json_body = {
"requested_extensions": [
"device_info",
"customer_info"
],
"cookies": {
"website_cookies": [],
"domain": ".amazon.de"
},
"registration_data": {
"domain": "Device",
"app_version": "3.56.2",
"device_serial": device_serial,
"device_type": "A2CZJZGLK2JJVM",
"device_name": (
"%FIRST_NAME%%FIRST_NAME_POSSESSIVE_STRING%%DUPE_"
"STRATEGY_1ST%Audible for iPhone"
),
"os_version": "15.5.0",
"software_version": "35602678",
"device_model": "iPhone",
"app_name": "Audible"
},
"auth_data": {
"use_global_authentication": "false",
"user_id_password": {
"user_id": username,
"password": password
}
},
"user_context_map": {
"frc": frc
},
"requested_token_type": [
"bearer",
"mac_dms",
"website_cookies"
]
}
r = httpx.post(url, headers=headers, json=json_body)
return r
if __name__ == "__main__":
username = "" # FILL OUT
password = "" # FILL OUT
domain = "de" # FILL OUT
current_otp = "" # FILL OUT IF 2FA is activated
password += current_otp
r = register(username, password, domain)
print(r)
print(r.headers)
print(r.cookies)
print(r.json()) |
I've found out myself, how to handle a challenge response from the server (like an OTPCode) when using the code above. But this step needs further user inputs equal to my implemented code. So I think I will don’t switch to this registration method. |
This issue has not been updated for a while and will be closed soon. |
This issue has automatically been closed due to no activities. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Need help from users for another method to register a new Audible dummy device!
Please tell me if the code below let you register a new device or if you get any error message!
The text was updated successfully, but these errors were encountered: