Skip to content

Fossil server pairing

Unfortunately the gadget is pretty locked down and it is necessary to use the vendor (official) app at least once. This has two reasons:

  1. The gadget seems to come with a demo firmware that is not functional and needs to be updated once. This can only be done with the official vendor's app.
  2. There is a secret per-gadget key that gets negotiated with the Fossil servers. This process seems to be cryptographically secure, unfortunately.

Usage of non-free (as-in freedom) software ahead

Unfortunately, these steps will take you outside of Gadgetbridge and require you to create an account in the official proprietary Fossil or Skagen app.

As the authentication keys are stored on Fossil's servers, there is no way to generate these keys locally at the moment.

You have to (later) make sure that the vendor app and Gadgetbridge do not collide with each other, perhaps have the vendor app installed on some other phone and keep the phone/Bluetooth off.

We currently know of several methods to authenticate the watch against the vendor's servers and retrieve the auth key. They are outlined below, in increasing complexity.

Don't unpair from vendor app

Anytime you unpair your gadget from the Fossil or Skagen app the pairing key will be invalidated and you must follow these steps again to generate a new key and obtain it. Just uninstall the vendor app instead.

Factory resetting the gadget invalidates the key

Every time you restore the factory settings on the gadget, the pairing key will be invalidated and you must follow these steps again to generate a new key and obtain it.

HTTPS certificate expired on Fossil servers

Fossil has apparently stopped maintaining the auth servers, causing the HTTPS certificate to expire without renewal. For this reason, make sure to use the latest version of one of the methods below, as previous versions didn't account for this problem.

Apart from being an inconvenience, this is also insecure. Please understand that regular HTTPS assurances don't apply anymore and any connection between you and the Fossil servers could be eavesdropped without you knowing.

Using FossilHRAuthenticator

  • Fetch the secret key from the official servers. This allows the same key to be used in Gadgetbridge and in the vendor app.
  • Create a shared secret for Fossil HR watches and more - this app allows authenticating against all endpoints that support the same protocol. Use the values displayed in the README for retrieving the key from the Fossil servers.

See WatchAuthenticator

When you obtained the authentication key you can enter it in Gadgetbridge.

Entering key

Using a Python script

#!/usr/bin/env python3
import requests
import sys
import json
import base64

def die(s, r):
    print(s, file=sys.stderr)
    print(r.text, file=sys.stderr)
    sys.exit(1)

if len(sys.argv) != 3:
    print("Usage: %s username password" % (sys.argv[0]), file=sys.stderr)
    exit(1)

email = sys.argv[1]
password = sys.argv[2]
base_url = 'https://c.fossil.com/v2.1'  # use for fossil watches
#base_url = 'https://api.skagen.linkplatforms.com/v2.1'  # use for skagen watches
auth_url = base_url + '/rpc/auth/login'
keys_url = base_url + '/users/me/device-secret-keys'

# add in the email and password
auth_fields = {
    "email": email,
    "password": password,
    "clientId": "xxx",
}
# try to fetch the auth URL with this username / password
r = requests.post(auth_url, json=auth_fields, verify=False)
if r.status_code != 200:
    die("wrong username/password?", r)

token = json.loads(r.text).get("accessToken")
if not token:
    die("no access token in results?", r)

# now we can fetch the device keys using the bearer token
r = requests.get(keys_url, verify=False, headers={
    "Authorization": "Bearer " + token,
})
if r.status_code != 200:
    die("access token not valid?", r)

devices = json.loads(r.text).get("_items")
if not devices:
    die("no devices in response?", r)

for dev in devices:
    devid = dev.get("id")
    key = dev.get("secretKey")
    if not key:
        die(devid + ": no secret key?", r)
    # only output the first 16 bytes of the secret key
    print(devid, base64.b64decode(key).hex()[0:32])

When you obtained the authentication key you can enter it in Gadgetbridge.

Entering key

Using a patched vendor app

There is a patched official app which will reveal the key. This will downgrade the watch firmware though, so after retrieving the auth key with the patched app, you will need to install the latest official app from the Play Store again to upgrade the watch to the latest firmware and watch apps. This will not change the auth key.

Warning

The Gen 6 hybrids didn't exist yet when the last version of the patched app was released, so this method won't work for gen 6 watches.

See this Reddit post for steps.

When you obtained the authentication key you can enter it in Gadgetbridge.

Entering key

Using root shell to read from app cache

Skagen

Needs independent verification

This method needs independent verification, at the time of writing only the author did it.

You need a rooted phone for this method.

  • Start with a clean slate, i.e. the official app must not be paired with your watch yet.
  • Pair the watch as usual.
  • Search for secret in the apps internal cache directory, e.g. for the Skagen app that is /data/data/com.skagen.connected/cache. There are many ways to do that, I used ADB and the command grep -rIi secret ., you can do the same with Termux or just copy that directory to your computer and search the directory with your favorite tools. I found the following (truncating some potential PI):
