FacetID Calculation
This section provides help in calculating the Access App facet ID. The FacetID is part of the required backend configuration.
- The nevisAdmin4 documentation offers information on where to configure the FacetID in the nevisFIDO Setup.
- Chapter FIDO UAF Configuration of the nevisFIDO Reference Guide provides detailed configuration information.
- The Nevis Access App supports wildcard facet entries such as
android:apk-key-hash:*
andios:bundle-id:*
. Wildcard facet IDs are useful for testing and demo purposes, however they are not allowed in production environments, use specific facet ID entries as described below instead. Because of this, only the integration flavor of the Access App allows / accepts wildcard facet IDs, the production flavor does not.
iOS
In the iOS case, the FacetID must be the BundleID URI of the application:
ios:bundle-id:<ios-bundle-id-of-app>
Android
To get the correct FacetID for the Android app, install the app on a device, and extract the facetID from the advanced settings menu.
According to the FIDO UAF 1.1 Specifications, the FacetID for Android is a Base64 encoded hash value based on the SPK signing certificate:
android:apk-key-hash:<hash-value>
The example in the FIDO UAF 1.1 specification "EXAMPLE 1: Computing an APK signing certificate hash" is wrong! It will lead to a wrong hash being calculated.
- The filtering of the error output is wrong (correct: "2>", incorrect: "&>2").
- The keystore (or key) password must be provided if the keystore is password protected.
- The Nevis Access App uses SHA-256 to calculate the Facet ID hash.
- Wildcard facet IDs are supported for development and testing purposes.
For additional information, refer to the chapter Functional Adaptions of the FIDO UAF Specification.
Hash Calculation
If Google Play store Play App Signing is used, you cannot use the tool to calculate the FacetID, as the certificate used by Google is different, and thus leads to a different FacetID. In this case, install the app on an Android device, and extract the facetID from the advanced settings menu.
We recommend using the calculateFacetId.sh
script to calculate the FacetID. This script checks the output of the keytool command logs error to stdout in case an error occurs.
calculateFacetId.sh Script - Click to Expand
#!/bin/bash
usage()
{
echo "usage: calculateFacetId.sh --keystore <path-to-apk-signing-keystore> --key-alias <alias-of-entry> [--keystore-password <keystore-password>]"
}
keystore=''
keystore_password=''
key_alias=''
while test $# -gt 0
do
case "$1" in
--keystore)
keystore=$2
;;
--key-alias)
key_alias=$2
;;
--keystore-password)
keystore_password=$2
;;
--*)
echo "bad option $1"
usage
exit 0
;;
esac
shift
done
if [ -z $keystore ] || [ -z $key_alias ]
then
usage
exit
fi
echo "-----------------------------------"
echo "Keystore: $keystore"
echo "Key alias: $key_alias"
echo "Keystore password is $(if [ -z $keystore_password ]; then echo "NOT "; fi)provided"
echo "-----------------------------------"
keystore_password_argument=$(if [ ! -z $keystore_password ]; then echo "-storepass $keystore_password"; fi)
command="keytool -keystore $keystore -alias $key_alias -exportcert $keystore_password_argument"
[ -f "$keystore" ] || {
echo "Keystore file ($keystore) doesn't exist."
echo "-----------------------------------"
exit 0
}
eval $command 2> /dev/null > cert.crt <&-
if [[ $(cat cert.crt) != *error* ]];
then
facet_id=$(cat cert.crt | openssl sha256 -binary | openssl base64 | sed 's/=//g')
echo "Calculated FacetID:"
echo "android:apk-key-hash:$facet_id"
echo "-----------------------------------"
else
echo "Error in calculation: $(cat cert.crt)"
echo "-----------------------------------"
fi
rm cert.crt
The script
- exports the signing certificate in DER format,
- base64 encodes the hash of it, and
- trims the '=' sign.
The script temporarily exports the certificate into a file (cert.crt) into the current directory. Therefore, the current user must have write permission in the current folder.
Script Usage
If the keystore is protected with a password, supply the option --keystore-password to prevent the execution from resulting in an error (see the code snippet further below; the option is part of the first code section).
If no errors occur, the scripts reports the whole FacetID as output:
> ./calculateFacetId.sh --keystore <path-to-apk-signing-keystore> --key-alias <alias-of-entry> --keystore-password <keystore-password>
-----------------------------------
Keystore: <path-to-apk-signing-keystore>
Key alias: <alias-of-entry>
Keystore password is provided
-----------------------------------
Calculated FacetID:
android:apk-key-hash:<calculated_hash>
-----------------------------------
In case of an error, the output shows the occurred error message:
> ./calculateFacetId.sh --keystore <path-to-apk-signing-keystore> --key-alias <alias-of-entry> --keystore-password <wrong-keystore-password>
-----------------------------------
Keystore: <path-to-apk-signing-keystore>
Key alias: <alias-of-entry>
Keystore password is provided
-----------------------------------
Error in calculation: keytool error: java.io.IOException: Keystore was tampered with, or password was incorrect
-----------------------------------
Manual FacetID Calculations
We recommend using the scripts below only for verification purposes, to check that the hash generated by the calculateFacetId.sh
script is correct.
Keystore without Password
In case of a keystore without password, you can use the computing method example included in the FIDO UAF 1.1 Specifications. Considering the warning mentioned above, the corrected method is the following:
keytool -keystore <path-to-apk-signing-keystore> \
-alias <alias-of-entry> \
-exportcert 2> /dev/null | \
openssl sha256 -binary | openssl base64 | sed 's/=//g'
Keystore with Password Containing Key
In case of a keystore with a password that contains the key, provide the keystore password (-storepass) to export the signing certificate:
keytool -keystore <path-to-apk-signing-keystore> \
-alias <alias-of-entry> \
-exportcert \
-storepass <keystore-password> 2> /dev/null | \
openssl sha256 -binary | openssl base64 | sed 's/=//g'