-
-
Save DavidePrincipi/e2007b998bb66ea69a1ff7832af6c417 to your computer and use it in GitHub Desktop.
| #!/usr/bin/env bash | |
| # castanet.sh: Script to connect a chromecast to a WiFi network. | |
| # | |
| # Allows you to put your Chromecast on WiFi and do Chromecast initial setup | |
| # without using the Google Home app at all, just using a normal Linux computer. | |
| # | |
| # You do need your Chromecast to be on Ethernet, or (untested) to join its setup WiFi | |
| # network with your PC, and you also need to find out its IP yourself with e.g. | |
| # Wireshark. | |
| set -e | |
| if [[ -z "${CHROMECAST_IP}" || -z "${WIFI_SSID}" || -z "${WIFI_PASSWORD}" ]] ; then | |
| echo 1>&2 "Usage: CHROMECAST_IP=\"XXX\" WIFI_SSID=\"XXX\" WIFI_PASSWORD=\"XXX\" ${0}" | |
| exit 1 | |
| fi | |
| if ! which curl >/dev/null 2>/dev/null ; then | |
| echo 1>&2 "Install curl to use this script!" | |
| exit 1 | |
| fi | |
| if ! which jq >/dev/null 2>/dev/null ; then | |
| echo 1>&2 "Install jq to use this script!" | |
| exit 1 | |
| fi | |
| # Set VERBOSITY=-vvv to see Curl traffic happening | |
| if [[ -z "${VERBOSITY}" ]] ; then | |
| VERBOSITY=-s | |
| fi | |
| echo "Connecting ${CHROMECAST_IP} to ${WIFI_SSID} with password ${WIFI_PASSWORD}" | |
| # Get the device's public key | |
| INFO_JSON="$(curl ${VERBOSITY} --insecure --tlsv1.2 --tls-max 1.2 https://${CHROMECAST_IP}:8443/setup/eureka_info)" | |
| CHROMECAST_PUBKEY="$(echo "${INFO_JSON}" | jq -r '.public_key')" | |
| # Scan for and find the network we want to get the encryption parameters | |
| curl ${VERBOSITY} --insecure --tlsv1.2 --tls-max 1.2 -X POST https://${CHROMECAST_IP}:8443/setup/scan_wifi | |
| sleep 20 | |
| WIFI_JSON="$(curl ${VERBOSITY} --insecure --tlsv1.2 --tls-max 1.2 https://${CHROMECAST_IP}:8443/setup/scan_results)" | |
| WIFI_NETWORK_JSON="$(echo "${WIFI_JSON}" | jq ".[] | select(.ssid == \"${WIFI_SSID}\")")" | |
| WIFI_AUTH_NUMBER="$(echo "${WIFI_NETWORK_JSON}" | jq -r '.wpa_auth')" | |
| WIFI_CIPHER_NUMBER="$(echo "${WIFI_NETWORK_JSON}" | jq -r '.wpa_cipher')" | |
| echo "${WIFI_NETWORK_JSON}" | |
| # Encrypt the password to the device | |
| # Encryption kernel by @thorleifjaocbsen | |
| # See <https://github.com/rithvikvibhu/GHLocalApi/issues/68#issue-766300901> | |
| # Using OpenSSL instead of Node.js | |
| # Ensure public key is in a proper format | |
| PUBKEY_FILE="/tmp/chromecast_pubkey.pem" | |
| echo "-----BEGIN RSA PUBLIC KEY----- | |
| ${CHROMECAST_PUBKEY} | |
| -----END RSA PUBLIC KEY-----" > "$PUBKEY_FILE" | |
| # Encrypt the password | |
| ENCRYPTED_KEY=$(echo -n "$WIFI_PASSWORD" | openssl rsautl -encrypt -pubin -inkey "$PUBKEY_FILE" -pkcs | base64 -w 0) | |
| # Cleanup | |
| rm -f "$PUBKEY_FILE" | |
| # Generate the command to connect. | |
| CONNECT_COMMAND="{\"ssid\": \"${WIFI_SSID}\", \"wpa_auth\": ${WIFI_AUTH_NUMBER}, \"wpa_cipher\": ${WIFI_CIPHER_NUMBER}, \"enc_passwd\": \"${ENCRYPTED_KEY}\"}" | |
| # And the command to save the connection. | |
| # Include keep_hotspot_until_connected in case we are on the Chromecast's setup hotspot and not Ethernet. | |
| # See <https://github.com/rithvikvibhu/GHLocalApi/issues/88#issuecomment-860538447> | |
| SAVE_COMMAND="{\"keep_hotspot_until_connected\": true}" | |
| # Send the commands | |
| curl ${VERBOSITY} --insecure --tlsv1.2 --tls-max 1.2 -H "content-type: application/json" -d "${CONNECT_COMMAND}" https://${CHROMECAST_IP}:8443/setup/connect_wifi | |
| # Hope this one gets there before it can actually disconnect if we're using the setup hotspot? | |
| # Otherwise we have to use Ethernet or jump over to the target network and find the device again. | |
| # See <http://blog.brokennetwork.ca/2019/05/setting-up-google-chromecast-without.html?m=1> for a script that knows how to swap wifi networks but needs to be ported to use the current API. | |
| curl ${VERBOSITY} --insecure --tlsv1.2 --tls-max 1.2 -H "content-type: application/json" -d "${SAVE_COMMAND}" https://${CHROMECAST_IP}:8443/setup/save_wifi | |
| # To see it working, if you aren't kicked off the hotspot (or if you set the new CHROMECAST_IP in your shell): | |
| # | |
| # curl --insecure --tlsv1.2 --tls-max 1.2 https://${CHROMECAST_IP}:8443/setup/eureka_info | jq . | |
| # | |
| # To list known networks: | |
| # | |
| # curl --insecure --tlsv1.2 --tls-max 1.2 https://${CHROMECAST_IP}:8443/setup/configured_networks | jq . | |
| # | |
| # To forget a newtwork: | |
| # | |
| # curl --insecure --tlsv1.2 --tls-max 1.2 -H "content-type: application/json" -d '{"wpa_id": 0}' https://${CHROMECAST_IP}:8443/setup/forget_wifi | |
| # | |
| # If you leave Ethernet plugged in, the Chromecast will ARP for its WiFi IP on | |
| # Etherenet and drop the WiFi connection! Unplug the Chromecast, and plug it in | |
| # again with no Ethernet, to get it to keep the WiFi connection up! | |
| # | |
| # Set Name and opt out of things: | |
| # | |
| # curl --insecure --tlsv1.2 --tls-max 1.2 -H "content-type: application/json" -d '{"name": "NovakCast5000", "opt_in": {"crash": false, "stats": false, "opencast": false}}' https://${CHROMECAST_IP}:8443/setup/set_eureka_info |
Even though most distros will already have openssl installed by default, it might be a good idea to add an openssl package check as well, just to be safe.
if ! which openssl >/dev/null 2>/dev/null ; then
echo 1>&2 "Install openssl to use this script!"
exit 1
fi
Also, the script will throw The command rsautl was deprecated in version 3.0. Use 'pkeyutl' instead in it's current iteration. Change the rsautl command to pkeyutl to fix the problem for the future.
sed -i 's|openssl rsautl -encrypt -pubin -inkey "$PUBKEY_FILE" -pkcs|openssl pkeyutl -encrypt -pubin -inkey "$PUBKEY_FILE" -pkeyopt rsa_padding_mode:pkcs1|g' castanet.sh
β For those interested in using the script on Android or other Linux distros, I've created a bit of a guide here if you want to take that path to set up your Chromecast. π
@DavidePrincipi just wanted to say thank you!
Your script saved my 1st generation Chromecast (2013).
After upgrading my router, I factory reset the Chromecast and Google Home on Android could no longer detect it. I thought I had bricked it and was about to throw it away.
Using your script on my MacBook (with the small base64 adjustment for macOS), I was able to reconnect it to my Wi-Fi and bring it back to life.
It's amazing that a few lines of code shared by strangers on the Internet can keep perfectly good hardware out of the trash.
Thank you very much from Spain! πͺπΈ
Same here, just resurrected a 2015 Chromecast that Google Home would not find. I connected to the Chromecast wifi and ran the script - worked in the first try. The IP you need will show as the "default gateway" when you connect to Chromecast wifi and get an IP from DHCP.
Thank you!