Python version of the Molto2 USB Config app - molto2.py

We have been getting many requests from the customers asking to make the USB Config tool for Molto2 available under macOS and Linux. The easiest way to achieve this was using cross-platform solutions, and we have chosen to implement this with Python. This allowed us to produce a cross-platform solution that will work on any platform, including Linux, macOS and Windows. The tool allows burning a seed as well as configure various options, such as hash type, system clock and time offset.


molto2.py is a solution developed by Token2 to program and configure the Molto2v2 TOTP hardware tokens using pyscard python library. It works under Linux, macOS and Windows.


Prerequisites


The installation of the required components is described for Windows 10 22H2. But these prerequisites should be suitable for other Windows versions > Window 7. The commands described below are best run via Command Prompt(cmd) with admin rights.
  • Download and install Python for Windows from python.org. Presently, the latest stable version is Python 3.1.1
  • Make sure you have python installed (run “python -–version” to verify )
  • Install swig (pip3 install swig)
  • Download and install Microsoft C++ Build Tools from https://visualstudio.microsoft.com/visual-cpp-build-tools/
  • Install the needed components from the downloaded installer ( vs_buildtools.exe --norestart --passive --downloadThenInstall --includeRecommended --add Microsoft.VisualStudio.Workload.NativeDesktop --add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Workload.MSBuildTools)
  • Install pyscard module for python (pip3 install pyscard)
  • Install sm4 module for python (pip3 install sm4)
  • [optional] Install PyQt5 module for python (pip3 install PyQt5) if you plan to use the GUI
Please note that there are alternative methods of installing Python and its components under Windows that you may find easier, such as Anaconda

  • Make sure you have python3 installed and configured (run "python3 --version" to verify). Follow the instructions here if you don't have python3 installed.
  • Install swig using homebrew (a prerequisite for pyscard installation).
  • Install pyscard module for python3 by following the instructions here
  • Install sm4 module for python ("pip install sm4")
  • [optional] Install PyQt5 module for python (pip install PyQt5) if you plan to use the GUI
  • Download and install the CCID driver for MacOS (to make it recognize Molto2 as a PCSC device)

The installation of the required components is described for Ubuntu 20.04 as an example. If you use a different version (or a different Linux distro), the process may slightly vary.
 
  • Make sure you have python3 installed and configured (run "python3 --version" to verify). Most Linux distros have python3 pre-installed.
  • sudo apt-get update
  • Install swig (sudo apt-get install swig)
  • Install pip (sudo apt-get install python3-pip). Run "pip --version" or "pip3 --version" to verify.
  • Install pyscard module for python3 by running sudo apt-get install python3-pyscard or using pip by running pip install pyscard (or by following the instructions here)
  • Install sm4 module for python ("pip install sm4")
  • [optional] Install PyQt5 module for python (pip install PyQt5) if you plan to use the GUI
  • Install and configure PCSC as described below
PCSC Installation
The script is using PCSC service to connect to the device, therefore you should be having some components installed before you can launch the script:

sudo apt-get install libusb-dev libusb++
sudo apt-get install libccid
sudo apt-get install pcscd
sudo apt-get install libpcsclite1
sudo apt-get install libpcsclite-dev
sudo apt-get install pcsc-tools

You can install them with a single line command as well: sudo apt-get update && sudo apt-get install swig python3-pip libusb-dev libusb++ libccid pcscd libpcsclite1 libpcsclite-dev pcsc-tools PCSC comes with a pre-defined list of supported hardware, primarily smart card readers. As Molto2v2 is a relatively new product, it is not listed in the default configuration, therefore we need to add it manually. Follow the instructions below:
  • Open the device list file, which is usually located at the path below (but the exact folder name may slightly vary):
    sudo nano /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist
    (if this file is not found, try searching using "sudo find / -name Info.plist ")
  • Add <string>0x349E</string> at the end of the section <key>ifdVendorID</key>
  • Add <string>0x0300</string> at the end of the section <key>ifdProductID</key>
  • Add <string>Token2 Molto2</string> at the end of the section <key>ifdFriendlyName</key>
  • Save and restart the service or the system for the changes to take effect (sudo service pcscd restart​)
The procedure above can be done with a bash script as well. See the code below:
#!/bin/sh
filelocation="/usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist";
arrayclose="<\/array>";
sed -i "/${arrayclose}/d" $filelocation;	
searchstring1="ifdProductID<\/key>";	
addstring1="\               <string>0x349E<\/string>";
searchstring2="ifdFriendlyName<\/key>";	
addstring2="\               <string>0x0300<\/string>";
searchstring3="Copyright<\/key>";
addstring3="\               <string>Token2 Molto2<\/string>";	
sed -i "/${searchstring1}/i ${addstring1}" $filelocation;
sed -i "/${searchstring1}/i ${arrayclose}" $filelocation;
sed -i "/${searchstring2}/i ${addstring2}" $filelocation;
sed -i "/${searchstring2}/i ${arrayclose}" $filelocation;
sed -i "/${searchstring3}/i ${addstring3}" $filelocation;
sed -i "/${searchstring3}/i ${arrayclose}" $filelocation;
reboot;


Having issues installing Python and required modules?
You can use the pre-compiled version of this script, molto2-config.exe (Windows only)

Usage

As a start, make sure your system is correctly configured. Plug Molto2 into a USB port and run the script without any parameters:
python3 molto2.py

Please note that depending on your settings the python3 executable name may need to be replaced by python

This should produce results similar to the below:

    [i] TOKEN2 Molto2 USB Config Tool, Python version, v0.1

    [!] Note: No customer key was provided, default customer key will be used

    [+] device serial number: 826658719844499

    [+] device system time (UTC): 2022-11-16 09:07:19

    [+] Authentication successful


