Recovering a private key without MicroB2B
This page shows how to get a certificate’s private key back with OpenSSL alone. Use it when MicroB2B cannot run, or when you must move a key to another product.
MicroB2B never stores a private key in the clear. It encrypts each key with the master key, SECRETS_KEY. To recover a key, you need two things:
- the database, or a backup of it
- the master key that the key was encrypted with
Without the master key, the private key cannot be recovered. See secrets for how to keep the master key safe.
What you need
- OpenSSL 3
bash,base64,od,trandcut- a shell on a safe machine, away from where the database is kept
A test runs the commands on this page against a key that MicroB2B encrypted. So they match what this version of MicroB2B does.
Step 1: Find the certificate’s ID
Open the certificate in the web UI. Its ID is the number in the address: /ui/certificates/<id>. If the web UI does not run, list the certificates from the database:
sqlite3 microb2b.db "SELECT id, description FROM certificates"Step 2: Read the key from the database
The table certificates holds two columns for a certificate with a private key:
| Column | What it holds |
|---|---|
private_key_bytes | The encrypted key, a PEM that starts with -----BEGIN ENCRYPTED PRIVATE KEY----- |
private_key_kid | The ID of the master key it was encrypted with: 8 lowercase hex characters |
Write the key to key.pem and keep the key ID in KID. With SQLite, for certificate 3:
sqlite3 microb2b.db "SELECT private_key_bytes FROM certificates WHERE id = 3" > key.pem
KID=$(sqlite3 microb2b.db "SELECT private_key_kid FROM certificates WHERE id = 3")With PostgreSQL, use psql "$DB_URL" -At -c "<the same SELECT>" instead.
Step 3: Set the master key
Set SECRETS_KEY to the master key, exactly as MicroB2B is configured with it:
SECRETS_KEY='<the base64 master key>'If MicroB2B reads the key from a file (SECRETS_KEY_FILE), use SECRETS_KEY=$(cat <that file>).
If your key is written in hex, not base64, set MASTER_KEY to the hex value instead. Then skip the first line of the commands in step 4.
Step 4: Decrypt the key
Run these commands in the directory where key.pem is:
MASTER_KEY=$(printf '%s' "$SECRETS_KEY" | base64 -d | od -An -tx1 | tr -d ' \n')
# The key id of this master key: it must be the row's private_key_kid.
printf '%s' 'microb2b secret key id' | openssl dgst -sha256 -mac HMAC -macopt hexkey:"$MASTER_KEY" -r | cut -c1-8
PASSWORD=$(openssl kdf -keylen 32 -kdfopt digest:SHA256 -kdfopt hexkey:"$MASTER_KEY" \
-kdfopt info:'microb2b private key v1' HKDF | tr -d ':' | tr 'A-F' 'a-f')
openssl pkcs8 -in key.pem -passin pass:"$PASSWORD" -out recovered.pemThe commands do three things:
- They turn the master key into hex.
- They print the ID of this master key.
- They work out the key’s password from the master key, and decrypt
key.pemintorecovered.pem.
Step 5: Check the result
Compare the printed key ID with KID.
- They are the same.
recovered.pemis the private key, as an unencrypted PKCS#8 PEM. Most products import this format. - They differ. This is not the master key the row was encrypted with. During a key rotation, the row may name an earlier key. Try each key from
SECRETS_PREVIOUS_KEYSin step 3.
If openssl pkcs8 fails with a decryption error, the master key is wrong, or key.pem is not complete. Check that key.pem starts with -----BEGIN ENCRYPTED PRIVATE KEY----- and ends with the matching END line.
Protect the recovered key. recovered.pem is not encrypted. Keep it and the master key away from the database and its backups. Delete recovered.pem when you no longer need it.
How the password is made
You only need this to write your own tool. Everything is derived from the 32 bytes of the master key:
| Value | How it is made |
|---|---|
| Key ID | The first 4 bytes of HMAC-SHA256(master key, microb2b secret key id), as 8 lowercase hex characters |
| Password | HKDF-SHA256 of the master key, empty salt, info microb2b private key v1, 32 bytes, as 64 lowercase hex characters |
The PEM is encrypted with PBES2, using PBKDF2-HMAC-SHA256 and AES-256-CBC. This is what openssl pkcs8 -topk8 -v2 aes-256-cbc -v2prf hmacWithSHA256 writes. The salt, iteration count and IV are in the PEM itself.
Other secrets
MicroB2B also encrypts the secret values of its configuration: passwords, header values, signing secrets and webhook URLs. This page does not cover them. If you lose one, enter it again.