created_at2024-04-17 02:57:11.921596
updated_at2024-04-23 21:45:21.550755
descriptionLibrary to encrypt/decrypt secrets
size32,798 (bestia-dev)




Library to encrypt/decrypt secrets
version: 1.1.7 date: 2024-04-23 author: repository: GitHub

rust maintained ready_for_use Documentation License Rust Hits

Lines in Rust code Lines in Doc comments Lines in Comments Lines in examples Lines in tests

Hashtags: #rustlang My projects on GitHub are more like a tutorial than a finished product: bestia-dev tutorials.


When we write an application, every connection to any server needs to work with secrets: passwords, passkeys, passcodes, passphrases, API secret_tokens and more.

Sometimes it is just fine to let the user type the password. Passwords are easy for humans to remember and type. But they are the least secure.

It is much better to have a long random "key" string like the API secret_token, but no human is capable of remembering that. It means we need to store it somewhere.

It is theoretically impossible to store this secret 100% securely using only software. Modern computers use special chips for that. But we can make it hard and not obvious for an attacker to get the secret.

GitHub API secret_token

The GitHub API secret_token is a secret just like a password. Maybe even greater.
With this API secret_token, a maleficent actor can change basically anything in your GitHub account. You don't want that.

How to protect this secret?
Ok, there are some basic recommendations:

  • Give the least permission/authorization to the API secret_token to minimize the harm an attacker can do
  • Expire the secret_token frequently, so old secret_tokens are of no use
  • HTTPS is a no-brainer. Never use HTTP ever again. It is plain text over the wire.
  • Never store the secret_token in a file as plain text
  • Plain text inside env vars can also be accessed from malware

Symmetric encryption

We will use encryption aes_gcm::Aes256Gcm for very short strings like API secret_tokens. So I suppose the performance is not a problem.
We use a passcode of 32 bytes to encrypt a string.
We can also enter a string password, that will be internally hashed into a 32-byte passcode.

Use SSH key to encrypt secret_token

We are accustomed to working with SSH keys because of Git and SSH connection to the web servers.
We already know how to create, secure and manage SSH keys. We know all about the private and public keys.
We know that the private key is secured by a passphrase.
We already know how to add an SSH key to ssh-agent. And we know that the use of ssh-agent makes life easier, but it has some security concerns. In most cases, this is not critical, but you have to choose your own balance between Convenience and Security.
All this knowledge is already mastered because of the workflow when developing in Rust.
We could use the same technique to encrypt the API secret_token.

We will use the private key to sign a random seed and the result will be a new super-secret passcode. The only way to get to this super-secret passcode is to sign the seed with the private key. We suppose that only the owner can sign with his/her private key. This is the basis of SSH key security.

The super-secret passcode will be used to symmetrically encrypt the secret_token and write it to a file as text. It is much simpler to work with text files.

Never commit secrets to your repository. GitHub is regularly scanned for uploaded secrets. That is a big no-no. I prefer to store the encrypted secret_token in the ~/.ssh directory near to other secret and encrypted keys.

Create an SSH key

It is recommended to encrypt every API secret_token with its dedicated SSH key. This way you have granular control over how to use it.

ssh-keygen -t ed25519 -C "github api secret_token"
# for test type these interactively:
# file name: tests/test_github_api_secret_token_ssh_1
# passphrase: test_passphrase
# repeat passphrase: test_passphrase

Balance between Convenience and Security

First thing first: it is theoretically impossible to secure a secret 100% only with software. If an attacker gets privileged or physical access to the computer, he can do anything. But that does not mean it is easy and quick. We can make it harder and harder to find a secret. Finally, we have to choose a balance between Convenience and Security.

You can choose to type the API key into the terminal every time. This is very inconvenient. You cannot remember the API key, you have to store it somewhere on the computer. And then use copy-paste. This is also a security concern. This secret_token will stay in the clipboard and that is easy to extract.

Never store secret_tokens in plain text. Nor in files nor environment variables. Files and env var are easy to upload to a malicious website. Use some kind of secret manager or encryption.

When the secret_token is encrypted with SSH, it must be decrypted using the private key. The private key is secured with a passphrase. This passphrase is easy to remember and type. You can choose to type the passphrase on every use of the secret_token. This is pretty secure but inconvenient.

Ultimately you can use ssh-agent to decrypt the private key only once typing the passphrase. It will work in the background for a specific time like 1 hour or until the end of the terminal session. This is not secure, because an attacker could use the same open-source code to extract the secret_token from ssh-agent in unencrypted form. But it is tricky to do and it is time-limited.

Just to mention the secret_token could be extracted from memory while in use. Or that the attacker could install a key logger and send all typed passwords and passphrases to a malicious website. There are really no limits to software exploits once the attacker has enough privilege.

Finally, your choice.

Open-source and free as a beer

My open-source projects are free as a beer (MIT license).
I just love programming.
But I need also to drink. If you find my projects and tutorials helpful, please buy me a beer by donating to my PayPal.
You know the price of a beer in your local bar ;-)
So I can drink a free beer for your health :-)
Na zdravje! Alla salute! Prost! Nazdravlje! 🍻


Commit count: 71

cargo fmt