Skip to main content

Software FIDO2 Passkey Authenticator

Project description

Soft FIDO2 (passkey)

Software implementation of the W3 WebAuthn specification. Project attempts to emulate all known attestation types.

Use at your own risk.

Prerequisites:

System

  • libnotify >= 0.8.7
  • bcrypt >= 1.1
  • python3-virtualenv >= 20.29.1

Python

  • = Python 3.7

Pip modules

  • asn1 >= 2.2.0
  • cryptography >= 38.0.1
  • cbor2 >= 4.1.2
  • PyJwt >= 0.6.1
  • PyQt6 >= 6.9.1

For GNOME Users (Tested on GNOME 48)

Usage

Command line

Attestation:

  • Basic usage  Module will look for a .fido2 folder in the home directory of the user. If it does not exist then the module will return a non-zero exit code. If the directory exists, the soft_fido2 module will then generate a key if required to generate an attestation type attestation response to the given attestation options:
FIDO_HOME=$HOME/.fido2 python3 -m soft_fido2.authenticator attestation <attestation type> <attestation options>
```  
The following example takes a JSON dictionary of attestation options provided by a FIDO2 relying party (RP) and prints a dictionary to stdout which contains the authenticator's response to the attestation request. The example uses 'packed-self' as the attestation format. Other attestation formats are supported; however, there is more complex setup required generating the required trust anchors and uploading them to your relying party.


```bash
ATTESTATION_OPTIONS='{
  "rp": {
    "id": "www.myrp.ibm.com",
    "name": "ISAM_Unit_test"
  },
  "user": {
    "id": "3RH-c7d8Ss60BKau7mLKXA",
    "name": "testuser",
    "displayName": "testuser"
  },
  "timeout": 60000,
  "challenge": "mjqlXDT4RySLMyRCEePZgHpbgRCkFq9Gip4apBxcvTg",
  "excludeCredentials": [],
  "extensions": {},
  "authenticatorSelection": {
    "userVerification": "preferred"
  },
  "attestation": "direct",
  "pubKeyCredParams": [
    {
      "alg": -7,
      "type": "public-key"
    },
    {
      "alg": -35,
      "type": "public-key"
    },
    {
      "alg": -36,
      "type": "public-key"
    },
    {
      "alg": -257,
      "type": "public-key"
    },
    {
      "alg": -258,
      "type": "public-key"
    },
    {
      "alg": -259,
      "type": "public-key"
    },
    {
      "alg": -65535,
      "type": "public-key"
    }
  ],
  "status": "ok",
  "errorMessage": ""
}'

