Is there a way to DELETE an Encrypted Key

I’m currently working on a project where I plan to use encryption for securing tokens. These tokens are subject to frequent changes. My concern is about efficiently managing the encrypted keys. Specifically, I am looking for guidance on how to delete an encrypted key once it’s no longer needed.

The goal is to prevent bloating our key storage with obsolete records, ensuring optimal performance and security. Could someone please advise on the best practices for this scenario in Anvil? Any tips or insights into how to handle this within the Anvil framework would be greatly appreciated.

Thank you in advance for your assistance!

  1. When a key is created, it’s added to a table together with its expiration date.
  2. When used, it’s checked first if it exists, then if it is expired.
  3. A nightly scheduled background task deletes all the expired keys.

For added security you could store the hash of the key rather than the key itself, so no one knows the keys, not even you. Then you hash the key before searching it in the table, every time it’s used.

Thanks, I had not realized they expired? Do you know what the timeout is on them? Also, I like the idea you have about hashing the key!

Hmm…
What keys are you talking about?
I thought you were talking about keys you are generating in your app for your users, where you could make decisions about their expiration time.

1 Like

When using:

token = anvil.secret.encrypt_with_key("key_name", "value")

value = decrypt_with_key("key_name", token)

# if this value is going to get replaced with something new
# it would be great to first delete the old value
# example

value.delete() # I know this doesn't exist (or not that I know of)

If there is a way to effectively do this?

The Anvil secret API includes the functions ‘decrypt_with_key’, ‘encrypt_with_key’, ‘get_secret’, and the the class ‘SecretError’. Secrets are managed with the secrets user interface in the hosted IDE, and at the command line or in the YAML config-file with anvil-app-server. They are useful for symmetric encryption within an Anvil app. As far as I know, there is no way to adjust secret definitions in code (this could invalidate the effective purpose of the secrets service, when it comes to things like over-the-shoulder exposure). So, this makes the secrets service a convenient way to store third party REST API keys used in an app, or potentially, keys which can be used to implement a rotation routine for encrypting database columns (for rotations that are typically enforced every 90, 180, or 360 days, for example).

If your purpose is to ‘use encryption for securing tokens. These tokens are subject to frequent changes’, you can encrypt and decrypt tokens as frequently as needed, using an encrypted secret. But if keys are also subject to frequent changes, and you want to implement a pure Anvil solution, then things become more complex. You could, for example, create a data table which stores the encrypted keys - perhaps you may want to use an infrequently rotated key stored in secrets to encrypt those keys, and implement a rotation strategy based on that configuration (decrypting and re-encrypting the encrypted keys in place in the database on the schedule you choose).

I think Stefano is suggesting it sounds like you could store hashed ‘key’ values in a database table, using a library like bcrypt to perform the hashing. This enables values to be stored and compared to a value that’s entered, for example, by a user (passwords are handled by Anvil using the bcrypt library), but the value can’t be looked up in reverse from the saved hash (not even by the database administrator). If the user enters a value which is compared correctly to the hashed key value, then that key can be used to decrypt values which have been encrypted and stored in a database column using a library such as cryptograpy.fernet. If the key is lost, it can not be recovered.

2 Likes

It sounds to me that the term ‘key’ is being used here to refer to something like an ‘API key’ typically used to validate users of a REST API. If that’s the case (you’re building a REST API, for example, and want to verify access to user accounts), then handling and storing API keys similarly to handling passwords, using bcrypt to stored hashed values in a database table, is the likely direction to explore (and that solution is straightforward).

1 Like

For the ‘API key’ use case, the terms ‘key’ and ‘token’ sometimes get used casually to refer to a value used similarly to a password, to provide access to data stored in other database tables (encrypted or not) - and often tied in to the user authorization system in Anvil. The term ‘key’ otherwise is used to perform both encryption and decryption of values stored in a table column.

