django-cryptography
django-cryptography copied to clipboard
Allow to rotate SECRET_KEY
Hi,
In a django project, I might need to rotate the SECRET_KEY.
However, when using the encrypt wrapper for the field, I can only override the CRYPTOGRAPHY_KEY which is used for encryption in FernetBytes, but not the SECRET_KEY used for the HMAC in FernetSigner.
Would it be possible to add an argument to the encrypt wrapper to be able to override the HMAC key ?
I hadn't seen this related issue here: https://github.com/georgemarshall/django-cryptography/issues/36.
However, the proposal of just adding an extra argument to the encrypt wrapper, and leave the rest up to the developer seems more flexible and much easier to implement. If needed, I can do a PR.
https://django-cryptography.readthedocs.io/en/latest/fields.html#django_cryptography.fields.encrypt
As I understand the code & the docs, the key argument of the encrypt field wrapper is then used as the first argument of FernetBytes, which is in turn used to override settings.CRYPTOGRAPHY_KEY.
However, the signing key cannot be set through the arguments of the encrypt field wrapper. When using the encrypt field wrapper, it uses the FernetSigner with no option, and the default key used within FernetSigner is settings.SECRET_KEY.
To rotate only the CRYPTOGRAPHY_KEY, I could use the key argument of the encrypt to set it manually to the value of the derived CRYPTOGRAPHY_KEY through the same PBKDF2 parameters as you do in the configuration.
However, I don't see a clear path to rotating SECRET_KEY properly, as it is used as the signing key in FernetSigner, and it seems it is not possible to override the signing key.
Am I mistaken?
If I wanted to properly rotate the SECRET_KEY with the current version of django-cryptography, I would need to do a migration in three steps:
- decrypt the data contained in the encrypted field and set it in clear text in a temporary field;
- rotate the
SECRET_KEYsetting; - re-set the clear text data contained in the temporary field in the new encrypted field.
This would leave the data in clear text temporarily in the database, which is a security issue.
What I suggest is to allow setting from the encrypt field wrapper a signing key, which would be used to override the SECRET_KEY in FernetSigner. This could then be used to:
- modify the existing field to use the current
SECRET_KEYas the signing key, the currentCRYPTOGRAPHY_KEYas the seed for the encryption key (with your PBKDF2 parameters); - rotate the keys in the settings & create a new encrypted field;
- make a migration where the data is decrypted from a field and re-encrypted in the other, without writing onto the databse the clear text data.
Key rotation via management command / settings config would be a very useful feature :heavy_plus_sign:
@tex0l were you planning on opening a PR in near future?
I was actually hoping @georgemarshall would agree with my suggestion first, and then if he does not have the time to make the modification himself, I would indeed make a PR. I don't want to fork without being sure it will be merged.
My PR would be dead simple: it would allow setting manually a key used in the FernetSigner as an argument of the encrypt wrapper (very much like the current key argument, used only in FernetBytes), a migration would be possible from that, but I wasn't planning to make a management command to do the rotation automatically.
@georgemarshall what do you think of my proposal?
@tex0l , do you think this help? https://cryptography.io/en/latest/fernet/#cryptography.fernet.MultiFernet
Key rotation is an enterprise requirement, if you can release a PR, that will be the best.
I need to deep dive again to reply to you. We solved the issue differently, I'll re-open the issue internally to see if we can prioritize resources on this in the coming weeks, but I doubt it.