#Presentation A HSM (Hardware Security Module) is a system that enables the secure storage of cryptographic secrets, and to which computations such as encryption, signing, Diffie-Hellman key exchange, encoding, random sequence generation, etc. can be delegated. The application presented here offers this type of functionality: - key management: RSA, elliptic curves, ED25519, X25519, AES, DES, DES3 - key-based operations: encryption/decryption, signing/verification, Diffie-Hellman key exchange - keyless operations: hashing, base64/ascii/hex encoding, random sequence generation - access via console, http(s) and ssh - user management - authentication by ssh key, ssl certificate or password - fine-grained access rights management - customisable formatting of result display The application can run on any type of platform: - on a computer or mobile device with an OS: Windows, Unix-like, MacOS, iOS, Android - bare-metal on the Raspberry Pi 4 board - bare-metal on the MM-2350 board #Setup - clone the application repository: >git clone https://github.com/ambermind/mini-hsm.git ## Running on a computer You can already run the application on your computer - install Minimacy, as described in the [Setup section](page://2000.100.100). Build Minimacy or use the Release distribution. - run the program ./hsm.mcy ## Running on the MM-2350 board You can use the application on the MM-2350 board: - it is assumed you are already familiar with the board; if not, see the tutorial here: [Tutorial >>](https://minimacy.net/book/#/tag/mm-2350) - copy the contents of the repository to the root of an SD card formatted as FAT32 - insert the SD card into the MM-2350 board - it is recommended to connect the console (usb/uart cable) and run the program ./programs/romdisk/romdisk.server.mcy to monitor the hsm startup - power on the MM-2350 board [](html) ## Running on the Raspberry Pi 4 board For the Raspberry Pi 4 board: - it is assumed you are already familiar with the board; if not, see the tutorial here: [Tutorial >>](https://minimacy.net/book/#/tag/rpi4) - prepare an SD card formatted as FAT32 with the official files and the two Minimacy-specific files, as explained in the 'Blink' chapter of the Raspberry Pi 4 page [](html) - then copy the contents of the hsm repository to the root of the SD card - it is recommended to connect the console (usb/uart cable) and run the program ./programs/romdisk/romdisk.server.mcy to monitor the hsm startup - power on the Raspberry Pi 4 board #Launch In all cases you get the same output in the console: >> Check admin account >> Load keys >> Start console > >MiniHSM - 2025 - Sylvain Huet >Type 'man' to access manual >OK >logon admin admin >Access granted >OK >> Please change the admin password! > >admin> By default, the hsm configuration only opens the console, and on first startup creates an 'admin' user with the password 'admin'. You are invited to change it as soon as possible. The console automatically connects using this admin account (as long as the password is 'admin'). You can then enter commands: >admin> randomBytes 24 >58fa244e2d72c48b3dc98d6b8fbf8f9a6adcb3bee64452e9 >OK This generates 24 random bytes. Initially no key is created. You can create an ED25519 key by giving it the name ed1 >admin> createKey ed1 ED25519 >OK You can display the list of existing keys: >admin> keys >- ed1: Tue, 17 Mar 2026 17:44:36 UTC; admin; ED25519 PRIVATE >OK With this key, you can for example sign the message "Foobar": >admin> sign ed1 "Foobar" >1e67a70f41784b804a8550c57ce6b9a04f7011e2c563433f73b83fa82e19c8fe343ca49ee7056342a7dba86d9994bd91e01340759a9505428e01a93af436980b >OK You can verify it (the * character means "the last result", which here is the signature above) >admin> verify ed1 "Foobar" * >YES >OK The hsm replies 'YES' which means the signature is correct. But the MAIN command is 'man' which displays the manual. >admin> man When called without an argument it displays the main page of the manual. It can be used with a command name or a topic name, for example: >admin> man createKey >------------------ > >createKey KEY_NAME TYPE [OPTION] > >Create a key with KEY_NAME and TYPE. See command 'keyTypes' to list the supported types. >OPTION depends on the type: >- AES: OPTION is the size of the key (128, 192, 256). Default is 256. >- EC : OPTION is the name of the elliptic curve. Default is secp256r1. >- RSA: OPTION is the size of the key. Default is 1024. > >Required rights: >- /admin/keys/create > >OK There are also several topics that detail usage and configuration: >- intro : get started >- connect : connection modes >- accounts : user management >- rights : right management >- crypto : common operations >- output : how to format the output >- config : configuration >- advanced : advanced topics For example, simply type: >admin> man crypto #Configuration Configuration is done in the file hsm.config.mcy. Configuration files in Minimacy are preferably written in the Minimacy language: - a single language for everything - it is compiled when you launch the application, so its syntax is checked - you have access to the language's computation functions const HOST_USER="foobar";; // on linux-like system, the hsm will switch to this use account as soon as http and ssh server are started. const CONSOLE_ENABLED=true;; const HTTP_ENABLED=false;; const HTTP_MAX_CONNECTIONS=16;; const HTTP_IDLE_TIMEOUT=30;; const HTTP_EVICTION_TIMEOUT=10;; // HTTPS server: //const HTTP_ADDR="0.0.0.0";; //const HTTP_PORT=8443;; //const TLS_SERVER_KEY="foobar.com.key.pem";; //const TLS_SERVER_KEY_PWD= "";; //const TLS_SERVER_CER="foobar.com.cer.pem";; //const TLS_LOGIN_CER="loginAuthority.cer.pem";; // HTTP server: const HTTP_ADDR="0.0.0.0";; const HTTP_PORT=8080;; const TLS_SERVER_KEY="";; const TLS_SERVER_KEY_PWD= "";; const TLS_SERVER_CER="";; const TLS_LOGIN_CER="";; const SSH_ENABLED=false;; const SSH_ADDR="0.0.0.0";; const SSH_PORT=1234;; const SSH_SERVER_KEY="ed25519_private.pem";; //openssl genpkey -algorithm ed25519 -out ed25519_private.pem const SSH_SERVER_KEY_PWD="";; const SSH_MAX_CONNECTIONS=16;; const SSH_IDLE_TIMEOUT=60*10;; const SSH_EVICTION_TIMEOUT=10;; If you set HTTP_ENABLED=true, you immediately have access via http on port 8080. For https access, you will need to provide: - the certificate foobar.com.cer.pem obtained from a certificate authority - the private key foobar.com.key.pem linked to your certificate, along with the password if the pem file is encrypted - for client authentication by SSL certificate, you must also provide the certificate of the certification authority To enable SSH, you must set SSH_ENABLED=true, but you must also create an SSH key for the server and give it a name such as 'ed25519_private.pem' You can use openssl to generate such a file: >openssl genpkey -algorithm ed25519 -out ed25519_private.pem Once the configuration has been modified, you must restart the application for the changes to take effect. #Boot details We will not go through the application source code in detail, but here is an explanation of the boot.mcy file, which enables the application to be launched on different platforms. When Minimacy runs on top of an operating system, the network has already been configured and is ready to use. In bare-metal, things are different: you must configure the network yourself. Every Minimacy host defines a specific constant ending in 'Device': WindowsDevice, UnixDevice, MacOsCmdLineDevice, ... For the MM-2350 board it is 'MM2350Device', for the Raspberry Pi 4 board it is 'RPi4Device'. The boot.mcy file contains three blocks: for MM-2350, for Raspberry Pi 4, and for any other host. Here is the MM-2350 block: use core.net.ipOverEth;; use baremetal.mm2350.boot;; use driver.generic.display;; const IP="169.254.1.1";; const LOGO= strFromLzw(strFromHex(strBuild([ "ffe0012058d0204181071502f8036ee1c1860f0dfe18289120458b043fe0cb0860230040100811801012c38078011e700406c310c996180c6450c90f00383887", "48e2248120c0a003364141294408c250121800183be00f002c68848841802a04020036039c668244880804ae5601e018f00f4022916420a01d76154200b38f44", "d28020f79fd2b7ff001912c90182a108811001b8aa3724210625230030840182807fc00e93043401c03078100cfc0196d141448b0c7e38b4c801a3451e1f2a4a", "f4f3d1e2bf1f362db6e6683120" ])), nil);; fun uiInit()= uiStart(0, 0, 128, 64, nil, "MiniHSM"); drawBitmap(8, 0, LOGO, 112); drawStringCenter(76, 22, "Less is more", false); drawStringRight(128, 39, strFormat("* ETH ->",IP), false); bitmapFillRectangle(uiBuffer(), 0, 55, nil, nil, 0xffffff, nil); drawStringCenter(64, 56, "2025 - MiniHSM - SH", true); uiUpdate();; fun main ()= uiInit(); netStatic(netUp(ETH_RIGHT), IP, "255.255.0.0", nil, nil); start("hsm");; The main() function first uses uiInit() to display a visual on the MM-2350 board's screen, whose purpose is to indicate the IP address and, with the arrow, which Ethernet port to use. [](html) The logo is displayed using the function drawBitmap(x, y, data, width), which takes as its 'data' argument a string where each bit indicates whether a pixel is on or off, scanning each line from left to right and top to bottom, in big-endian order. To reduce the size of data, it has been compressed with LZW. The LOGO definition starts from the hexadecimal representation of the compressed image. strBuild() is applied to concatenate the lines, then strFromHex to retrieve the binary value, and finally strFromLzw to retrieve the raw image data, whose first lines, containing the top of the logo, are: >fff0000000000000000000000000 >fff0000000000000000000000000 >7fe0000000000000000000000000 >7fe0000000000000000000000000 >3ff0000000000000000000000000 >... Then the main() function configures the "right" port with a static IP. Then the hsm application is launched, i.e. the file hsm.mcy. The Raspberry Pi 4 block simply initialises the network layer. Since the miniHsm application acts as a server, a static IP configuration is preferred. Then the hsm application is launched, i.e. the file hsm.mcy. #elifdef RPi4Device use core.net.ipOverEth;; fun main() = netStatic(netUp("eth0"), "169.254.1.1", "255.255.0.0", nil, nil); start ("hsm");; Finally, for hosts with an operating system, we simply launch the hsm application, i.e. the file hsm.mcy. #else fun main ()= start("hsm");; #endif