12

I'm looking at using a crypto lib such as pycrypto for encrypting/decrypting fields in my python webapp db. But encryption algorithms require a key. If I have an unencrypted key in my source it seems silly to attempt encryption of db fields as on my server if someone has access to the db files they will also have access to my python sourcecode.

Is there a best-practice method of securing the key used? Or an alternative method of encrypting the db fields (at application not db level)?

UPDATE: the fields I am trying to secure are oauth tokens.

UPDATE: I guess there is no common way to avoid this. I think I'll need to encrypt the fields anyway as it's likely the db files will get backed up and moved around so at least I'll reduce the issue to a single vulnerable location - viewing my source code.

UPDATE: The oauth tokens need to be used for api calls while the user is offline, therefore using their password as a key is not suitable in this case.

citronic
  • 9,868
  • 14
  • 51
  • 74

3 Answers3

5

If you are encrypting fields that you only need to verify (not recall), then simple hash with SHA or one-way encrypt with DES, or IDEA using a salt to prevent a rainbow table to actually reveal them. This is useful for passwords or other access secrets.

Python and webapps makes me think of GAE, so you may want something that is not doing an encrypt/decrypt on every DB transaction since these are already un-cheap on GAE.

Best practice for an encrypted databased is to encrypt the fields with the users own secret, but to include an asymmetric backdoor that encrypts the users secret key so you (and not anyone who has access to the DB source files, or the tables) can unencrypt the users key with your secret key, should recovery or something else necessitate.

In that case, the user (or you or trusted delegate) can retireve and unencrypt their own information only. You may want to be more stringent in validating user secrets if you are thinking you need to secure their fields by encryption.

In this regards, a passphrase (as opposed to a password) of some secret words such "in the jungle the mighty Jungle" is a good practice to encourage.

EDIT: Just saw your update. The best way to store OAuth is to give them a short lifespan, only request resources your need and re-request them over getting long tokens. It's better to design around getting authenticated, getting your access and getting out, than leaving the key under the backdoor for 10 years.

Since, if you need to recall OAuth when the user comes online, you can do as above and encrypt with a user specfic secret. You could also keygen from an encrypted counter (encrypted with the user secret) so the actual encryption key changes at each transaction, and the counter is stored in plaintext. But check specific crypto algo discussion of this mode before using. Some algorithms may not play nice with this.

