get_encryption_key.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #!/usr/bin/env python3
  2. import base64
  3. import getpass
  4. import hashlib
  5. import hmac
  6. import json
  7. import sys
  8. import boto3
  9. import requests
  10. # Those values have been obtained from the following files in SwitchBot Android app
  11. # That's how you can verify them yourself
  12. # /assets/switchbot_config.json
  13. # /res/raw/amplifyconfiguration.json
  14. # /res/raw/awsconfiguration.json
  15. SWITCHBOT_INTERNAL_API_BASE_URL = (
  16. "https://l9ren7efdj.execute-api.us-east-1.amazonaws.com"
  17. )
  18. SWITCHBOT_COGNITO_POOL = {
  19. "PoolId": "us-east-1_x1fixo5LC",
  20. "AppClientId": "66r90hdllaj4nnlne4qna0muls",
  21. "AppClientSecret": "1v3v7vfjsiggiupkeuqvsovg084e3msbefpj9rgh611u30uug6t8",
  22. "Region": "us-east-1",
  23. }
  24. def main():
  25. if len(sys.argv) < 3:
  26. print(f"Usage: {sys.argv[0]} <device_mac> <username> [<password>]")
  27. exit(1)
  28. device_mac = sys.argv[1].replace(":", "").replace("-", "").upper()
  29. username = sys.argv[2]
  30. if len(sys.argv) == 3:
  31. password = getpass.getpass()
  32. else:
  33. password = sys.argv[3]
  34. msg = bytes(username + SWITCHBOT_COGNITO_POOL["AppClientId"], "utf-8")
  35. secret_hash = base64.b64encode(
  36. hmac.new(
  37. SWITCHBOT_COGNITO_POOL["AppClientSecret"].encode(),
  38. msg,
  39. digestmod=hashlib.sha256,
  40. ).digest()
  41. ).decode()
  42. cognito_idp_client = boto3.client(
  43. "cognito-idp", region_name=SWITCHBOT_COGNITO_POOL["Region"]
  44. )
  45. auth_response = None
  46. try:
  47. auth_response = cognito_idp_client.initiate_auth(
  48. ClientId=SWITCHBOT_COGNITO_POOL["AppClientId"],
  49. AuthFlow="USER_PASSWORD_AUTH",
  50. AuthParameters={
  51. "USERNAME": username,
  52. "PASSWORD": password,
  53. "SECRET_HASH": secret_hash,
  54. },
  55. )
  56. except cognito_idp_client.exceptions.NotAuthorizedException as e:
  57. print(f"Error: Failed to authenticate - {e}")
  58. exit(1)
  59. except BaseException as e:
  60. print(f"Error: Unexpected error during authentication - {e}")
  61. exit(1)
  62. if (
  63. auth_response is None
  64. or "AuthenticationResult" not in auth_response
  65. or "AccessToken" not in auth_response["AuthenticationResult"]
  66. ):
  67. print(f"Error: unexpected authentication result")
  68. exit(1)
  69. access_token = auth_response["AuthenticationResult"]["AccessToken"]
  70. key_response = requests.post(
  71. url=SWITCHBOT_INTERNAL_API_BASE_URL + "/developStage/keys/v1/communicate",
  72. headers={"authorization": access_token},
  73. json={"device_mac": device_mac, "keyType": "user"},
  74. )
  75. key_response_content = json.loads(key_response.content)
  76. if key_response_content["statusCode"] != 100:
  77. print(
  78. "Error: {} ({})".format(
  79. key_response_content["message"], key_response_content["statusCode"]
  80. )
  81. )
  82. exit(1)
  83. print("Key ID: " + key_response_content["body"]["communicationKey"]["keyId"])
  84. print("Encryption key: " + key_response_content["body"]["communicationKey"]["key"])
  85. if __name__ == "__main__":
  86. main()