If your use case is ‘API key’, you can provide a user interface for validated users to generate hash values from user-entered values, from randomly generated values, etc. (using bcrypt or other libraries), and save those hash values to a column in the user table (or link a table containing hash values, to the user table), and validate users that way. With that sort of interface, users can change their keys after logging in with valid credentials - or administrators, back-end system logic (including logic to manage scheduled expiration practices), etc. - any entity with validated access to the API key table/column - can create new keys and delete old keys as needed - but no one can perform a reverse lookup of those keys. They’re basically just used as a secure way to save validation ‘keys’/‘tokens’ (with hashes that can only be confirmed to match an input, but never be read), as opposed to a way to save ‘keys’ that are used to encrypt and decrypt values in the database.

I hope this hasn’t come across as patronizing, just hoping to avoid potential indirection down an incorrect path, if your use case is simply to handle ‘API keys’ that are securely hashed (can’t be looked up). If your intent is to encrypt and decrypt database columns (so they can be written to and read from, not just validated as correct), with keys that need to be rotated often, then using Anvil secrets provides a mechanism to do that, but requires developing an internal process to manage rotating keys (periodically reading all the data from columns with a previously saved encryption key, and then encrypting that data again in the same cells of the table, with a new key (stored in Anvil secrets) - and those secrets can’t be managed by the code of an app (that’s not entirely true - code in an anvil server module could potentially be used to edit environment variables if you’re self hosting…). If you have compliance requirements to satisfy (HIPAA, PCI, etc.), then at least some data in the app needs to be encrypted at rest (you can also look into full hard drive encryption, and database systems like MSSQL and Firestore that provide automated encryption and key rotation).

My assumption, from your description (despite the word ‘encryption’), is that you’re most likely asking about how to store keys that provide account access (rather than keys to decrypt encrypted values). If that’s the case, storing hashed values in database table, along with a column storing expiration dates, etc., is the practice you’re looking for. The hashed values can’t be decrypted, so they are generally a secure way of storing values that need to be validated for access.

1 Like

It doesn’t look like you are generating new keys. You are encrypting a text, then you are in charge to store it, keep it or delete the previously stored one.

Here is a tutorial about how to manage encryption: App Secrets

1 Like

Hello,

I’m working on an Anvil app where I need to securely manage API refresh tokens. My current approach involves using the secrets module to hash user-specific API keys and store them in a database. This method seems preferable for security reasons over directly storing API refresh tokens.

From my understanding, there isn’t a direct method to delete stored secrets within Anvil’s secrets module. It has been mentioned in other posts that these secrets self-delete after a certain period. However, I’m seeking clarification on this aspect.

Could anyone provide insights on the following questions:

  1. Do stored secrets in Anvil’s secrets module indeed self-delete after a specific time?
  2. If so, is there a way to know or determine this self-deletion time frame? Understanding this would greatly help in managing the lifecycle of the stored API refresh tokens more effectively.

Any guidance on managing these secrets, especially in terms of their self-deletion and timing, would be highly appreciated. It’s crucial for me to ensure that the tokens are updated and managed efficiently while maintaining security.

Thank you for your assistance!

I have never seen any indication that values stored in the Secrets service delete after a certain period, and have never experience that myself. Since the Secrets service is intended for things like database passwords and API keys your app is using, it would be counterproductive for those to delete themselves.

I hope not!
I have keys that have been there for years and are still working.

If you need something that is generated by the code and stored by the code and deleted by the code, then you can create your own key. I would use something like ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(16)) and store it on a table with its expiration date of your choice.

That’s what I do with some of my apps. But they don’t have special requirements about security, I just need a unique key that no one will ever be interested in stealing, because there is nothing to steal.

I only use secrets for keys that are critical for the app security, not for something that will expire in a few minutes anyway. But I’m far from being a security expert!

I think I may have misunderstood this post?

Therefore, from the most recent responses, my understanding is that:

  1. The secrets NEVER expire.
  2. There is no way to DELETE old and never to be used again secrets.

