Skip to content

Instantly share code, notes, and snippets.

@LeoDJ
Created April 15, 2025 22:52
Show Gist options
  • Save LeoDJ/4a5405873bcd0bd8863e08a6c53d5e2f to your computer and use it in GitHub Desktop.
Save LeoDJ/4a5405873bcd0bd8863e08a6c53d5e2f to your computer and use it in GitHub Desktop.
Some reverse engineering of the Carmin Android app backend
# pip3 install pycryptodome
# Encryption for the "http://carmin-backend.appspot.com/rs" URL paths
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
class CarminURLEncryptor:
def __init__(self):
# The SHA256 digest (from the Android app signature)
hex_digest = "27561785fbc8213f459a091e0c24c6d1e1eea5264500e660382b8eb5cf6141bd"
digest_bytes = bytes.fromhex(hex_digest)
# Base64 encode the digest, then use the first 16 characters as the key/IV
base64_digest = base64.b64encode(digest_bytes).decode()
key_iv = base64_digest[:16].encode()
self.key = key_iv
self.iv = key_iv
def encrypt(self, plaintext: str) -> str:
if not plaintext:
raise Exception("Empty string")
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
padded = pad(plaintext.encode(), AES.block_size)
encrypted = cipher.encrypt(padded)
# URL-safe Base64
encoded = base64.b64encode(encrypted).decode()
return encoded.replace('+', '-').replace('/', '_')
def decrypt(self, encoded_str: str) -> str:
if not encoded_str:
raise Exception("Empty string")
# URL-safe Base64
safe_str = encoded_str.replace('-', '+').replace('_', '/')
encrypted_bytes = base64.b64decode(safe_str)
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
decrypted = unpad(cipher.decrypt(encrypted_bytes), AES.block_size)
return decrypted.decode()
if __name__ == "__main__":
encryptor = CarminURLEncryptor()
ciphertext = encryptor.encrypt("4843060768800768") # uYuTMMCAFMCWF3v_Pa1pg-JIZC1gmN8trwkDiY97rQs=
print(ciphertext)
print(encryptor.decrypt("0mAo3kpeErHLTHAhiUH8Og==")) # com.min.car
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment