Staticman's Encryption Mechanism

Verify encrypted content

Background

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.

TODO

  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.

GET https://staticman-frama.herokuapp.com/v3/encrypt/test

i6bxZBOCZYm4uPbBhyAL4Z42jYbWkeRWZk6Jefe4m01vFD8b4TtwDHOqs88EBMmpTd33EpgGlHsTA2D7FIox5a0+/2vAzZ1bQ2xQHknUY1mB7OI8TAbXYtr6ubJqhuH5c7QIAsn/qyt3ivYAZZUOzbvHxVCQsSnENeQYT19ZjtjvQs7lUXmSoDYuw3//J4VtnG1hWVlWa/gpkKAby9BmCEQEs4rca4CXlV+nnKdZID6Fe6xcca6Zp6WyYtxw5JfIeIGbQXNAZdSNsX4UJDXgPzNNe/ytndNucxKh+GEMqQxmlEkqq8QyL49HFRN3FjrjT6EcjU5v5McsWQWJuxaUBA==

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.

Problem

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 staticman_key.pub
$ 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:

Discussion

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

$ openssl rsautl -encrypt -pubin staticman_key.pub -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.

Solution

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

Conclusion

The public RSA key generated staticman_key.pub 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