summaryrefslogtreecommitdiff
path: root/django/srpproject/srp/views.py
diff options
context:
space:
mode:
Diffstat (limited to 'django/srpproject/srp/views.py')
-rw-r--r--django/srpproject/srp/views.py72
1 files changed, 53 insertions, 19 deletions
diff --git a/django/srpproject/srp/views.py b/django/srpproject/srp/views.py
index 38d5503..8529fa9 100644
--- a/django/srpproject/srp/views.py
+++ b/django/srpproject/srp/views.py
@@ -2,7 +2,7 @@
from django.http import HttpResponse
-from srp import models
+from django.contrib.auth.models import User
###
### General methods
@@ -41,7 +41,7 @@ def register_page(request):
# 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 models.SRPUser.objects.filter(username=request.POST["I"]).count() > 0:
+ 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()
@@ -50,7 +50,8 @@ def register_salt(request):
# 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
- models.SRPUser(salt=request.session["srp_salt"], username=request.session["srp_name"], verifier=request.POST["v"]).save()
+ 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");
@@ -65,6 +66,7 @@ def register_user(request):
# 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)
@@ -72,15 +74,28 @@ def handshake(request):
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 = models.SRPUser.objects.get(username=request.session["srp_I"])
- salt = user.salt
- v = int(user.verifier, 16)
+ 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
+ x = int(hashlib.sha256(salt + hashlib.sha256(user.username + ":" + hashpass).hexdigest()).hexdigest(), 16)
+ v = pow(2, x, N)
+
# We don't want to leak that the username doesn't exist. Make up a fake salt and verifier.
- except models.SRPUser.DoesNotExist:
+ except User.DoesNotExist:
salt, x = generate_fake_salt(request.POST["I"])
v = pow(g, x, N)
@@ -91,31 +106,26 @@ def handshake(request):
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
- response = "<r s='%s' B='%s' />" % (salt, hex(B)[2:-1])
# 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])
- response = "<r s='%s' B='%s' />" % (salt, hex(B)[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
- try:
- 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>"
- except models.SRPUser.DoesNotExist:
- # This should only happen when authentication is successful with SRP, but the user isn't in the auth table.
- response = "<error>Authentication failed. This is likely a server problem.</error>"
+ 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"]
@@ -125,3 +135,27 @@ def verify(request):
except KeyError:
pass
return HttpResponse(response, mimetype="text/xml")
+
+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")
+
+def upgrade_add_verifier(request):
+ from srp.models import SRPUser
+ from django.contrib.auth.models import User
+ import hashlib
+ salt = generate_salt()
+ x = int(hashlib.sha256(salt + hashlib.sha256("%s:%s" % (request.session["srp_I"], request.POST["p"])).hexdigest()).hexdigest(), 16)
+ user = User.objects.get(username=request.session["srp_I"])
+ srpuser = SRPUser()
+ srpuser.__dict__.update(user.__dict__)
+ srpuser.verifier = hex(pow(2, x, 125617018995153554710546479714086468244499594888726646874671447258204721048803))[2:-1]
+ srpuser.salt = salt
+ srpuser.password = ""
+ srpuser.save()
+ return HttpResponse("<ok/>", mimetype="text/xml")