python3 python_authenticator/soft_fido2/authenticator.py 'attestation' 'packed-self' ${ATTESTATION_OPTIONS}
> {
>   "id": "EyOlQBLvCZUK96Z9DpCKYBw_aLOh4FikSd3h-1fKukk=",
>   "rawId": "EyOlQBLvCZUK96Z9DpCKYBw_aLOh4FikSd3h-1fKukk=",
>   "response": {
>     "clientDataJSON": "eyJvcmlnaW4iOiAiaHR0cHM6Ly93d3cubXlpZHAuaWJtLmNvbSIsICJjaGFsbGVuZ2UiOiAiVmk2Z3ZOMnlJdk5STDlLVndvOEZ0Ui1mSDNnUjkyTHdDdG5lUXVleWF3WT0iLCAidHlwZSI6ICJ3ZWJhdXRobi5jcmVhdGUifQ==",
>     "attestationObject": "o2hhdXRoRGF0YVkBbi-RrhkzFXpmZDWmVjlcmnlaWE_ET4cAHsNcOr-craCzRQAAAAAAAAAAAAAAAAAAAAAAAAAAACATI6VAEu8JlQr3pn0OkIpgHD9os6HgWKRJ3eH7V8q6SaRhMQNhMzkBAGItMVkBANNSB4BmS7RVWYwmuTyQmkmOZjiULIEgU_YpmgYX2yxTDgwf36TEwZDuoq-dfJiKGyPux5hnPSNia0iYGR8ABtO5pt9Ay5fHiHQ9Io5qcXw29gm8VPdHJhvcc0hMtctTCWy87QXiaI85MP-Uxd6fdEcGySnmhlUBjR5REJY89bql4BYLoK8wR90bohppGT0Dxh3kwY6QpXdZFVek2aGKA7YF4IM0lquRqMSvy9b_j2tl7NvNcoAU_-Kv-UufpyFqvWn1psjUMFyUvTBeP5dH_VWuuIINnbrgYuloei3IlA6DjIu7dvMuExXpFTTbILnstvOJGkrofboB8ELPnYK87P1iLTJEAAEAAWNmbXRmcGFja2VkZ2F0dFN0bXSiY2FsZzkBAGNzaWdZAQBPiPQ22-D-hqHKBDGtp6qKo8PuIttaD9qvXLU6IsfYVK9xUban1teHTqfCZ6bvubnSQc7SzR-DmrAGh4GvQA38ag__W-3uWQ3x2el_dvIWd5fZRtbYuf0n7v4WCIHru79AyIaNszECOIZu--0QoWRbrmcpjgsDQbS6Rm3eqqczKAWHUWAJuKtCp1Evv1V3ChYSmpMIKBTvDmOltF1YncY6goCt-Xa3auWm9VwbXi6LH_wAtSWCLrdyp6VcIS8n7w9m7fTiGALIi_y1xaiVJz5U5rYlHpTElKTvI4ceO23mlEqgi_O9Pfqg8dA1ejXxpc4yvTTMaihbZq_vtEgMup4h"
>   },
>   "type": "public-key",
>   "getClientExtensionResults": "oA==",
>   "nickname": "some_name"
> }

Assertion:

  • Basic usage

FIDO2_HOME=$HOME/.fido2 python3 -m soft_fido2.authenticator assertion <assertion options>

The following example takes a JSON dictionary of assertion options provided by a FIDO2 RP and generates the assertion response. This example will only work if an attestation (registration) has previously been run for the required user against the target relying party.

ASSERTION_OPTIONS='{
  "rpId": "www.myrp.ibm.com",
  "timeout": 60000,
  "challenge": "kI9SKJRxv4zpICnG1Ls9FMwQ4t4Zq6t8HqKAJKzeyXI",
  "extensions": {},
}'

python3 -m soft_fido2.authenticator 'assertion' ${ASSERTION_OPTIONS}
> {
>     "id": "EyOlQBLvCZUK96Z9DpCKYBw_aLOh4FikSd3h-1fKukk=",
>     "rawId": "EyOlQBLvCZUK96Z9DpCKYBw_aLOh4FikSd3h-1fKukk=",
>     "response": {
>         "clientDataJSON": "eyJvcmlnaW4iOiAiaHR0cHM6Ly93d3cubXlpZHAuaWJtLmNvbSIsICJjaGFsbGVuZ2UiOiAia0k5U0tKUnh2NHpwSUNuRzFMczlGTXdRNHQ0WnE2dDhIcUtBSkt6ZXlYST0iLCAidHlwZSI6ICJ3ZWJhdXRobi5nZXQifQ==",
>         "authenticatorData": "L5GuGTMVemZkNaZWOVyaeVpYT8RPhwAew1w6v5ytoLMFAAAAAA==",
>         "signature": "Tn1J7kTWVL_MmSVimB95r7MDhG8T18pm-CD7TQn5dsbcTec6M8E_4-TFS-U3xto6bYlmciw8YYXpINCag0KetdnCMhm0D23ElcUGcEbdJmpzuMdotjW6AZRnLMe6aZU7uSyzwvcustYeKlAtSziSAw7qHL4ucnJYQZhsaCpya325UgpNshAHXcG3an_nRbogvKd__zjg3Fr-2qltP8r9CneuOSpphnBTWTmNk8cC16Nluhi81rugjlMdDgP6_pyYcpxSR1FVN_fJnnqmwRyundR29C-SCe3-NGHcgKOdeZf6izpw1FXfET4LRKpxoPiIApWLGb7tg6jIVQieT_QXsQ=="
>     },
>     "type": "public-key"
> }

PIP module

First install from artifactory (requires IBM W3 login details)

  • pip3 install soft_fido2

