In the turbogears development.ini file, there's a value something like this:
cookie_secret = aabbccdd-eeff-0011-2233-445566778899
consisting of hexadecimal digits and dashes.
The same value is placed in beaker.session.secret and beaker.session.validate_key.
http://turbogears.org/2.0/docs/main/Config.html has a section on this value:
The beaker.session.secret key of the base_config object contains the secret used to store user sessions. Pylons automatically generates a random secret for you when you create a project. If an attacker gets his hands on this key, he will be able to forge a valid session an use your application at though he was logged in. In the event of a security breach, you can change this key to invalidate all user sessions.
What's the best way to generate a new key?
It can be anything you want. Better if hard to catch or bruteforce. Same rules of password apply. It is currently generated with uuid.uuid4() if I remember correctly
Related
I'm working on a distributed application, and we need a way to authorize clients. Every client has a PGP keypair associated with them, and we require them to enter their private key (which is not stored) through which their pubkey is derived and used to identify clients and modify their fields on the distributed database.
Now, considering user experience, entering a private key on a website whenever you need to do something is troublesome. But we also cannot maintain a central database for username/password based authentication as that creates a single failure point (not what the distributed application is meant to do)
I am hoping there is some way to get an easier to remember human readable descriptor of the private key which can be used to authenticate if something like that exists. Any other ideas are appreciated too.
I'll throw a bunch of ideas to clarify the question:
Are you certain that PGP is suited for your needs?
I feel like you should provide some more details to be sure:
- How are the private and public keys used exactly? I understand the following : user inputs its private key, information is decrypted and modified, public key is deduced from private and used to encrypt the updated information.
- How is this different from using a regular password and being able to authenticate the user and encrypt data?
- You seems to send private keys on the network, and they should remain private.
How you could use a regular password:
User has a password, your application uses a function (e.g sha256, KDF,...) to make it usable by classical encryption algorithms (e.g AES). With the same (not stored) key, you can then encrypt and decrypt datas. You just have to make sure that decryption is valid, by adding a known value at the beginning of the data (e.g a part of the key).
Quick example:
password: "WeakPassword"
key: sha256("WeakPassword"+"MySalt") = 493e3ae...b2eec8ef
Decrypt(data,key)
clearData = "493e3ae{123;456}" //valid, because you can check the beginning
Encrypt(clearData,key)
Advantages: usable passwords, faster symmetric encryption
Use a QR code
If you stick to PGP and have a camera available it is pretty handy.
You could also use hexadecimal, base64, ... but for a 2048 bits RSA key, that still gets you hundreds of characters.
I have a service where users each have an API key. I need to store the keys so that they can be used to validate API requests.
If I store the keys in plaintext in my database, I'm worried about the scenario of someone getting access to the db, grabbing all the plaintext api keys, then using them to impersonate others (there will likely be bigger problems if someone got access to the db, though).
This is similar to storing user passwords, where you just store the hash and validate using that - however most APIs let you view your API keys, which means they need to be stored in some recoverable way.
Is there a best practice for this?
The threat that someone gets the database and gets the keys means they can use the api keys to access the data in the database, which they already have, so no win there.
The threat that someone can access the database, get the passwords, means they can reuse those passwords on other web sites with the same user name because people tend to reuse their passwords.
Another reason having passwords in the clear or easily reversable is someone in your company could get a hold of the passwords, and start to do bad stuff acting as the user. Which IS a risk you might have if your API keys are in the clear.
Typically, HMAC is a solution for cryptographically computing a secure value from a single secret key, and some public value.
Have a look at HMAC. With HMAC, you can load a secret key into memory with the app (config file, read off of amazon KMS, typed in on app start, or however you want to get that secret key there).
In the database, store a token. Token = UUID() for example. The token should be unique to the user, the token could be versioned in case you need to regenerate, and the token could be random (like UUID). The token is not secret.
The API key is computed using the secret key (SK) and user token (UT) as follows:
API_SECRET = HMAC(SK, UT)
Then distribute that UT (More commonly called API_KEY) and API_SECRET to the user, and when the user tries to connect, you compute the API_SECRET:
Get user record from database (you're probably already asking the user to provide their username)
Compute the API_SECRET from the UT in the database:
API_SECRET_DB = HMAC(SK, UT)
Compare the computed API_SECRET_DB to the one provided in the request:
if (API_SECRET_DB == API_SECRET_FROM_REQUEST){
//login user
}
Bottom line, you only protect the Secret Key, and not every single credential.
I did an update to some library written in PHP which made it using an Impersonate Protection Algorithm (IPA). that lead to not saving the Token itself inside a database.
For more info check this https://github.com/vzool/api-hmac-guard
Hope it helps, Thanks
I came across many APIs that give the user both an API key and a secret. But my question is: what is the difference between both?
In my eyes, one key can be enough. Say I have a key and only I and the server know it. I create a HMAC hash with this key and do an API call. On the server, we create the HMAC hash again and compare it with the sent hash. If it's the same, the call is authenticated.
So why use two keys?
Edit: or is that API key used to lookup the API secret?
You need two separate keys, one that tells them who you are, and the other one that proves you are who you say you are.
The "key" is your user ID, and the "secret" is your password. They just use the "key" and "secret" terms because that's how they've implemented it.
Simple answer, if I understood it correctly...
If you use your API key for encryption, how will the service know who is contacting them? How will they decrypt that message?
You use API key to state who you are, this is what you are sending in plain text.
The SECRET key you do not send to anyone. You simply use it for encryption. Then you send the encrypted message. You do not send the key that was used for encryption, that would defeat the purpose.
One thing that I did not see mentioned here, although it is an extension of Marcus Adams's answer, is that you should not be using a single piece of information to both identify and authenticate a user if there is a possibility of timing attacks, which can use the differences in response times to guess how far a string comparison got.
If you are using a system which uses a "key" to look up the user or credential, that piece of information could be incrementally guessed over time by sending thousands of requests and examining the time that it takes for your database to find (or not find) a record. This is especially true if the "key" is stored in plaintext instead of a one-way hash of the key. You would want to store users's keys in a plaintext or symmetrically-encrypted for if you need to be able to display the key to the user again.
By having a second piece of information, or "secret", you can first look up the user or credential using the "key", which could be vulnerable to a timing attack, then use a timing-safe compare function to check the value of the "secret".
Here is Python's implementation of that function:
https://github.com/python/cpython/blob/cd8295ff758891f21084a6a5ad3403d35dda38f7/Modules/_operator.c#L727
And it is exposed in the hmac lib (and probably others):
https://docs.python.org/3/library/hmac.html#hmac.compare_digest
One thing to note here is that I don't think that this kind of attack will work on values that are hashed or encrypted before lookup, because the values that are being compared change randomly each time a character in the input string changes. I found a good explanation of this here.
Solutions for storing API keys would then be:
Use a separate key and secret, use the key to look up the record, and use a timing-safe compare to check the secret. This allows you to show the user the key and secret to a user again.
Use a separate key and secret, use symmetrical, deterministic encryption on the secret, and do a normal comparison of encrypted secrets. This allows you to show the user the key and secret again, and could save you from having to implement a timing-safe comparison.
Use a separate key and secret, display the secret, hash and store it, then do a normal comparison of the hashed secret. This removes the necessity to use two-way encryption, and has the added benefit of keeping your secret secure if the system is compromised. It has the downside that you cannot show the secret to the user again.
Use a single key, show it to the user once, hash it, then do a normal lookup of the hashed or encrypted key. This uses a single key, but it is not able to be shown to the user again. Has the benefit of keeping keys secure if the system is compromised.
Use a single key, show it to the user once, encrypt it, and do a normal lookup of the encrypted secret. Can be shown to the user again, but at the cost of having keys vulnerable if they system is compromised.
Of these, I think that 3 is the best balance of security and convenience. I have seen this implemented on many websites when getting keys issued.
Also, I invite any actual security experts to critique this answer. I just wanted to get this out there as another discussion point.
There are answers explaining what the secret and (public) key is. It's a public-private key pair that they give confusing names to. But nobody says why the APIs require both, and many APIs only give you one secret! I've also never seen any API's docs explain why they have two keys, so the best I can do is speculate...
It's best to put only your public key in your request and sign the request locally with your private key; sending anything more shouldn't be needed. But some get away with just having the secret in the request. Ok, any good API will use some transport security like TLS (usually over HTTPS). But you're still exposing your private key to the server that way, increasing the risk of them somehow mishandling it (see: GitHub and Twitter's password logging bug recently discovered). And HTTPS is theoretically just as secure, but there are always implementation flaws out there.
But many – actually most it seems – APIs have you send both keys in requests since that's easier than making people do their own signatures; can't have pure cURL examples otherwise! In that case, it's pointless to have them separate. I guess the separate keys are just for in case they change the API later to take advantage of them. Or some have a client library that might do it the more secure way.
Here's the situation - its a bit different from the other database/password questions on StackOverflow.com
I've got two sets of users. One are the "primary" users. The others are the "secondary" users. Every one has a login/password to my site (say mysite.com - that isn't important).
Background: Primary users have access to a third site (say www.something.com/PrimaryUser1). Every secondary user "belongs" to a primary user and wants access to a subpart of that other site (say www.something.com/PrimaryUser1/SecondaryUser1).
At mysite.com, the primary users have to provide their credentials to me which they use to access www.something.com/PrimaryUser1, and they specify which "subparts" the secondary users of their choice get get access to.
Mysite.com helps manage the sub-access of the secondary users to the primary user's site. The secondary users can't "see" their primary user's password, but through my site, they can access the "subparts" of the other site - but ONLY to their restricted subpart.
In a crude way, I'm implementing OAuth (or something like that).
The question here is - how should I be storing the primary user's credentials to the other site? The key point here is that mysite.com uses these credentials to provide access to the secondary users, so it MUST be able to read it. However, I want to store it in such a way, that the primary users are reassured that I (as the site owner) cannot read their credentials.
I suppose this is more of a theoretical approach question. Is there anything in the world of cryptography that can help me with this?
Text added:
Since most ppl are completely missing the question, here's attempt #2 at explaining it.
PrimaryUser1 has a username/password to www.something.com/PrimaryUser1Site
He wishes to give sub-access to two people- SecondaryUser1 and SecondaryUser2 to the folders- www.something.com/PrimaryUser1Site/SecondaryUser1 and www.something.com/PrimaryUser1Site/SecondaryUser2
Mysite.com takes care of this sub-user management, so PrimaryUser1 goes there and provides his credentials to Mysite.com. MySite.com internally uses the credentials provided by PrimaryUser1 to give subusers limited access. Now, SecondaryUser1 and SecondaryUser2 can access their respective folders on www.something.com/PrimaryUser1Site through the MySite.com
NOW, the question arises, how should I store the credentials that PrimaryUser1 has provided?
First rule: Never, ever store passwords!
Second rule: Calculate a hash over password, with additional salt, and store this in your database.
Third rule: A username (uppercased) could be used as salt, but preferably add a little more as salt! (Some additional text, preferably something long.)
Fourth rule: It doesn't matter how secure a hashing algorithm is, they will all be hacked sooner or later. All it takes is time!
Fifth rule: The security of your site depends on the value of what's behind it. The more value the content has, the more likely that you'll be attacked!
Sixth rule: You will discover, sooner or later, that your site is hacked but not through a hacked password, but through a loophole somewhere else in your code. The biggest risk is expecting your site is secure now you've implemented some strong security.
Seventh rule: All security can be broken, all sites can get hacked, all your secrets can be discovered, if only people are willing to invest enough time to do so.
Security is an illusion but as long as no one breaks it, you can continue to dream on! Always be prepared for rough awakenings that will require you to rebuild your illusion again. (In other words, make regular backups! (Preferably daily.) Don't overwrite the backups of the last week and make sure you keep at least one backup of every week, just in case you discover your site was hacked months ago and all your backups ever since are infected!
Now, if you really need to store passwords, use a hash over username plus password. Then hash again with hash plus salt! Better yet, create a list of salts (just list of words) and whenever a new user account is created, pick a random salt word to use to hash his username plus password. Store the index of the salt with the user account so you know which one to use whenever he logs on again.
And:
Eight rule: Always use HTTPS! It's not as secure as most people thing but it does give a feeling of security to your users!Since you've added text, I'll add more answer.
Since you want user1 to grant temporary access to user 2, you'll need a secondary user table. (Or expand the user table with a parent user ID. Also add a timestamp to keep track of the account age. User 1 can create the credentials and this is done in the normal way. Just store a hash with combined username and salt. In this case, use the username of user 1 as additional salt! Just make sure you'll disable the user 2 account when user 1 logs off or when a certain amount of time has gone by. And allow user 1 to enable all accounts again that he created, so they can re-use an account instead of having to create new ones all the time.
Security isn't a matter that depend on primary or secondary users. In general, treat them the same way! Secondary users have an added bonus that you can use the primary account as additional salt. The rest of it has nothing to do with authentication any more. It's authorization that you're dealing with. And while authentication and authorization have a strong relationship, be aware that you should treat them as two different, stand-alone techniques.
When user 1 logs on, he's granted access to the primary site. When he grants access to user 2, user 2 gets a reduced set of roles. But this has nothing to do with storing user names or passwords. You just have an user-ID which happens to be member of certain roles, or groups. Or not, but those would be inaccessible.
They're both just users, one with more rights than the other.
It depends on the kind of authentication your primary site and the secondary site agree on. Is it forms authentication, HTTP Basic or HTTP Digest? If is forms or basic then you have no choice, you must store the password, so your only choice is to encrypt it. You cannot store a password hash as you must present the clear text during authentication for both forms and HTTP Basic. The problems that arise from storing the encrypted password are due to either incorrect use of cryptography (ie. you don't use an IV or salt or you don't use correctly a stream cipher), but more importantly you'll have key management problems (where to store the key used to encrypt the passwords and how to access it from a non-interactive service/demon).
If the 3rd party site accepts HTTP Digest then you're in better luck, you can store the HA1 hash part of the Digest hash (ie. MD5 of username:realm:password) because you can construct the Digest response starting straight from HA1.
I did not address how the user provision the secondary credentials (ie. how you get the secondary site username and password n the first place), I assume you have secured a protected channel (ie. HTTPS from client to your primary site).
BTW this assumes that the authentication occurs between your primary and secondary site and the secondary site content is tunneled through an HTTP request made to the primary site. If that's not the case and the secondary site is actually accessed straight from the browser, then the secondary site must support some sort of pre-authenticated token based authorization of third parties like OAuth. Relying on credential authentication and storing the credentials on the primary site when the credentials are actually needed by the browser has so many problems is not even worth talking about.
Have you thought about accepting OpenID like Stack Overflow does? That way you are not responsible for storing passwords at all.
There is only one way to do this, and it is probably too burdomesome for the users.
You could encrypt the users password with a public/private key, the user keeps their key so the password can be unencrypted only when the key is submitted back to your server. The only way to make this simple would to be to have some web browser plugins that auto submit the information.
And either way, you could always packet sniff the communication to/from the server so its still mostly pointless.
there has got be a better way to explain this :(
but if you just want to know how to store the passwords safely do this:
username:john, password:pass
key = '!!#ijs09789**&*';
md5(username.password.key);
when they login just check to see if md5(username.password.key) = is equal to the one in the db - you can also use sha1 and or any other encryption method.
http://us.php.net/md5 & http://us.php.net/sha1
Never store passwords in a database but store a salted and hashed version of every password.
Check this article if this is chinese for you.
If you want to store the password yourself the best apporach is to use a one-way hashing algorithm such as MD5 or SHA-1. The advantage of this approach is that you cannot derive the password from the hashed value.
Precisely which algorithm you choose depends the precise products you are using. Some front-end tools offer these functions, as do some database products. Otherwise you'll need a third-party library.
Edit
Secondary users ought to have their own passowrds. Why wouldn't they?
You're making it too complex. You need to stop trying to mix authentication and authorization.
What you want to do is establish credentials for everyone, not worrying at this point if they are "primary" or "secondary" users. Then on the main site, where you manage the users and the primary/secondary relationships, you can do the logic of which users are primary or secondary and store all that stuff in a table. You grant or deny whatever rights and sub-rights you wish to each secondary user whenever the primary users update their relationships with them. When they're done, you finally need to replicate the appropriate user credentials from the main site out to the secondary site(s).
Then when a secondary user wants to head to any site in your farm, they authenticate themselves only as themselves - they never impersonate the primary user! And they have only the rights you granted them when the primary users gave them "secondary" status.
--
OK, since you shot that solution down in the comment, consider this:
First, I doubt anything will be truly secure. You can always recover the secret if you monitor the users' activity.
Now, this is completely off the cuff, and I haven't cryptanalyzed it, but check into what is called a secret sharing scheme. Store the "effective" or "real" main-site primary user password as the shared secret. Use the salted hash of the password given by the primary user as one secret. Use the salted hash of the password given by the first secondary user as another secret, and so on for each additional secondary user. Don't store the salted hashes! Just store the salt and the protected shared secret.
When a user enters their password, you retrieve the protected shared secret, use the salt and hash of their password to produce the salted hash, decrypt the protected shared secret, and now you've got the original primary user password.
i am starting to use cryptostream class. i may be wrong, if you encrypt something, close the app, and then try to decrypt it, it will not be able to because a different key will be generated. because i do need this functionality, i am wondering if it's possible to save the key in application settings and whether this is the right way to go?
If you always run your app under the same user account (it can be a local user or a domain user), the best option would be to use DPAPI. The advantage of using DPAPI is that you do not have to worry about the key (the system generates it for you). If you run the app under different user identities, then it gets more complex because the options that are available range from bad to worse (the major problem is: how do you protect your secret: key, password, passphrase, etc). Depending on what you want to do, you may not need to use encryption at all (e.g. if you want to encrypt a connection string, consider using integrated windows authentication, which does not require a password). For more info on the topic, check out this MSDN article: Safeguard Database Connection Strings and Other Sensitive Settings in Your Code; it may give you some ideas.
Lots of applications save the keys in configuration files. It's a common bad practice.
It's not secure but all secure options are hard to implement. There are options using different factors,
You can derive the key from a password using PBE (password-based encryption). But you have to enter a password to start your application. This is so called "What you know" factor.
Put the key in a smartcard. This is very secure but you need to have access to the card on the machine. This is called "What you have".
Ignore other schemes involving encrypting keys with yet another key. It doesn't really change the security strength.