There is terminology being mixed up here, which appears to be the source of confusion. It would be helpful if you could explain a bit more what you’re defining as a ‘key’. You said that you’re ‘hashing’ key values using secrets. Secrets are used to encrypt and decrypt values, not to hash values. Bcrypt should be used to hash values. Secrets don’t expire, and they can’t be altered from code. What’ Stefano was describing to you was creating a database table, with columns to hold your key values (which can be either hashed or encrypted using Anvil secrets for encryption, bcrypt, or a library like cryptography.fernet, depending on your needs) and expiration dates. You would use a background task to periodically delete rows from such a data table when the expiration date in a row has passed.

1 Like

You can delete secrets from the UI, just like you can create them.

My post has nothing to do with secrets.

We need some more information about the context in which you’re using the words ‘key’, ‘token’, ‘encrypt’, ‘hash’, etc., because it seems that that terminology has been used loosely, and we can’t provide an appropriate answer until we know exactly what you’re trying to do with those ‘keys’, and how they will be used. From what I’m gathering here, it sounds like you want to Hash keys with bcrypt, and save those hash values in a database table, perhaps with an expiration date that gets checked in the background function, using whatever logic you want to implement in that and other functions. That’s what it sounds like, but I’m just guessing until your exact use case is defined clearly.

1 Like

Use Anvil secrets to store values that shouldn’t be visible in an app’s source code, such as API keys needed to access third-party Rest APIs, or keys which are used to encrypt / decrypt values stored in a database. Use a database table, with an optional column to store expiration dates, and some optional logic executed in a background task, to store values that you hash with bcrypt, or encrypt / decrypt with key stored in Secrets, or with cryptography.fernet, etc.

1 Like

Hashing is a one-way operation, in which values can be validated, but not read. It’s useful for securely storing values such as passwords and API ‘keys’ - for example, if you’re creating a rest API with Anvil. Encryption and decryption are two-way operations, which enables a saved value which has been encrypted using a private ‘key’, to be decrypted using that same key. Encryption is useful for saving data in an encrypted state (‘at rest’) in a database, and then reading it back later. This ensures, for example, that if your database tables are breached, they can’t be read by anyone who doesn’t have your decryption key. Anvil Secrets can be used to store encryption keys, and to perform the encryption/decryption routine. We need to know more about exactly what sort of security functionality you intend to implement, and which sort of ‘keys’ you need to work with, in order to give you any more specific help.

1 Like

I’m working on a project where I need to manage refresh_tokens obtained from a third-party API efficiently. Here’s a step-by-step breakdown of my current process:

  1. Obtaining the Refresh Token: I initially get a refresh_token from a third-party API.
  2. Token Encryption: Next, I use anvil.secrets.encrypt_with_key("my_key_name", refresh_token) to get a hash_token.
  3. Storing the Hash Token: I then save this hash_token in a data table for future reference.
  4. Retrieving the Hash Token: When needed, I fetch the hash_token from the table.
  5. Decrypting to Get Refresh Token: I use anvil.secrets.decrypt_with_key("my_key_name", hash_token) to retrieve the original refresh_token.
  6. Updating the Refresh Token: Here, I obtain an updated refresh_token and restart this process. At this point, I want to delete the current refresh_token entry from the secrets. However, I haven’t found a clear method in the Anvil API for this deletion.

The Challenge: My primary concern is the potential accumulation of thousands of refresh_tokens. Without a way to purge outdated tokens, I’m worried about hitting data limits in my application.

1 Like

For the use case you’ve described, the only value that should be stored in Anvil secrets is the encryption key that you will use to encrypt and decrypt refresh tokens. The encrypted refresh tokens will be saved to a data table column. You’ll encrypt and decrypt those refresh tokens, using the key stored in Anvil secrets. For your step 6, you need to establish how you will identify encrypted keys that need to be removed. You could set an expiration date in another column of the row storing the encrypted token, and run a scheduled background task to delete expired rows, or you could save any other identifying information that you use to evaluate that the encrypted refresh token stored in that row needs to be deleted.

2 Likes