We are always very excited to put Kryptor to work on diverse use cases and this time we have been busy steaming encrypted audio files using Kryptor HSM FPGA. Imagine using it for sending encrypted voice messages or any other audio file that needs protection.
For this project, you need 2 Raspberry boards and 2 Kryptor HSM FPGA boards. As we have mentioned before, you have to keep in mind that by using Kryptor you can secure the end2end data communication between two endpoints and this also means (in order to have the higher level of security) that you need two boards, one on each end. This is the safest way to secure the data link and ensure that no one in the middle can decrypt the data along the path, only the two FPGA chips (one per board) have the proper keys (self-generated within the chip) to encrypt and decrypt the data. As a compromise (less secure) you can also have only one end-pointed secured with Kryptor and the other one running on a software library (e.g., OpenSSL or WolfSSL). It does work (in fact Kryptor uses very standard encryption protocols) but the software side will be your weakest link in the solution.
In the following paragraphs, we will walk you through the process of creating an encrypted voice streaming application by using Kryptor HSM FPGA. The server encrypts the audio chunks and sends them in real-time to a client. The client decrypts and plays the incoming multimedia stream in real-time and plays the audio as the data is received (always in real-time). Received chunks are played immediately. Two Raspberry Pi’s are used and each of them is connected to a Kryptor HSM module. For this use case, all software has been written in python3.
- 2x Kryptor HSM FPGA boards
- 2x Raspberry Pi’s:
– RPI-1: model Pi4 model B 2GB (player for the audio file)
– RPI-2: model Pi3 model B+ 1GB (sender for audio file)
Both models have a CPU with 4 cores and the application is optimized for using all cores despite python GIL limitations.
Both Raspberry Pi's have to be updated:
sudo apt update
sudo apt upgrade
sudo apt dist-upgrade
sudo apt install python3-pip
sudo apt install -y python3-pyaudio
1.1 System configuration
RPI-1: eth0: 192.168.1.225 Linux RPI-1 5.10.17-v7l+ #1403 python 3.7.3 RPI-2: eth0: 192.168.1.117 Linux RPI-2 5.10.17-v7+ #1403 python 3.7.3
1.2 Connect Kryptor FPGA to the Raspberry Pi
Read the documentation here.
1.3 Setting up Raspberry Pi
1.3.1 Install Raspbian to an SD card
Download and install Raspbian, Raspberry Pi’s official operating system, to an SD card. Image and installation tools are found here: Raspberry Pi Downloads.
1.3.2 Install Kryptor FPGA Command-Line Interface tool (CLI)
Kryptor FPGA board ships (verify the update procedure on how to get it on the Skudo site) with the command-line software
hsm_cli which we will be using in this tutorial.
Alternatively use WinSCP (or similar) to move the file from your PC to the RPi
Make the file executable by running:
$ chmod +x hsm-cli
Verify that the Raspberry Pi is able to communicate with Kryptor FPGA by reading the device’s serial number by running:
$ ./hsm-cli --serial
You should see something along with the following output (depending on the version you got):
Vendor: Skudo OÜ (www.skudo.tech) Product: HSM/FPGA Serial: XXXX-XXXX-XXXX-XXXX
If the command fails please check that all jumper wires are properly connected according to the diagram in section 1.2. Make also sure that your breadboard and the cables are of good quality, try to wiggle them in their positions (it’s not uncommon to have quality problems with jumper wires and breadboards).
If command hsm_cli command returns
Procotol version mismatch.
This hsm_cli is using protocol 1.3, while device is reporting 0.0
Please use matching hsm_cli version, or update the device firmware.Protocol version mismatch
The Kryptor board is not well connected to raspberry and not recognized by the CLI.
1.3.4 Enable SPI on Raspberry Pi
Be sure SPI is enabled on raspberry
Create public-private key pairs
1.4 Configure Raspberry to run the audio application
1.4.1 Create ramdisk
hsm_cli works getting a file as input and writes a file as output. Realtime cryptography requires time-intensive operations. We use a ramdisk for all I/O physical operations performed by HSM-CLI. Read and write speed will boost performances eliminating glitches in the audio playing.
Both RPI-1 and RPI-2 run a small ramdisk.
Command to create 1MB ramdisk and copy hsm_cli:
pi@RPI-1:~ $ sudo mkdir /tmp/ramdisk
pi@RPI-1:~ $ sudo chmod 777 /tmp/ramdisk
pi@RPI-1:~ $ sudo mount -t tmpfs -o size=1m myramdisk /tmp/ramdisk
pi@RPI-1:~ $ cp /home/hsm_cli /tmp/ramdisk
pi@RPI-2:~ $ sudo mkdir /tmp/ramdisk
pi@RPI-2:~ $ sudo chmod 777 /tmp/ramdisk
pi@RPI-2:~ $ sudo mount -t tmpfs -o size=1m myramdisk /tmp/ramdisk
pi@RPI-2:~ $ cp /home/hsm_cli /tmp/ramdisk
OSS: Ramdisk created with these commands is not permanent and has to be recreated if Raspberry is rebooted.
1.4.2 Configure ALSA audio
(install the latest version from source)
Install pulseaudio modules:
sudo apt install pulseaudio pulseaudio-utils python3-pyaudio
RPI CPU might burn too much CPU time doing non-sound-related tasks and not allocating enough CPU time to write sound data chunks to the soundcard. This is recognized by getting the following message when our application is run on the player audio (RPI-1):
ALSA lib pcm.c:7843:(snd_pcm_recover) underrun occurs during playback
The kernel empties out the buffer into the soundcard (to be played) and then ALSA reports underrun - i.e. the buffer is completely empty.
To prevent this situation ALSA buffer needs to be increased by setting in /etc/pulse/daemon.conf the following parameters:
default-fragments = 100
default-fragment-size-msec = 1
and restarted pulseaudio with
pulseaudio -k or
systemctl --user restart pulseaudio.service
1.4.3 Install python3 lib
On both RPI install the following python modules:
sudo pip3 install python3-pyaudio
1.5 Audio software installation
1.5.1 Software modules
RPI-1 reads chunks from a WAV file, encrypted by using local Kryptor HSM, and sends to the player (RPI-2). Data transfer is performed using TCP protocol that allows to send packets bigger than MTU and automatically splits up packets into multiple pieces. TCP will get reassembled at the end. Due to our hardware configuration and audio codec (PCM) used in our test, there is a need to send a big packet to avoid audio buffer underrun on the player side.
Client-server software has been developed to test real-time audio encryption. Both modules (sender WAV file and player) include functions to encrypt and decrypt audio chunks locally using the HSM board. It is recommended to run first the player and then launch the sender:
Module in RPI-1 are saved in
RPI-1:~/audioPlayer $ ls -ltr
-rw-r--r-- 1 pi pi 6098 Mar 12 17:43 audioPlayerFileTCP.py
Module in RPI-2 are saved in
RPI-2:~/audioSender $ ls -ltr
-rw-r--r-- 1 pi pi 8375 Mar 12 17:43 audioSenderFileTCP.py
1.5.2 Socket configuration and run application
RPI-2:~/audioSender $ python3 audioSenderFileTCP.py 192.168.1.117 10100 encryption
The sender is listening on local IP 192.168.1.117 and port 10100 for incoming connections.
RPI-1:~/audioPlayer $ python3 audioPlayerFileTCP.py 192.168.1.117 10100 encryption
If these two ports are used already by other applications then you need to change them.
Type the following command to check if a port is in use on Linux:
$ sudo netstat -tulpn | grep LISTEN
1.5.3 WAV file parameters
In the package, there is a sample WAV file,
sample.wav of 30sec., format=8, bitrate=44100, and 2 channels.
The sender extracts multimedia WAV info directly from the sample.wav file. audioPlayerFileTCP.py has 3 parameters to set in the code with the same values:
CHANNELS = 1
RATE = 44100
If you are using a different WAV file those 3 settings have to be reconfigured.
1.5.4 Audio buffer and chunk size
audioPlayerFileTCP.py uses a small buffer, call
AUDIOBUFFER to play audio without glitches. In our environment, the audio buffer is set to "20" (
AUDIOBUFFER=20) and it can be adjusted based on hardware and network performances. It can be increased when the LAN is overloaded and too slow. However, a bigger buffer introduces a longer delay before starting to hear the incoming audio streaming.
1.5.5 Frame per buffer
frames_per_buffer – Specifies the number of frames per buffer.
Congratulations! Your audio file is now securely encrypted, sent, and received between 2 endpoints. We hope this tutorial gave you some concrete and practical demonstration of how SKUDO Kryptor works and inspires you to try it yourself on your next project that needs strong and trusted encryption.