
# Django Tink Fields

Leverages [Google Tink](https://developers.google.com/tink) to encrypt Django's core model fields. This work is heavily based on the work of [Django Fernet Fields](https://github.com/orcasgit/django-fernet-fields) which seems to have been abandoned last few years.

## Installation

Use `pip` to install `django-tink-fields`:

```bash
  pip install django-tink-fields
```

Edit `settings.py` and introduce a configuration section for `TINK_FIELDS_CONFIG`:

```python
TINK_FIELDS_CONFIG = {
    "default": {
        "cleartext": False,
        "path": "/path/to/an/encryted_keyset.json",
    },
    "another": {
        "cleartext": True,
        "path": "/path/to/a/cleartext_keyset.json",
    }
}
```

Tink keysets can be created via `tinkey`, and may optionally be wrapped via a key-management system such as `AWS KMS` or `GCP KMS`.

To create a cleartext keyset for testing purposes:

```bash
tinkey create-keyset --out-format json --out test_plaintext_keyset.json --key-template AES128_GCM
```

Alternatively, to create an encrypted keyset that is wrapped by `GCP KMS`, specify `--master-key-uri` as follow:

```bash
tinkey create-keyset --out-format json --out test_encrypted_keyset.json --key-template AES128_GCM --master-key-uri=gcp-kms://projects/foo1/locations/global/keyRings/foo2/cryptoKeys/foo3
```

To learn more about `tinkey` [read the relevant documentation](https://github.com/google/tink/blob/master/docs/TINKEY.md)

## Examples

The following model creates an encrypted char field that makes use of the `default` keyset.

```python
from django.db import models
from tink_fields import EncryptedCharField

class SomeModel(models.Model):
    some_value = EncryptedCharField(max_length=32)

```

You may specify the keyset by specifying a `keyset` keyword argument:

```python
from django.db import models
from tink_fields import EncryptedCharField

class AnotherModel(models.Model):
    some_value = EncryptedCharField(max_length=32, keyset="another")

```

Other field types include: `EncryptedCharField`, `EncryptedTextField`, `EncryptedDateField`, `EncryptedDateTimeField`, `EncryptedEmailField`, and `EncryptedIntegerField`.

### Associated Data

The encrypted fields make use of `Authenticated Encryption With Associated Data (AEAD)` which offers confidentiality and integrity within the operation. This allows the caller to specify a cleartext fragment named `additional authenticated data (aad)` to the encryptiona and decryption operation, and receive guarantees that the associated data has not been tampered with.

To specify the `aad`, provide a callback function `aad_callback` in the keyword arguments:

```python
from django.db import models
from tink_fields import EncryptedCharField

class AnotherModel(models.Model):
    some_value = EncryptedCharField(max_length=32, aad_callback=lambda x: b"some value")

```

The value passed to the callback is the instance of the model field, with a signature of `Callable[[models.Field], bytes]`.

## Acknowledgements

- [Google Tink](https://github.com/google/tink/blob/master/docs/PYTHON-HOWTO.md)
- [Django Fernet Fields](https://github.com/orcasgit/django-fernet-fields)

## Authors

- [@script3r](https://www.github.com/script3r)
