-
Notifications
You must be signed in to change notification settings - Fork 123
Crypto tutorial #1955
Crypto tutorial #1955
Changes from 15 commits
db0a8e3
ef60fd5
cd5e48e
a484bdc
6b846a3
42e2e33
1e0c5e2
fab1b5a
4bb95aa
6cecc56
00481d3
9019088
f53cbe9
bdbefda
95dc360
3bae912
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,275 @@ | ||
# Cryptographic Methods in Elektra | ||
|
||
Elektra can protect the following aspects of your configuration: | ||
|
||
1. confidentiality (i.e. protection against unauthorized access), and | ||
2. integrity (i.e. protection against unauthorized modification). | ||
|
||
Elektra provides two plugins to achieve this protection: | ||
|
||
1. `crypto`, and | ||
2. `fcrypt`. | ||
|
||
## Prerequisites - GnuPG | ||
|
||
For the rest of this tutorial we assume that you are somewhat familiar with GnuPG (GPG). | ||
The documentation of GnuPG can be found [here](https://gnupg.org/documentation/index.html). | ||
|
||
In order to find your GPG private key(s) you can use: | ||
|
||
gpg2 --list-secret-keys | ||
|
||
If GPG private keys are available, you see an output, that looks similar to this: | ||
|
||
sec rsa1024 2016-08-20 [SC] | ||
DDEBEF9EE2DC931701338212DAF635B17F230E8D | ||
uid [ultimate] Elektra Unit Tests (DO NOT USE IN PRODUCTION) <[email protected]> | ||
ssb rsa1024 2016-08-20 [E] | ||
|
||
The GPG key we use in this tutorial has the ID `DDEBEF9EE2DC931701338212DAF635B17F230E8D`. | ||
|
||
A GPG private key is mandatory for the plugins to work. | ||
If you have no GPG private key available, you can generate one by entering the following command: | ||
|
||
gpg2 --generate-key | ||
|
||
The `fcrypt` plugin and the `crypto` plugin support both versions (version 1 and version 2) of GPG. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible to intermix them? Which will be preferred? |
||
|
||
In order to set up our tutorial we import the Elektra test key. | ||
We **DO NOT RECOMMEND** to use our key on your local machine, as it is available to the public! | ||
|
||
```sh | ||
gpg2 --import src/plugins/crypto/test_key.asc || gpg --import src/plugins/crypto/test_key.asc | ||
echo "trust-model always" > ~/.gnupg/gpg.conf | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this line is quite dangerous. This command just overwrote my local GPG configuration. |
||
``` | ||
|
||
## Introduction | ||
|
||
In this tutorial we explain the use of the `crypto` plugin and the `fcrypt` plugin by a simple example: | ||
We want to protect a password that is contained in an INI-file. | ||
|
||
The following example demonstrates how the INI-file is mounted without encryption enabled. | ||
We create the password at `user/test/password` and display the contents of `test.ini`. | ||
|
||
*Step 1:* Mount `test.ini` | ||
|
||
```sh | ||
kdb set /sw/elektra/kdb/#0/current/plugins "" | ||
sudo kdb mount test.ini user/test ini | ||
``` | ||
|
||
*Step 2:* Set the password at `user/test/password` and display the contents of `test.ini` | ||
|
||
```sh | ||
kdb set user/test/password 1234 | ||
#> Create a new key user/test/password with string "1234" | ||
kdb file user/test/password | xargs cat | ||
#> password = 1234 | ||
``` | ||
|
||
*Step 3:* (Optional) Cleanup | ||
|
||
```sh | ||
kdb rm user/test/password | ||
kdb rm /sw/elektra/kdb/#0/current/plugins | ||
sudo kdb umount user/test | ||
``` | ||
|
||
As you can see the password is stored in plain text. | ||
In this tutorial we demonstrate two different approaches towards confidentiality: | ||
|
||
1. with the `fcrypt` plugin, which encrypts the entire INI-file, and | ||
2. with the `crypto` plugin, which allows the encryption of specific key values only. | ||
|
||
We also show how to approach integrity with the signature features of the `fcrypt` plugin. | ||
|
||
## Configuration File Encryption/Decryption | ||
|
||
The `fcrypt` plugin enables the encryption and decryption of entire configuration files, thus protecting the confidentiality of the configuration keys and values. | ||
`fcrypt` utilizes GPG for all cryptographic operations. | ||
The GPG key, which is used for encryption and decryption, is specified in the backend configuration under `encrypt/key`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is too fast. It is not clear what the tutorial is about. What is a backend configuration? (maybe avoid the term altogether) |
||
|
||
sudo kdb mount test.ini user/test fcrypt "encrypt/key=DDEBEF9EE2DC931701338212DAF635B17F230E8D" ini | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This command fails if we start with an empty configuration:
. I would add something like this: If the above command fails, please take a look at the
[ReadMe of the `fcrypt` plugin](https://master.libelektra.org/src/plugins/fcrypt/README.md#known-issues). . |
||
|
||
If the above command fails, please take a look at the | ||
[ReadMe of the `fcrypt` plugin](https://master.libelektra.org/src/plugins/fcrypt/README.md#known-issues). | ||
|
||
As a result the file `test.ini` is encrypted using GnuPG. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At the moment the file was not even written, it might not even exist (no kdb set up to now). And even if it exist, what would happen with the plain text file present there before? |
||
`fcrypt` will call the `gpg2` or `gpg` binary as follows: | ||
|
||
gpg2 -o test.ini -a -r DDEBEF9EE2DC931701338212DAF635B17F230E8D -e test.ini.tmp | ||
|
||
Note that `test.ini` can not only be decrypted by Elektra, but it is also possible to decrypt it with GnuPG directly. | ||
You can try to decrypt `test.ini` with GPG: | ||
|
||
gpg2 -d test.ini | ||
|
||
The complete procedure looks like this: | ||
|
||
```sh | ||
kdb set /sw/elektra/kdb/#0/current/plugins "" | ||
sudo kdb mount test.ini user/test fcrypt "encrypt/key=DDEBEF9EE2DC931701338212DAF635B17F230E8D" ini | ||
kdb set user/test/password 1234 | ||
#> Create a new key user/test/password with string "1234" | ||
kdb file user/test/password | xargs cat | ||
``` | ||
|
||
To clean up the environment we run: | ||
|
||
```sh | ||
kdb rm user/test/password | ||
kdb rm /sw/elektra/kdb/#0/current/plugins | ||
sudo kdb umount user/test | ||
``` | ||
|
||
## Configuration File Signatures | ||
|
||
`fcrypt` also offers the option to sign and verify configuration files, thus protecting the integrity of the configuration values. | ||
If `sign/key` is specified in the backend configuration, `fcrypt` will forward the key ID for signing the configuration file. | ||
|
||
An example backend configuration is given as follows: | ||
|
||
sudo kdb mount test.ini user/test fcrypt "sign/key=DDEBEF9EE2DC931701338212DAF635B17F230E8D" ini | ||
|
||
As a result the file `test.ini` will be signed using GPG. | ||
`fcrypt` will call the `gpg2` or `gpg` binary as follows: | ||
|
||
gpg2 -o test.ini -a -u DDEBEF9EE2DC931701338212DAF635B17F230E8D -r DDEBEF9EE2DC931701338212DAF635B17F230E8D -s test.ini.tmp | ||
|
||
If `test.ini` is modified, all following calls of `kdb get` will fail with an error message stating that the signature of the file could not be verified. | ||
|
||
The complete example looks like this: | ||
|
||
```sh | ||
kdb set /sw/elektra/kdb/#0/current/plugins "" | ||
sudo kdb mount test.ini user/test fcrypt "sign/key=DDEBEF9EE2DC931701338212DAF635B17F230E8D" ini | ||
kdb set user/test/password 1234 | ||
#> Create a new key user/test/password with string "1234" | ||
kdb file user/test/password | xargs cat | ||
``` | ||
|
||
To clean up the environment we run: | ||
|
||
```sh | ||
kdb rm user/test/password | ||
kdb rm /sw/elektra/kdb/#0/current/plugins | ||
sudo kdb umount user/test | ||
``` | ||
|
||
### Combining Signatures and Encryption | ||
|
||
The options `sign/key` and `encrypt/key` can be combined together, resulting in configuration files, that are signed and encrypted. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please example. Is there some shortcut if it is two times the same key? Is it allowed to use two different keys? |
||
|
||
Mounting `test.ini` with signatures and encryption enabled can be done like this: | ||
|
||
sudo kdb mount test.ini user/test fcrypt "sign/key=DDEBEF9EE2DC931701338212DAF635B17F230E8D,encrypt/key=DDEBEF9EE2DC931701338212DAF635B17F230E8D" ini | ||
|
||
The complete example looks like this: | ||
|
||
```sh | ||
kdb set /sw/elektra/kdb/#0/current/plugins "" | ||
sudo kdb mount test.ini user/test fcrypt "sign/key=DDEBEF9EE2DC931701338212DAF635B17F230E8D,encrypt/key" ini | ||
kdb set user/test/password 1234 | ||
#> Create a new key user/test/password with string "1234" | ||
kdb file user/test/password | xargs cat | ||
``` | ||
|
||
To clean up the environment we run: | ||
|
||
```sh | ||
kdb rm user/test/password | ||
kdb rm /sw/elektra/kdb/#0/current/plugins | ||
sudo kdb umount user/test | ||
``` | ||
|
||
|
||
## Configuration Value Encryption/Decryption | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We already know how to encrypt/decrypt files, why does the tutorial continue. Maybe say something about that often only a single password should be protected or similar convincing use cases. |
||
So far we learned how to encrypt and decrypt entrie configuration files. | ||
Sometimes we only want to protect a smaller subset of configuration values in a bigger configuration setting. | ||
For this reason the `crypto` plugin was developed. | ||
|
||
The `crypto` plugin is actually a family of plugins and comes with three different providers: | ||
|
||
1. `crypto_gcrypt` using `libgcrypt`, | ||
2. `crypto_openssl` using `libcrypto`, and | ||
3. `crypto_botan` using `Botan`. | ||
|
||
We recommend that you use `crypto_gcrypt` as it is the fastest variant. | ||
The variants of the `crypto` plugin work the same internally, but use a different crypto library for cryptographic operations. | ||
|
||
The `crypto` plugins provide the option to encrypt and decrypt single configuration values (Keys) in a Keyset. | ||
GPG is required for the key-handling. | ||
|
||
To follow our example of an encrypted password in `test.ini`, we first mount the INI-file with the `crypto_gcrypt` plugin enabled, like this: | ||
|
||
sudo kdb mount test.ini user/test crypto_gcrypt "crypto/key=DDEBEF9EE2DC931701338212DAF635B17F230E8D" base64 ini | ||
|
||
We recommend adding the `base64` plugin to the backend, because `crypto` will output binary data. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not recommend it in the contract? Then simply pass --with-recommends in the command above. |
||
Having binary data in configuration files is hardly ever feasible. | ||
`base64` encodes all binary values within a configuration file and transforms them into Base64 strings. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Small example: what are base64 strings |
||
|
||
### Marking Keys For Encryption | ||
|
||
To tell the `crypto` plugin which Keys it should process, the meta-key `crypto/encrypt` is used. | ||
The `crypto` plugin searches for the meta-key `crypto/encrypt`. | ||
If the value is equal to `1`, the value of the Key will be encrypted. | ||
|
||
We want to protect the password, that is stored under `user/test/password`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again: a more concrete example would be more interesting. |
||
So we set the meta-key as follows: | ||
|
||
kdb setmeta user/test/password crypto/encrypt 1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does it also work if you do everything with cascading keys (without user). (And thus writing to spec) |
||
|
||
Now we are safe to set the actual password: | ||
|
||
kdb set user/test/password "1234" | ||
|
||
The resulting INI-file contains the following data: | ||
|
||
#@META crypto/encrypt = 1 | ||
password = @BASE64IyFjcnlwdG8wMBEAAADwPI+lqp+X2b6BIfLdRYgwxmAhVUPurqkQVAI78Pn4OYONbei4NfykMPvx9C9w91KT | ||
|
||
You can access the password as usual with `kdb get`: | ||
|
||
kdb get user/test/password | ||
|
||
As a result you get "1234". | ||
|
||
### Disabling Encryption | ||
|
||
You can disable the encryption by setting `crypto/encrypt` to a value other than `1`, for example: | ||
|
||
kdb setmeta user/test/password crypto/encrypt 0 | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Always demonstrate that what you said actually happened (cat the file or grep for the value) |
||
### Complete Example | ||
|
||
The complete example looks like this: | ||
|
||
```sh | ||
kdb set /sw/elektra/kdb/#0/current/plugins "" | ||
sudo kdb mount test.ini user/test crypto_gcrypt "crypto/key=DDEBEF9EE2DC931701338212DAF635B17F230E8D" base64 ini | ||
kdb setmeta user/test/password crypto/encrypt 1 | ||
kdb file user/test/password | xargs cat | ||
kdb set user/test/password 1234 | ||
#> Set string to "1234" | ||
kdb set user/test/config "I am not encrypted" | ||
#> Create a new key user/test/config with string "I am not encrypted" | ||
kdb file user/test/password | xargs cat | ||
``` | ||
|
||
To disable encryption on `user/test/password`, we can run: | ||
|
||
```sh | ||
kdb setmeta user/test/password crypto/encrypt 0 | ||
kdb file user/test/password | xargs cat | ||
``` | ||
|
||
To clean up the environment we run: | ||
|
||
```sh | ||
kdb rm user/test/config | ||
kdb rm user/test/password | ||
kdb rm /sw/elektra/kdb/#0/current/plugins | ||
sudo kdb umount user/test | ||
``` | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also for checking signatures?