How to compute the app hash string for Android SMS Retriever API

Emanuele Origgi
funambol-techblog
Published in
3 min readJan 31, 2020

Very often during the sign up process, to complete the user creation procedure, apps make use of SMS to send a verification code. When the same phone is used to both receive the SMS and perform the signup, the app can automatically read the SMS message and detect the verification code, without requiring the user to manually enter it.

Until a few months ago, on Android, implementing this type of auto detection required the user to grant permission for SMS (SMS_RECEIVE and SMS_READ). Once granted, apps could listen for incoming SMS and read the verification code.

Since January 2019, due to security reasons, Google has restricted the usage of some permissions, including the SMS ones. With this new policy, only very specific apps can be allowed to use the SMS permissions and Google Store is very strict in verifying it.

Thankfully, in order to keep using the auto insertion of the verification code, Google made a new API to read an SMS text without requiring the SMS permissions, the SMS Retriever API.

Automatic SMS Verification with the SMS Retriever API

With this new API the app doesn’t need to keep listening for incoming SMS but it’s up to the Android system to send the text of a specific SMS to the app.

In order to do so, we need to use the new SmsRetrieverClient object:

After calling the client.startSmsRetriever() method, the system will start listening up to 5 minutes for a specific SMS.

When the SMS is delivered, a broadcast is triggered:

If the status is CommonStatusCode.SUCCESS we can get the message and extract from it the verification code.

However, this raises a concern: how can the system detect which SMS message we need?

To allow this, the SMS needs to contain a specific string that uniquely identifies our app. For instance, this is a valid SMS the system can detect:

Your ExampleApp code is: 123ABC78FA+9qCX9VSu

The last string (FA+9qCX9VSu) is a hash that allows the system to associate the SMS to our app.

Google documentation describes the steps to generate that hash:

  1. Convert the certificate used to sign the app to lower-case hex string
  2. Append that hex string to the app package name, separated by a single space
  3. Compute the SHA-256 of the combined string and convert the result to a Base64 string
  4. The first 11 characters of the Base64 string is the hash to use in the SMS

Manually executing these steps can be tricky and error prone.

In the same page of the Google documentation there is a command that performs all the steps to compute the hash:

keytool -exportcert -alias PlayDeploymentCert -keystore MyProductionKeys.keystore | xxd -p | tr -d "[:space:]" | echo -n com.example.myapp `cat` | sha256sum | tr -d "[:space:]-" | xxd -r -p | base64 | cut -c1-11

But, as noted in the documentation, that command is not very reliable:

  • it does not emit an error if the reading of the certificate fails. Instead, it will compute the hash of the error message itself!
  • it should be changed a bit to run it on Mac
  • it does not work at all on Windows

To resolve these issues, in Funambol we wrote a small but effective python script to automatically compute the needed hash string that correctly handles the error scenarios.

The script is available in our GitHub page.

This python script (smshash.py) works on Linux, Mac and Windows and it is very easy to use. It just requires four parameters:

  • The path of the Android keystore that contains the certificate
  • Keystore alias
  • Keystore passphrase
  • App package name
python3 smshash.py path/keystore MyAndroidAlias MySecretPassphrase com.example.myapp

In case of errors, the script stops, returning a descriptive error message. For instance:

keytool command failed. Please check the alias and the password are correct

Feel free to fork the repository and submit your own pull requests, or star it if you think it is useful.

--

--