Once isntalled the FIDO2 authenticator can be imported like any other python module. The following example shows how to use the authenticator to generate an attestation (registration) with the 'packed-self' format then subsequently use the same authenticator to perform an assertion.

import json
import requests
from soft_fido2 import Fido2Authenticator

#This will create a Fido2Authenticator with 2048-bit RSA key
authenticator = Fido2Authenticator()

##Attestation
attestation_options = {
  "rp": {
    "id": "www.myrp.ibm.com",
  },
  "user": {
    "id": "rOIpHRr9St-YqugsfyZgAw",
    "name": "testuser",
    "displayName": "testuser"
  },
  "timeout": 60000,
  "challenge": "Vi6gvN2yIvNRL9KVwo8FtR-fH3gR92LwCtneQueyawY",
  "excludeCredentials": [],
  "extensions": {},
  "authenticatorSelection": {
    "userVerification": "preferred"
  },
  "attestation": "direct",
  "pubKeyCredParams": [
    {
      "alg": -7,
      "type": "public-key"
    },
    {
      "alg": -35,
      "type": "public-key"
    },
    {
      "alg": -36,
      "type": "public-key"
    },
    {
      "alg": -257,
      "type": "public-key"
    },
    {
      "alg": -258,
      "type": "public-key"
    },
    {
      "alg": -259,
      "type": "public-key"
    },
    {
      "alg": -65535,
      "type": "public-key"
    }
  ],
}

attestation_response = authenticator.credential_create(attestation_options, atteStmtFmt='packed-self')
print(json.dumps(attestation_response, indent=4)) # print not required but useful for debugging

rp_response = requests.post("https://www.myrp.ibm.com/attestation/result",
                        json=attestation_response)

##Assertion
assertion_options = {
  "rpId": "www.myrp.ibm.com",
  "timeout": 60000,
  "challenge": "kI9SKJRxv4zpICnG1Ls9FMwQ4t4Zq6t8HqKAJKzeyXI",
  "extensions": {},
}

assertion_response = authenticator.credential_request(assertion_options)
print(json.dumps(assertion_response, indent=4))

rp_response = requests.post("https://www.myrp.ibm.com/assertion/result",
                        json=assertion_response)

Environment properties

FIDO_HOME

Property used for firectory which contains .passkey files which can be opened by suft_fido2 to provide attestaiton and assertion responses.

Passkey files can be generated by the util scripts, or the system tray (if supported).

SOFT_FIDO2_SKIP_UP

The SOFT_FIDO2_SKIP_UP property is used to skip the user presence check during attestation and assertion.

If this property is set to true then UV checks always immediatly return true for the get_info, make_cred and get_next_assert authenticator commands.

SOFT_FIDO2_DEBUG_LEVEL

The SOFT_FIDO2_DEBUG_LEVEL property is used to set the debug level for the soft_fido2 library. The default debug level is INFO

SOFT_FIDO2_LOG_FILE

The SOFT_FIDO2_LOG_FILE property is used to set the log file for the soft_fido2 library. If this file is provided it will be created relative to the $FIDO_HOME directory. The default log file is stdout.

USBIP OS Integration

Requires:

  • USB/IP
  • Python
    • usb_ip

Python server is hard coded to listen on the default USB/IP port (3240)

Users can use lsusb to list the devices known to the client.

Users can use dmesg to debug USB packed recieved by the client.

Start the python usbip server

python hid_device.py

List the device

usbip list -r 127.0.0.1

Attach to a device

sudo modprobe vhci-hcd
usbip attach -r 127.0.0.1 -b <bus_id, 1-1.1>

UHID OS Integration

Requires

  • UHID (Fedora)
  • Python3
  • Notify Send (libnotify)

Users must set the FIDO_HOME environment property. This should be a directory which will contain encrypted passkey files.

Virtual Passkey Device can be started by running the module as a user with sufficient permission to open the /dev/uhid device:

# Root privileges are assumed
# Give sufficient permissions to open /dev/uhid:
# Create a rule in /etc/modules or /etc/modules-load.d so that the uhid module loads during boot
echo 'uhid' | tee /etc/modules-load.d/uhid.conf
# Create udev group and add a user to it
groupadd udev
usermod -aG udev $USER
# Create udev rule for uhid access with sufficient permissions
echo 'KERNEL=="uhid", GROUP="udev", MODE="0660"' | tee /etc/udev/rules.d/90-uhid.rules
# Apply rule
udevadm control --reload-rules && udevadm trigger
# Reboot to load uhid module during next boot

# Create key pair for encrypting half of the pin hash, this should be done for all users using software passkeys
openssl ecparam -name prime256v1 -genkey -noout -out $HOME/.fido/platform.key

# Create systemd daemon
export FIDO_HOME=/opt/soft_fido2
mkdir -p $FIDO_HOME
virtualenv $FIDO_HOME
$FIDO_HOME/bin/python -m pip install --upgrade pip soft_fido2
# In user's home directory
mkdir -p ${HOME}/.fido2
#FIDO_HOME=${HOME}/.fido2 $FIDO_HOME/bin/python -m soft_fido2
echo 'FIDO_HOME=${HOME}/.fido2' > $FIDO_HOME/passkey.env
cat <<EOF > /usr/lib/systemd/system/passkey.service
[Unit]
Description=Software FIDO2 Passkey
After=basic.target

[Service]
ExecStart=/opt/soft_fido2/bin/python -m soft_fido2
Type=simple
Restart=no
EnvironmentFile=/opt/soft_fido2/passkey.env

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable passkey
systemctl start passkey

# Confirm authenticator is running
hexdump -C "/sys/bus/hid/devices/$(ls /sys/bus/hid/devices | grep 1337:1337)/report_descriptor"
# Output of command should be identical to the sequence below
# 00000000  06 d0 f1 09 01 a1 01 09  20 15 00 26 ff 00 75 08  |........ ..&..u.|
# 00000010  95 40 81 02 09 21 15 00  26 ff 00 75 08 95 40 91  |.@...!..&..u..@.|
# 00000020  02 c0                                             |..|
# 00000022

Development

Project can be build and installed locally using a python virtual environment.

Set up a python virtual environment as follows:

export FIDO_HOME="$HOME/.fido2"
mkdir -p $FIDO_HOME
virtualenv $FIDO_HOME
$FIDO_HOME/bin/python -m pip install --upgrade pip
$FIDO_HOME/bin/python -m pip install --upgrade -r dev-requirements.txt
export GITHUB_RUN_NUMBER=9999
$FIDO_HOME/bin/python -m build
$FIDO_HOME/bin/python -m pip install --upgrade dist/soft_fido2-*-py3-none-any.whl 
$FIDO_HOME/bin/python -m soft_fido2

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

soft_fido2-0.3.6.tar.gz (71.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

soft_fido2-0.3.6-py3-none-any.whl (71.5 kB view details)

Uploaded Python 3

File details

Details for the file soft_fido2-0.3.6.tar.gz.

File metadata

  • Download URL: soft_fido2-0.3.6.tar.gz
  • Upload date:
  • Size: 71.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.5

File hashes

Hashes for soft_fido2-0.3.6.tar.gz
Algorithm Hash digest
SHA256 7a5e6606e8bf53b2c7c4bd4b54e4a8cdd134302ff6376ab7ee3012e4b2dae3bd
MD5 e6a25d87876051081c42d4f164288b2f
BLAKE2b-256 9c616231fb719463e5d0d220681de37fc07434592f30f20edd7b347c4841fee7

See more details on using hashes here.

File details

Details for the file soft_fido2-0.3.6-py3-none-any.whl.

File metadata

  • Download URL: soft_fido2-0.3.6-py3-none-any.whl
  • Upload date:
  • Size: 71.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.5

File hashes

Hashes for soft_fido2-0.3.6-py3-none-any.whl
Algorithm Hash digest
SHA256 cc16831f0511daafe1e6e1cc28522c1be4edb91a581f909d85894f4ce61b6961
MD5 8daa64cca95fa8c1626e96b352fd532b
BLAKE2b-256 2d48ebbf369b46b15b38ca239bfe75177a05d4fea9df4770ade2fc230a2af097

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page