diff options
author | Azul <azul@leap.se> | 2012-07-20 10:56:36 +0200 |
---|---|---|
committer | Azul <azul@leap.se> | 2012-07-20 10:56:36 +0200 |
commit | 50de80c5e817476ac95a096c718a66f5555fcd05 (patch) | |
tree | e05a25868a999557e2788a91f41da3a5a8a1a0b0 /django/srpproject/srp/views.py | |
parent | 07fe2d8976db0ec267bd57ded90778f0d7695478 (diff) |
INCOMPATIBLE: major restructuring of the repository
* removed Django code - we're keeping the tests - so I hope the two can still be used together
* removed js packer - everyone has their own packaging strategy these days
* cleaned up the repository - we only have js so javascript directory does not make much sense
Diffstat (limited to 'django/srpproject/srp/views.py')
-rw-r--r-- | django/srpproject/srp/views.py | 230 |
1 files changed, 0 insertions, 230 deletions
diff --git a/django/srpproject/srp/views.py b/django/srpproject/srp/views.py deleted file mode 100644 index 74209e5..0000000 --- a/django/srpproject/srp/views.py +++ /dev/null @@ -1,230 +0,0 @@ -from django.http import HttpResponse, HttpResponseRedirect - -from django.contrib.auth.models import User - -### -### General methods -### - -# We need randomly generated salts. This is about 100 bits of entropy. -def generate_salt(): - import string, random - randomgen = random.SystemRandom() - salt_chars = "./" + string.ascii_letters + string.digits - return "".join([randomgen.choice(salt_chars) for i in range(0,16)]) - -# We want to avoid information leakage. For users that don't exist, we need salts to be consistent. -# These "fake" salts are seeded with the username and the django secret_key. They're not as random -# as true salts should be, but they should be indistinguishable to a hacker who isn't sure whether -# or not an account exists. -def generate_fake_salt(I): - import string, random, settings, hashlib - random.seed("%s:%s" % (I, settings.SECRET_KEY)) - salt_chars = "./" + string.ascii_letters + string.digits - salt = "".join([random.choice(salt_chars) for i in range(0,16)]) - return salt, int(hashlib.sha256("%s:%s" % (salt, settings.SECRET_KEY)).hexdigest(), 16) - -# In upgrades, we'll need to decrypt some AES data -def decrypt(c, key, plen): - from srp import aes - import base64 - moo = aes.AESModeOfOperation() - cypherkey = map(ord, key.decode("hex")) - ciphertext = base64.b64decode(c.replace("_", "+")) - iv = map(ord, ciphertext[:16]) - ciphertext= map(ord, ciphertext[16:]) - return moo.decrypt(ciphertext, 0, moo.modeOfOperation["CFB"], cypherkey, len(cypherkey), iv)[:plen] - -def generate_verifier(salt, username, password): - import hashlib - x = int(hashlib.sha256(salt + hashlib.sha256("%s:%s" % (username, password)).hexdigest()).hexdigest(), 16) - return hex(pow(2, x, 125617018995153554710546479714086468244499594888726646874671447258204721048803))[2:-1] - -def login_page(request): - from django.shortcuts import render_to_response - import util - return render_to_response('login.html', \ - {'error': "Invalid username or password" if "error" in request.GET and request.GET["error"] == '1' and not request.user.is_authenticated() else "",\ - 'jsHeader': util.loginHeader("http://%s/srp-test/javascript" % request.get_host()),\ - 'loginForm': util.loginForm("http://%s/srp/" % request.get_host(), "http://google.com"),\ - 'loginFunction': util.loginFunction() }) - -def register_page(request): - from django.shortcuts import render_to_response - import util - return render_to_response('login.html', \ - {'error': "Invalid username or password" if "error" in request.GET and request.GET["error"] == '1' and not request.user.is_authenticated() else "",\ - 'jsHeader': util.registerHeader("http://%s/srp-test/javascript" % request.get_host()),\ - 'loginForm': util.registerForm("http://%s/srp/" % request.get_host(), "http://google.com"),\ - 'loginFunction': util.registerFunction() }) - -### -### User Registration -### - -# Step 1. A client submits a username. If the username is available, we generate a salt, store it, and return it. -# Otherwise, we return an error. -def register_salt(request): - if User.objects.filter(username=request.POST["I"]).count() > 0: - return HttpResponse("<error>Username already in use</error>", mimetype="text/xml") - request.session["srp_name"] = request.POST["I"] - request.session["srp_salt"] = generate_salt() - return HttpResponse("<salt>%s</salt>" % request.session["srp_salt"], mimetype="text/xml") - -# Step 2. The client creates the password verifier and sends it to the server, along with a username. -def register_user(request): - from django.contrib import auth - from srp.models import SRPUser - SRPUser(salt=request.session["srp_salt"], username=request.session["srp_name"], verifier=request.POST["v"]).save() - del request.session["srp_salt"] - del request.session["srp_name"] - return HttpResponse("<ok/>", mimetype="text/xml"); - -# Step 3: The client initiates the login process. - -### -### User Login -### - -# Step 1: The user sends an identifier and public ephemeral key, A -# The server responds with the salt and public ephemeral key, B -def handshake(request): - import random, hashlib - from srp.models import SRPUser - randomgen = random.SystemRandom() - request.session["srp_I"] = request.POST["I"] - A = int(request.POST["A"], 16) - request.session["srp_A"] = request.POST["A"] - g = 2 - N = 125617018995153554710546479714086468244499594888726646874671447258204721048803 - k = 88846390364205216646376352624313659232912717719075174937149043299744712465496 - upgrade = False - if A % N == 0: - return HttpResponse("<error>Invalid ephemeral key.</error>", mimetype="text/xml") - else: - try: - user = User.objects.get(username=request.session["srp_I"]) - try: - user = user.srpuser - salt = user.salt - v = int(user.verifier, 16) - # The auth.User exists, but the SRPUser does not - # We need to create an SRPUser to correspond to that auth.User - # Initially, the verifier will be based on the known hash of the password - except SRPUser.DoesNotExist: - salt = generate_salt() - algo, dsalt, hashpass = user.password.split("$") - upgrade = True - v = generate_verifier(salt, user.username, hashpass) - - # We don't want to leak that the username doesn't exist. Make up a fake salt and verifier. - except User.DoesNotExist: - salt, x = generate_fake_salt(request.POST["I"]) - v = pow(g, x, N) - - # Ensure that B%N != 0 - while True: - b = randomgen.getrandbits(32) - B = k*v + pow(g,b,N) - u = int(hashlib.sha256("%s%s" % (hex(A)[2:-1],hex(B)[2:-1])).hexdigest(), 16) - if B % N != 0 and u % N != 0: break - - # Ideally, we could return this response and then calculate M concurrently with the user - # Unfortunately, django isn't designed to do computations after responding. - # Maybe someone will find a way. - S = pow(A*pow(v,u,N), b, N) - request.session["srp_S"] = hex(S)[2:-1] - Mstr = "%s%s%s" % (hex(A)[2:-1],hex(B)[2:-1],hex(S)[2:-1]) - request.session["srp_M"] = hashlib.sha256(Mstr).hexdigest() - response = "<r s='%s' B='%s'%s />" % (salt, hex(B)[2:-1], " a='%s' d='%s'" % (algo, dsalt) if upgrade else "") - return HttpResponse(response, mimetype="text/xml") - -# Step 2: The client sends its proof of S. The server confirms, and sends its proof of S. -def verify(request): - import hashlib - from django.contrib.auth import login, authenticate - user = authenticate(username=request.session["srp_I"], M=(request.POST["M"], request.session["srp_M"])) - if user: - response = "<M>%s</M>" % hashlib.sha256("%s%s%s" % (request.session["srp_A"], request.session["srp_M"], request.session["srp_S"])).hexdigest() - login(request, user) - else: - response = "<error>Invalid username or password.</error>" - - try: - del request.session["srp_I"] - del request.session["srp_M"] - del request.session["srp_S"] - del request.session["srp_A"] - except KeyError: - pass - return HttpResponse(response, mimetype="text/xml") - -# Check that the user has generated the correct M -def upgrade_auth(request): - import hashlib - if request.POST["M"] == request.session["srp_M"]: - response = "<M>%s</M>" % hashlib.sha256("%s%s%s" % (request.session["srp_A"], request.session["srp_M"], request.session["srp_S"])).hexdigest() - request.session["srp_preauth"] = True - else: - response = "<error>Invalid username or password.</error>" - return HttpResponse(response, mimetype="text/xml") - -# Receive the encrypted password, create the verifier, save the user, and notify the client -def upgrade_add_verifier(request): - from srp.models import SRPUser - from django.contrib.auth.models import User - import hashlib - salt = generate_salt() - key = hashlib.sha256(request.session["srp_S"]).hexdigest() - user = User.objects.get(username=request.session["srp_I"]) - srpuser = SRPUser() - srpuser.__dict__.update(user.__dict__) - srpuser.verifier = generate_verifier(salt, request.session["srp_I"], decrypt(request.POST["p"], key, int(request.POST["l"]))) - srpuser.salt = salt - srpuser.password = "" - srpuser.save() - return HttpResponse("<ok/>", mimetype="text/xml") - -# If a user has posted their username and password, we'll go ahead and authenticate them -def no_javascript(request): - from django.contrib.auth.models import User - from srp.models import SRPUser - from django.contrib.auth import login, authenticate - try: - user = User.objects.get(username=request.POST["srp_username"]) - try: - # Create a verifier for the user, and check that it matches the user's verifier - # Since we're doing it all on one side, we can skip the rest of the protocol - v = generate_verifier(user.srpuser.salt, request.POST["srp_username"], request.POST["srp_password"]) - user = authenticate(username=request.POST["srp_username"], M=(user.srpuser.verifier, v)) - if user: - login(request, user) - if not request.POST["srp_forward"].startswith("#"): - return HttpResponseRedirect(request.POST["srp_forward"]) - else: - return HttpResponseRedirect("%s%s" % (request.META["HTTP_REFERER"], request.POST["srp_forward"])) - except SRPUser.DoesNotExist: - # The user exists in the auth table, but not the SRP table - # Create an SRP version of the user - if user.check_password(request.POST["srp_password"]): - srpuser = SRPUser() - srpuser.__dict__.update(user.__dict__) - srpuser.salt = generate_salt() - srpuser.verifier = generate_verifier(srpuser.salt, request.POST["srp_username"], request.POST["srp_password"]) - srpuser.password = "" - srpuser.save() - if not request.POST["srp_forward"].startswith("#"): - return HttpResponseRedirect(request.POST["srp_forward"]) - else: - return HttpResponseRedirect("%s%s" % (request.META["HTTP_REFERER"], request.POST["srp_forward"])) - except User.DoesNotExist: - # The user does not exist in the auth tables - # Send the client back to the login page with an error - pass - if "?" in request.META["HTTP_REFERER"]: - if "error=1" in request.META["HTTP_REFERER"]: - return HttpResponseRedirect("%s" % request.META["HTTP_REFERER"]) - else: - return HttpResponseRedirect("%s&error=1" % request.META["HTTP_REFERER"]) - else: - return HttpResponseRedirect("%s?error=1" % request.META["HTTP_REFERER"]) |