Staticman's Encryption Mechanism

Verify encrypted content


Staticman’s documentation gives a link to the public key for the public Staticman instance.

I’ve set up my own Staticman instance for testing Staticman’s native GitLab support. It’s a coincidence that the public Staticman instance has been hitting it’s API limit, as reported in Staticman issue 227. To help others, I’ve published the URL of my own Staticman instance, which is associated with the GitHub/GitLab user staticmanlab. As Node.js’s RSA library has been used in Staticman, I have the responsibility to publish the public RSA key for my Staticman instance.

Before releasing my public key, I have to verify that public key stored in the local repository is the right one. To avoid breaking things, I conducted the testing in the local repository for my public Staticman instance for Framagit.


  1. Generate the RSA public key from my private one.
  2. Test my Staticman instance’s encryption endpoint by locally decrypting a test message "test".
  3. Publish the key generated in step 1.

In a web browser, opening the following link gives an encrypted text.



N.B. Although the encryption algorithm itself is deterministic, its implementation includes OAEP, in which a random sequence of zero bits is appended to the message. Consequently, OpenSSL’s RSA encryption tool gives different results for the same input. The above output is just my observation, and it can never be reproduced.


After having generated a public key from the private RSA key created by OpenSSL, I was unable to decrypt the message encrypted online by my Staticman instance for Framagit.

$ openssl rsa -in staticman_key -pubout -out
$ cat > text.enc # save Staticman's encrypted text into "text.enc"
$ cat text.enc | openssl rsautl -decrypt -inkey staticman_key            
RSA operation error
140599129772480:error:0406506C:rsa routines:rsa_ossl_private_decrypt:data greate
r than mod len:../crypto/rsa/rsa_ossl.c:401:


The above error is due to an encoding mismatch. Statimcan encrypts a string into a base64 string, whereas

$ openssl rsautl -encrypt -pubin -in msg -out msg.enc

produces a binary file from the input text file msg. Therefore, to use OpenSSL’s RSA decrytion utility, the encrypted message text.enc has to be decoded into binary data from base64 first.

Then, I encountered another error.

$ cat text.enc | base64 -d | openssl rsautl -decrypt -inkey staticman_key            
RSA operation error
139653142688192:error:0407109F:rsa routines:RSA_padding_check_PKCS1_type_2:pkcs
decoding error:../crypto/rsa/rsa_pk1.c:241:
139653142688192:error:04065072:rsa routines:rsa_ossl_private_decrypt:padding che
ck failed:../crypto/rsa/rsa_ossl.c:487:

Defacing text.enc would not reproduce the above RSA padding check error. To get the same error message, I generated another private RSA key with OpenSSL and fed it to -inkey. It seemed that I had used the wrong private RSA key staticman_key for testing. Nonetheless, heroku config:get RSA_PRIVATE_KEY returned the same key. To be 100% sure of that, I had saved the it into a temporary file, I ran diff -u and got nothing.


It’s clear that the parsing of the private RSA key caused the error. Staticman’s source code in Node.js provides no clue for that. Finally, by searching “ssh key decryption”, I found the missing flag -oaep in Bjørn Johansen’s file encryption guide.

Hence, the command to decrpyt Staticman’s encrypted string is

$ cat text.enc | base64 -d | openssl rsautl -decrypt -oaep -inkey staticman_key
test% # '%' indicates the absence of newline '\n' at the end in Zsh


The public RSA key generated from openssl rsa -pubout matches the private key staticman_key. The former is now ready to be committed into the Git repository.

You may view the public keys for

No comment