Synced from upstream — do not edit this file directly
This page is generated from
CARSSCenter/OpenNerve-Implantable-Pulse-Generator at Docs/encryption-instructions.md as of commit 7ab3cd3.
To change it, edit the file upstream and re-run tools/sync_docs.py.
Use the "Edit this page" link above to go straight to the upstream source.
OpenNerve encryption overview v0.2¶
Alex Baldwin Jan 20 2026
Summary¶
The OpenNerve IPG uses public-key cryptographic authentication (ECDSA P-256) to validate any control software. This means that the MCU firmware running on the STM32 microcontroller hosts public keys for Admin (developer), Clinician, and Patient permission states; a user’s software must send the matching private key over BLE during the startup sequence to grant the ability to apply stimulation, modify parameters, or stream data. While the public keys can be released (e.g. in open source repositories) with no security risks, the corresponding private keys MUST be kept secure and private to prevent unauthorized modification of the OpenNerve device. For your convenience we have generated a “development” private key / public key pair; the public keys can be found in the MCU firmware (see below) and the private keys are available upon request. We recommend that any new users create their own public/private key pairs before developing a device based on OpenNerve for any new clinical application.
In the current version of OpenNerve’s software and firmware, the software must send an authorization command using the format described below. The steps that the software uses to generate the different payload components are as follows: * Hash message: the software takes a string input, in OpenNerve’s case a short message plus a random number, and generates a 32 byte hash using SHA-256 * ECDSA signatures part r and s: after generating the hash, the software will “sign” it using the private key as read from a text file. The signature is generated by the .NET function’s ECDSA.SignHash() function found in System.Security.Cryptography. * Warning: the private key should NEVER be included in the software code itself, or in a file that is indexed by git. Right now, OpenNerve’s Windows App reads the private key from the following file: "(root directory)\secrets\admin_priv_d_hex.text". The “secrets” folder is excluded from git via instructions in the .gitignore file. The path can be changed by adjusting the private_key_path variable. * CRC16: this is an automatic checksum that the software automatically adds to any BLE message before transmission. It does not count as part of the payload.
Limitations¶
One important limitation of the current encryption scheme is that, while each authorization request will be different due to the random hashing and signing, the current version of firmware will accept any request that it cryptographically determines is valid. This means that if someone records or “sniffs” a valid authorization request they will be able to re-use it in the future. One improvement which would fix this vulnerability would be to include a “used key” list in firmware, such that a device will reject a hash + signature pair if it is used more than once.
Generation of Public/Private Keys and Firmware Modification¶
One easy way to generate keys is using OpenSSL, a free and open source cryptography tool. For Mac or Linux users this tool is already installed; for Windows users you will need to install OpenSSL from one of the many online installation sites or from the OpenSSL foundation’s GitHub repository (https://github.com/openssl/openssl/releases). The following terminal / command prompt commands can then be used to generate a new set of public and private admin keys for your application. The same commands (with different output filenames) can be used to generate clinician and patient keys.
- Generate a P-256 private key: openssl ecparam -name prime256v1 -genkey -noout -out admin_priv.pem
- Extract a public key from this private key: openssl ec -in admin_priv.pem -pubout -out admin_pub.pem
- Print both keys to terminal: openssl ec -in admin_priv.pem -pubout -text -noout
The private key is generated with leading zeroes. To update the text file, remove the first two zeroes and all colons / spaces / newline characters, and put all 32 bytes on a single line. To modify firmware to use your new public key / private key pair, you will need to update the variables APP_ECC_PUBKEY_QX_ADMIN and APP_ECC_PUBKEY_QY_ADMIN with your new public keys. These variables can be found in the file ecc_publickey.h in the App/Config folder of the MCU firmware’s source code. To get these variables, take the public key generated using OpenSSL and drop the leading “04” byte. Then, the first 32 bytes correspond to QX and the second 32 bytes correspond to QY.
Clinician/Patient vs Admin keys¶
Clinician/Patient keys are processed differently from the Admin key. While the Admin public keys are stored in firmware and cannot be changed once a board is flashed, the Clinician and the Patient keys are loaded from firmware to flash memory during the board’s first use and can be modified over BLE if a user has authenticated to Admin mode. When attempting to authenticate using a Patient/Clinician private key, the firmware will check the public keys stored in flash, not the ones hard-coded into firmware. Both the Admin public key and the Clinician/Patient public keys can be found in the ecc_publickey.h file.
The following op codes can be used in software to modify the Clinician key (CRC) and the Patient key (PRC), once Admin privilege has been established.