Based OTP application with two state gen_statem, proof of concept for using asymeric file encryption with openssl, OTP crypto and OTP public_key.
We have a public facing Erlang server that has to log some sensitive clients information (in example GDPR, HIPAA or GLBA protected). In case of a hostile agent get access to the server we do not want it to read our clients data. Unfortunatelly public_key:encrypt_private/2 function and other similar are deprecated in OTP. We can use sign and verify, but those functions guarantee only integrity and not confidentiality.
We create a public key cryptosystem. The public key is used by the server to encrypt sensitive records. The private key is stored in air-gapped server in case we need to read those data from the logs. We create our own Elliptic Curve Integrated Encryption Scheme (ECIES), based on this notebook.
- Use openssl to create a private/public key pair.
- Store the private key (PvKI) in an isolated machine and the public key PuKI kept on server.
- Create an ephermal private server key (PvSK) and connected public key (PuSK) withing erlang server. Use crypto:generate_key/2
- When sensitive data has to be logged the data is encrypted with a secret created from PvSK and PuKI plus additional data like Initiation Vector, Salt etc are used to encrypt information. The PuSK, IV, Salt, but not PvSK need to be provided in the logs. Use crypto:crypto_one_time/5
- The PvSK should be deleted and regenerated after encryption or at least every specified time.
- If there is needs to decrypt data, it should be copied to the isolated machine, and there logged PuSK, IV, Salt, and PvKI can be used to recreate shared secret and decrypt sensitive information. Use for that: openssl pkeyutl -derive -inkey PvKI -peerkey PuSK -out secret openssl enc -d -base64
Details in the code.
scripts/clean.sh
Install erlang and rebar3 for example with asdf.
https://github.com/asdf-vm/asdf
https://github.com/asdf-vm/asdf-erlang
https://github.com/Stratus3D/asdf-rebar
$ rebar3 compile
scripts/generate.sh
$ rebar3 shell
> tracing_experiments:switch_state().
...
> tracing_experiments:switch_state().
> q().
cat logs/erlang.log
2024-08-20T07:49:27.333830+02:00 notice:
scripts/decrypt_logs.sh
2024-08-20T07:49:27.333830+02:00 notice:
14c0081fc339b8ced2099716e35663407b3699f5108fce60977ad1c2183f4e982024-08-20T07:49:27.336480+02:00 notice:
Done!