Digest authentication in django - python

As far as my knowledge says in digest authentication, a client does an irreversible computation, using the password and a random value supplied by the server as input values. The result is transmitted to the server who does the same computation and authenticates the client if he arrives at the same value. Since the computation is irreversible, an eavesdropper can't obtain the password.
Keeping eye on the above definition, I used CryptoJS.HmacSHA256("password", "key") in Javascript to send the information to django server, now the problem is:
I need to check that in server using same logic but django already has hashed the password in its own format, for example using pbkdf2_sha256.
Should I use some reversible algorithm like AES? I don't think it is possible to crack django's hashing algorithm and write the same for client side?

Why are you trying to do authentication in this manner? You can not use djangos default authentication for this.
What you could do though is (for example):
Create a new model, linked to the user, that has a shared secret key, and a token
Create your own authentication backend which accepts the signed value, validates the signed value, and then logs the user in
I used the details in this article to implement the algorithm. Even if you aren't using this method, you're still going to need to create your own custom authentication backend.

AES is not a hashing algorithm. It's an encryption algorithm.
You can use hashing algorithms like SHA1 or MD5.

Related

Design an encrypted time-limited API on Client/Server side

I am planning design an encrypted time-limited API on both Client and Server sides, the server side is written in Django, the client side is a GUI program which call the API by
import requests
c = requests.post("http://127.0.0.1:8000/VideoParser/", data={'videoUrl': videoUrl })
The way it call the API is desperately exposed to those who can use network traffic capturing tools like wireshark and fiddler, while I don't want anyone else could call the API with their customized videoUrl, and if people made the post call with the same parameters 2 minutes later after the client initially made the call, the call should be valid or expired, so how to design the encrypted time-limited API on both Client and Server side in this case ?
P.S. I think add an identifier to the post data could prevent them using the API
import requests
c = requests.post("http://127.0.0.1:8000/VideoParser/", data={'videoUrl': videoUrl, 'identifier':value_of_identifier })
provided there is something encrypted in the value_of_identifier and it changes with each call, but I don't know how to get started, any idea ?
It would be better to show some code , I really don't know how to start to write code.
I think this will address your objectives:
Create an access key and a secret key for each user who is allowed to make requests.
Give one copy of each key to the user and keep one copy of each key on the server.
Add the following two parameters to each request: timestamp, and access key
Require that when the user sends a request, she creates a string of the post request, along with a timestamp parameter, and hash it using SHA256, using the secret key. (any hashing algo will do)
Create a parameter named Signature in your Post request, and use the hashed string as the value of the signature.
When the request reaches the server, use the access key to retrieve that user's secret key, and hash the request again. This will re-create the signature. The signature created at the server and one sent by the user must match.
If the two signatures don't match, discard. This way, anyone listening on the wire will have the url as well as the access keys, but will not be able to create a valid signature without the secret key associated with the access key.
Since there is a timestamp involved, the attacker will not be able to re-use a stolen signature.
Amazon uses this technique. http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html

Hashing tokens with django rest

I am creating a REST API with django-rest-framework. The framework supports token authentication but this feature does not seem to be very robust. For example, I would like to hash the tokens before they are inserted in the DB as well as add a salt.
Can I hash and salt a token with the authentication mechanism in django-rest?
Thanks
Make use of django-rest-framework-jwt. It's a modern way of authentication and doesn't require any DB operation. Also you can send some data to front end like the roles and other non secure user information.

HMAC Authentication using Django - Shared Secret

For those who read this later: This was part of a hobby project I was doing and back then I wasn't aware of such a thing called Let's Encrypt! Also, I didn't want to purchase an SSL cert; so I was trying to have SOME security without https. Signing does not replace encryption. If you wanna do what I wanted to do, don't. Get a cert from Let's Encrypt. It's Easier and more secure!
I am implementing a web service using Django for a mobile app. I decided to use Hash-MAC to authenticate requests (no Oath, no https) but the challenge is what should I use as the shared secret key?
First I considered using The user's password but it required to store passwords in plain text in server-side database. The other solution that came to my mind was salting and hashing password in the mobile app just the way that Django auth app does in order to compute hashed password on client-side.
What does Django use as salt? Are they "secret"? Is there any problem with sending them as plain-text to users? We don't have to keep salts as "secret"s in general, but Django may use something that should be kept secret as salts, I don't know, it is about how Django implemented this.
Users have to know their salts to compute a hashed password, so the server should provide them with it. An adversary can ask for all users salts and eventually (s)he can have all the salts (Even if there is a limit to the number of times someone can ask for this in a certain time period). Even though salts are not secret but I guess knowing "all" of them can be dangerous. (or maybe I am overly concerned about security!)
Requests format:
HTTP request header:
x-mac-digest: 1d186b9c0fd5cd393f23623f0d167f7b17ac7d1cd74d8442647991d61e756c19
HTTP request body:
{
"username": "mjafar",
... rest of request in json
}
Authenticating request (simplified):
hash_digest = request.META['HTTP_X_MAC_DIGEST']
request_body = request.body.decode('utf-8')
request_json = json.loads(request_body)
user = UserModel.objects.get(username=request_json['username'])
sharedKey = getSharedKey(user) # What should it return?
hash = hmac.new(sharedKey, request_body, hashlib.sha256).hexdigest()
if hash != hash_digest:
return HttpResponseBadRequest('MAC authentication failed')
HMAC is used to authenticate a block of messages. It's used to verify block of cipher/Text was not changed during the transmission. You will need to use asymmetric encryption (RSA, DH,..etc) to transfer your shared key.
Using a plain text without using digital signature is useless. You will be vulnerable to MITM attack. Unless you manage to put the shared secret on the mobile app without internet (GSM SIM cards have shared key inside the sim itself and it's used to encrypt GSM calls).
Django uses random function to generate its secret_key. Random function on Linux will call /dev/urandom, on windows will call what's equivalent to that.
In your case, create a rest api to create a username and password, then return a hash value to be used to access your views.
If you want to compute a custom hash value, you can call make_password function, and save it directly in the password attribute in User
Read this: https://docs.djangoproject.com/en/1.8/topics/auth/passwords/
Example: Django make_password too slow for creating large list of users programatically

Password submission in Python

I am developing a website using Google app engine and I want to know what is the proper way to handle the submission.
I was thinking of doing something like hashing the password client-side with some salt, and then hash it again with some other salt on the server-side.
I want to know if this is at least some decent security, and if it already exists a Python library that does just that or something better.
The standard practice is to use SSL encryption for the connection (e.g. https), then hash it with a salt on the server side. When later a user logs in, you will have to still verify the password and sending a hash of the password from browser to server is just as insecure as sending the password itself; an attacker that intercepts either can still log in as that user.
There is a python package called passlib that can take care of the various forms of password hashing and salting for you:
from passlib.hash import sha256_crypt
hashed = sha256_crypt.encrypt(password)
It is generally a good idea to include the choosen algorithm in the stored password hash; RFC 2307 passwords (as used in LDAP) use a {SCHEME} prefix, other hash schemes use a unix $digit$ prefix, where digit is a number; the sha256 scheme in the code snippet above uses $5$ as a prefix.
That way you can upgrade your password scheme at a later time while still supporting older schemes by choosing the correct hashing algorithm to verify a password at a later time.
Most passlib hashing schemes already return hashes with their standard prefix, documented in each scheme's detailed documentation page. You can use the .identify() function to identify what hash algorithm was used when you later need to verify a password hash against an entered password.
Use TLS (HTTPS). It isn't perfect, but it is better than nothing (and way better than digest authentication).
If you don't want to store passwords, you can let Google take care of everything: https://developers.google.com/appengine/articles/auth
If you do want to worry about storing passwords, use passlib, as explained by Martijn Pieters.
You are looking for a digest authentication. Digest Auth is secure, that means, the password is not transfered in clear text. However, the communication after the auth is not encrypted.
See a full example here: http://code.activestate.com/recipes/302378-digest-authentication/

How to store a crypto key securely?

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.
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.
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.
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?

Categories