./cacheResponse/c4280c8aa94ab69d6fa8a9521d3dccc5.0:https://api.skagen.linkplatforms.com/v2/users/me/devices/D0S00212GU/secret-key
./cacheResponse/c4280c8aa94ab69d6fa8a9521d3dccc5.1:{"id":"...","uid":"...","secretKey":"DIcI3xns...d4K4mOh0=","createdAt":"2022-05-24T18:53:29.624Z","updatedAt":"2022-05-24T20:06:09.736Z","_links":{"self":"/v2/users/me/devices/.../..."},"_etag":"...","_isNew":false}

What we are interested in is the secretKey value.

  • Convert the key to be used in Gadgetbridge, see instructions below for mitmproxy (command includes hexdump).

Fossil

Needs independent verification

This method needs independent verification, at the time of writing only the author did it.

You need a rooted phone for this method.

  • Start with a clean slate, i.e. the official app must not be paired with your watch yet.
  • Pair the watch as usual.
  • Search for secret in the Fossil app directory (/data/data/com.fossil.wearables.fossil). There are many ways to do that, I used ADB and the command grep -R secret ., you can do the same with Termux or just copy that directory to your computer and search the directory with your favorite tools. I found the following (truncating some potential PI):
$ grep -R secret .
Binary file ./app_flutter/_network_cache_3/normal/... matches
Binary file ./app_flutter/_network_cache_3/normal/... matches
Binary file ./app_flutter/_network_cache_3/normal/... matches
Binary file ./app_flutter/_network_cache_3/normal/... matches
Binary file ./app_flutter/_network_cache_3/normal/... matches

$ cat ./app_flutter/_network_cache_3/normal/...         # one of any of the previous files
{"_etag":"556334f6a25526c367a58cf6b1f0a882","_items":[{"id":"...","uid":"...","secretKey":"...","createdAt":"...","updatedAt":"...","_links":{"self":"/v3/users/me/device-secret-keys/..."},"_etag":"...","_isNew":false}],"_range":{"limit":20,"offset":0,"hasNext":false},"_links":{}} [...]

What we are interested in is the secretKey value.

  • Convert the key to be used in Gadgetbridge, see instructions below for mitmproxy (command includes hexdump).

Using mitmproxy (sniffing decrypted https traffic)

Warning

This section is probably outdated and needs testing.

Requirements

To do it this way, you need the following:

  • A rooted Android device (if you can, use a junk device which is not your daily phone)
  • A PC running Linux on the same network
  • mitmproxy and knowledge of using of how to use it

The procedure is generally speaking (there should be detailed tutorials on using mitmproxy elsewhere):

  • Run mitmproxy
  • Copy the auto-generated certificate to your rooted android phone in the appropriate folder
  • Setup iptables to forward traffic though mitmproxy
  • Test if mitmproxy works (you should see decrypted output when you use the browser and go so some https site)

Running the Fossil App with mitmproxy enabled

  • Now when you register a new device you can inspect the traffic from/to Fossil servers in mitmproxy. Facebook is also fed with data. You cannot opt out, but you can block the traffic.
  • Look for a PATCH request to the Fossil server ending with /secret-key (even if it has a 404 response)
  • press enter on that request and loop at the JSON. There your will see a 256 byte key that is base64 encoded, it will look something like this: "secretKey": "eriwogvjmerighDFGWERj45jdfgsd345FDGdfgdfgdf="
  • Do the following (insert your key) echo "eriwogvjmerighDFGWERj45jdfgsd345FDGdfgdfgdf=" | base64 -d | hexdump -C
  • Take the first 16 bytes of the output, in our example this is 7a b8 b0 a2 0b e3 99 ea e2 82 10 c5 19 61 11 8f, remove the spaces and prefix with 0x, ignore the second 16 bytes (second line), we don't need it.
  • This is your key you need for Gadgetbridge (here: 0x7ab8b0a20be399eae28210c51961118f)

Note

You need to finish the firmware installation to the watch and then activate your watch. If the process is interrupted, you need to start over, and you will get a new key, the old one will be invalid, so make sure to keep mitmproxy running until the watch is usable.

When you obtained the authentication key you can enter it in Gadgetbridge.

Entering key

Entering key

If you are currently on the "Device discovery" page, long press on the device name and click on "Auth key" to enter the key.

If you added the gadget already, touch the icon under your gadget name (while on the home screen) to go to the "Device specific settings", open the "Authentication" section, and click on "Auth key" to enter the key.

Enter your key prefixed with 0x ( eg. if your key is 46fec12c98382dgf enter 0x46fec12c98382dgf). Don't press Enter/Return key on the keyboard and make sure 0x is really 0x before pressing "OK", as some keyboards might use different symbols.

After entering your authentication key, try connecting to your gadget to see if it is working.

If everything works alright, congratulations! Now you can uninstall the vendor app of your gadget and start using Gadgetbridge.

Configuring your gadget

Troubleshooting

If you have hard time pairing the watch and you need to factory reset it, here is how.

  • Remove My Watch in the watch settings in the Fossil app.
  • Go to Bluetooth settings and forget the Fossil Watch.
  • Press and hold the middle button until the watch buzzes hard and it resets.
  • Set the watch on its charger.
  • Press and hold the center button AGAIN until the watch resets again.
  • Open the Fossil app and "Pair my First Watch".

Source: Reddit