Cris Stringfellow
  • 3,714
  • 26
  • 48
  • would this not mean the user needing to authorise each time the app made a request? – citronic Feb 08 '12 at 18:12
  • it's up to you. If you want to store long-life OAuth then they wont need to reauthorize OAuth every request. And you can keep the plaintext OAuth in your app memcache when the user is online, and use their password (or other user secret) at session start to decrypt your DB Oauth. But asking a re-request every 2 weeks or 30 days seems kind of professional if you are serious about security. – Cris Stringfellow Feb 08 '12 at 18:15
  • I can see how a security professional would conclude that but personally I've yet to come across a web app using a 3rd party api via oauth that doesn't store oauth tokens at least until the user explicitly revokes authorisation on the 3rd party site. – citronic Feb 08 '12 at 18:33
  • Sure, but it's always best to advise best practice to keep things moving forward. But practically, it's not really a problem. If someone can access a server with all the oauth, then all those oauth belong to them, even if it's short-span. but if each entry is encrypted with a user-specific key, then that's a great way to secure them more and frustrate the malfeasants. please don't put a secret key in your source code. – Cris Stringfellow Feb 08 '12 at 18:53
  • but if I ask the user for a key I still need to store that to use it later do I not? – citronic Feb 08 '12 at 19:14
  • 1
    Okay I am assuming you already have some form of access control for the user, in which case you will already be storing their password. So you can form the encryption key from that password and use that to encrypt the Oauth. But if you are outsourcing user access control to a third part (i.e. Google), maybe the only way to do it is to store a randomly generated key in a cookie with the user, and encrypt your server based oauth with that key, and only re-request permissions when the cookie is not present. However, if you are outsourcing authent to Google, doesn't Python have a Users API – Cris Stringfellow Feb 09 '12 at 08:43
  • And you can get email / unique ID from that Users API? If you're comfortable with this thinner layer of protection you could use the unique ID from one of the various fields (depending on user origin) described here : http://code.google.com/appengine/docs/python/users/userclass.html – Cris Stringfellow Feb 09 '12 at 08:45
  • Sorry, not using app engine. Regarding using the user password - I store it as a secure hash. If the attacker has access to my db files and my source code (in order to see that I use the hashed password as key for the other fields) then that offers no additional benefit over storing the key in plaintext in my source, other than the fact the attacker will have to use a different (but known) field each time for cracking the encrypted fields. Is that a correct assumption? – citronic Feb 09 '12 at 22:26
  • 1
    No. The unhashed password, because you store it as a hash, has an unknown value to the attacker. Even if the hacker can see the hashes of passwords, he will still have to crack those (which if you salt them as is standard will make it much harder for the attacker) to crack any encryption you base on the (unhashed) password value. Base the encryption key on the *unhashed* password value, and recompute that key everytime the user logs in. So the users OAuth is protected, and only accessible at the time the user correctly logs in. – Cris Stringfellow Feb 10 '12 at 06:25
  • I see now. Not suitable for my application though as it requires oauth-secured actions while the user is offline. – citronic Feb 12 '12 at 18:49
  • 1
    Yu probably don't want to go to all the trouble, but yu could have a separate server for your oauth. your application can request tokens from this server. But your application needs to authenticate itself without leaving a key in the source code. A way to do this is to use a counter key based on the last interaction. Kind of like car locks that change the code each time. If someone can compromise the run state of your main server then they can still get the oauth keys, but not if they only have the source code. The secrets are stored in memory. You can encrypt this counter with your ouath – Cris Stringfellow Feb 14 '12 at 03:11
  • with your ouath server's public key, and send it securely to your ouath server to verify. Your main application then updates it's counter key for the next interaction. One way to do this update is to have the ouath server return an open-channel nonce, and encrypt your current counter key with that nonce. The counter key remains secure as long as the RAM on your main server is secure. (of course you need to initially sync a secret with the ouath server on load but this can be done DH Key Xchange with a random session key). Finally you get another – Cris Stringfellow Feb 14 '12 at 03:16
  • dimension of security from the fact that your oauth server only accepts requests from your main servers domain. – Cris Stringfellow Feb 14 '12 at 03:16
  • thankyou for your persistence and this very complete solution. Security isn't easy. – citronic Feb 14 '12 at 14:28
1

Symmetric encryption is indeed useless, as you have noticed; however for certain fields, using asymmetric encryption or a trapdoor function may be usable:

  • if the web application does not need to read back the data, then use asymmetric encryption. This is useful e.g. for credit card data: your application would encrypt the data with the public key of the order processing system, which is on a separate machine that is not publically accessible.

  • if all you need is equality comparison, use a trapdoor function, such as a message digest, ideally with a salt value. This is good for passwords that should be unrecoverable on the server.

Simon Richter
  • 28,572
  • 1
  • 42
  • 64
  • I already have my password hashed using SSHA. For my users' oauth tokens I obviously need to decrypt before using them in requests on the users behalf. – citronic Feb 08 '12 at 17:54
0

Before you can determine what crypto approach is the best, you have to think about what you are trying to protect and how much effort an attacker will be ready to put into getting the key/information from your system.

What is the attack scenario that you are trying to remedy by using crypto? A stolen database file?

Anders Lindahl
  • 41,582
  • 9
  • 89
  • 93
  • Yes a stolen db file. I've read that the expectation is that oauth tokens & app keys should be encrypted to the same level as other sensitive info such as passwords. – citronic Feb 08 '12 at 17:56