If you see the serial number of the device, this means the script has access to it.  You can continue with using the tool. The exact syntax and parameters can be obtained by running the script with --help argument:

python3 molto2.py --help

usage: molto2.py [-h] [--key KEY] [--keyascii KEYASCII] [--profile PROFILE] [--title TITLE] [--seed SEED] [--seedbase32 SEEDBASE32] [--setkey SETKEY] [--setkeyascii SETKEYASCII] [--config]
                     [--display_timeout DISPLAY_TIMEOUT] [--algorithm ALGORITHM] [--timestep TIMESTEP] [--factoryreset]
    
    optional arguments:
      -h, --help            show this help message and exit
      --key KEY             Customer key in hex format. Default will be used if not supplied.
      --keyascii KEYASCII   Customer key in ascii format. Default will be used if not supplied.
      --profile PROFILE     Profile number, from 0 to 49 (Molto2) or from 0 to 99 (Molto2 v2)
      --title TITLE         Profile title, 12 chars max
      --seed SEED           Seed to write, in hex format
      --seedbase32 SEEDBASE32
                            Seed to write, in base32 format
      --setkey SETKEY       Set the new customer key, providing the key in hex. Please note that setting new key requires confirmation on the device (physical button press)
      --setkeyascii SETKEYASCII
                            Set the new customer key, providing key in ascii. Please note that setting new key requires confirmation on the device (physical button press)
      --config              If config parameter is set, the config parameters become required.
      --display_timeout DISPLAY_TIMEOUT
                            mandatory if --config is set as 1. Possible values 0=15s, 1=30s, 2=60s, 3=120s
      --algorithm ALGORITHM
                            mandatory if --config is set as 1. Possible values 1=SHA1 HMAC or 2=SHA256 HMAC hashing algorithm
      --timestep TIMESTEP   mandatory if --config is set as 1. Possible values 1=30 seconds or 2= 60 seconds
      --factoryreset        Resets the device to factory setting and clear all data. Please note this requires confirmation on the device (physical button press)


  --synctime            Will update time on the given profile. Should be used together with --profile parameter
  --synctimeall         Will update time on all profiles.

  --lock                Lock device screen (only for v2.1 and higher)
  --unlock              Unlock device screen (only for v2.1 and higher)
The following example sets a new hex seed (`--seed DEADBEEFDEADBEEF`) and a configuration (`--config`) of TOTP step of 30 seconds (`--timestep 1`), the HMAC algorithm of SHA1 (`--algorithm 1`), title of 'Google' (`--title Google`) and a display sleep timeout of 30 seconds (`--display_timeout 2`) for profile №2 (`--profile 2`):
python3 molto2.py --config --profile 2 --seed DEADBEEFDEADBEEF --timestep 1 --algorithm 1 --display_timeout 2

GUI

A simplified GUI built with QT is also available.

Launch the GUI using the following command (from the same directory):

python3 gui.py

The GUI replicates the interface of the Windows app. Please ensure that the PyQT5 module is installed by executing:

pip install PyQt5

Supported Products

Token2 Molto2v2 purchased in Q2 2022 or later.

License

The solution will be distributed under Fair Source License. While this means that the source code of the solution will be available for our commercial customers, this not a classic "open-source" license. With Fair Source license, you, as an individual user, can view, download, execute, and modify the code free of charge, but cannot re-distribute it without a prior written approval from Token2.


Obtaining the software

The python script will be available for download from your customer account interface if you have placed an order containing a Molto2v2 product.


FAQ

Q: The seed value is not accepted, an error similar to 'Non-base32 digit found'  is produced. How can this be fixed?

Our script expects the base32 seed to be in upper case and without spaces. Some systems (i.e. Google) generate the seed in a format similar to below:
24kw bi2e zwgi xexy a5m4 qdev ax3b qjst
The easiest way to convert this seed to a compatible format is running the command below
echo "24kw bi2e zwgi xexy a5m4 qdev ax3b qjst" | sed 's/ //g' | tr [:lower:] [:upper:]
This command will output the seed as 24KWBI2EZWGIXEXYA5M4QDEVAX3BQJST, which will be accepted by the script


Q: The seed is not accepted. The error given is "binascii.Error('Incorrect padding')". What is the reason?

While this does not matter for the TOTP calculation itself, the string length of a base32 seed is expected to be a power of 2 (i.e. 16, 32 or 64). If the seed value you have is shorter, you can fix the issue by adding empty characters ("A" in base32). So, for example,  if the seed is JBSWY3DPEHPK3PXPJBSWY3DPEHPK (28 chars), you just add 4 "A"s to it and use JBSWY3DPEHPK3PXPJBSWY3DPEHPKAAAA instead. The OTP generated will be exactly the same (empty characters are ignored).


Q: How can I remove a seed?

There is no API for removing a seed, but you can simply overwrite with an empty one (32 x "0" characters in hex): 
i.e. python3 molto2.py --profile 2 --seed 00000000000000000000000000000000 will overwrite the seed of profile #2 with an empty string


Q: Do I have to sync the time clock of each TOTP profile separately, or do they use the same hardware clock?
A: Each profile has its own independent clock, allowing you to set and adjust time settings individually for each one. For example, while most TOTP implementations use UTC timezone, there may be cases when a particular service has implemented a different time zone. For this reason, you can set the time of that particular profile differently from the rest.

However, if you want to synchronize the clocks for all TOTP profiles simultaneously, you can conveniently use the --synctimeall parameter. This parameter ensures that the time synchronization process is applied to all profiles at once, simplifying the management of time settings across your TOTP profiles.