def new(password, server=defaultServer, clientId=None, username="******"): """ Encrypts a new @password by interacting with the Pythia service. @clientId: If specified, this value is used. If omitted, a suitable value is selected. @returns a tuple of required values to verify the password: (w,t,z,p) where: @w: client ID (key selector) @t: tweak (randomly generated user ID) @z: protected passwords @p: server public key bound to clientId - used to verify future proofs from this server. """ # Set the client ID if not clientId: w = secureRandom() else: w = clientId if ersatzHash == True: ersatzPw = "ersatz" ersatzHashGen = ersatzlib.ErsatzHashGenerator(hash.pbkdf2_sha1,\ username, password, \ ersatzPw, rounds=5000) #create ersatz salt t = ersatzHashGen._compute_ersatz_salt(password, ersatzPw) ersatzHashGen.salt = t a = ersatzHashGen._compute_ersatz_hash(password) a = passlib.utils.ab64_decode(a) #create ersatz input ersatzInput = ersatzHashGen._ersatzfy_input(password) z, p = query(ersatzInput, w, t, server) z = vpop.wrap( pyrelic.vpop.update(vpop.unwrapY(z), long(a.encode('hex'), 16))) #do the Z^a nonsense, where a is the pbkdf2 else: t = secureRandom() hashedPW = pbkdf2_sha1.encrypt(password, salt=t, rounds=5000) z, p = query(hashedPW, w, t, server) z = vpop.wrap( pyrelic.vpop.update(vpop.unwrapY(z), long(hashedPW.encode('hex'), 16))) #t = secureRandom() #z,p = query(password, w, t, server) return w, t, z, p
def check(password, w, t, z, p, server=defaultServer, username="******"): """ Checks an existing @password against the Pythia server using the values (w,t,z,p). @returns: True if the password passes authentication; False otherwise. """ if ersatzHash: ersatzHashGen = ersatzlib.ErsatzHashGenerator(hash.pbkdf2_sha1,\ username, password, \ "ersatz", rounds=5000) ersatzHashGen.salt = t ersatzInput = ersatzHashGen._ersatzfy_input(password) #check true password zPrime1, _ = query(ersatzInput, w, t, previousPubkey=p, server=server) zPrime2, _ = query(password, w, t, previousPubkey=p, server=server) #create ersatz salt a = passlib.utils.ab64_decode( ersatzHashGen._compute_ersatz_hash(password)) zPrime1 = vpop.wrap( pyrelic.vpop.update(vpop.unwrapY(zPrime1), long(a.encode('hex'), 16))) a = passlib.utils.ab64_decode( hash.pbkdf2_sha1.encrypt(password, salt=t, rounds=5000)) zPrime2 = vpop.wrap( pyrelic.vpop.update(vpop.unwrapY(zPrime2), long(a.encode('hex'), 16))) if z == zPrime1: return 1 elif z == zPrime2: return 2 else: return 0 #check ersatz password else: hashedPW = pbkdf2_sha1.encrypt(password, salt=t, rounds=5000) zPrime, _ = query(hashedPW, w, t, previousPubkey=p, server=server) zPrime = vpop.wrap( pyrelic.vpop.update(vpop.unwrapY(zPrime), long(hashedPW.encode('hex'), 16))) #zPrime,_ = query(password, w, t, previousPubkey=p, server=server) return z == zPrime
def new(password, server=defaultServer, clientId=None, username="******"): """ Encrypts a new @password by interacting with the Pythia service. @clientId: If specified, this value is used. If omitted, a suitable value is selected. @returns a tuple of required values to verify the password: (w,t,z,p) where: @w: client ID (key selector) @t: tweak (randomly generated user ID) @z: protected passwords @p: server public key bound to clientId - used to verify future proofs from this server. """ # Set the client ID if not clientId: w = secureRandom() else: w = clientId if ersatzHash == True: ersatzPw = "ersatz" ersatzHashGen = ersatzlib.ErsatzHashGenerator(hash.pbkdf2_sha1,\ username, password, \ ersatzPw, rounds=5000) #create ersatz salt t = ersatzHashGen._compute_ersatz_salt(password,ersatzPw) ersatzHashGen.salt = t a = ersatzHashGen._compute_ersatz_hash(password) a = passlib.utils.ab64_decode(a) #create ersatz input ersatzInput = ersatzHashGen._ersatzfy_input(password) z,p = query(ersatzInput, w, t, server) z = vpop.wrap(pyrelic.vpop.update(vpop.unwrapY(z), long(a.encode('hex'),16))) #do the Z^a nonsense, where a is the pbkdf2 else: t = secureRandom() hashedPW = pbkdf2_sha1.encrypt(password, salt=t, rounds=5000) z,p = query(hashedPW, w, t, server) z = vpop.wrap(pyrelic.vpop.update(vpop.unwrapY(z), long(hashedPW.encode('hex'),16))) #t = secureRandom() #z,p = query(password, w, t, server) return w, t, z, p
def update(wPrime,w,t,z,p,server=defaultServer): # Query the service via HTTP(S) GET response = fetch(queryUrlUpdateTemplate.format(server,w,wPrime)) # Grab the required fields from the response. pPrime,delta = extract(response, ["pPrime","delta"]) updatedZ = vpop.wrap(pyrelic.vpop.update(vpop.unwrapY(z), pyrelic.vpop.unwrapDelta(delta))) updateP = vpop.wrap(vpop.unwrapP(p)*vpop.unwrapLong(delta)) return wPrime, t, updatedZ, updateP
def update(wPrime, w, t, z, p, server=defaultServer): # Query the service via HTTP(S) GET response = fetch(queryUrlUpdateTemplate.format(server, w, wPrime)) # Grab the required fields from the response. pPrime, delta = extract(response, ["pPrime", "delta"]) updatedZ = vpop.wrap( pyrelic.vpop.update(vpop.unwrapY(z), pyrelic.vpop.unwrapDelta(delta))) updateP = vpop.wrap(vpop.unwrapP(p) * vpop.unwrapLong(delta)) return wPrime, t, updatedZ, updateP
def check(password, w, t, z, p, server=defaultServer, username="******"): """ Checks an existing @password against the Pythia server using the values (w,t,z,p). @returns: True if the password passes authentication; False otherwise. """ if ersatzHash: ersatzHashGen = ersatzlib.ErsatzHashGenerator(hash.pbkdf2_sha1,\ username, password, \ "ersatz", rounds=5000) ersatzHashGen.salt = t ersatzInput = ersatzHashGen._ersatzfy_input(password) #check true password zPrime1,_ = query(ersatzInput, w, t, previousPubkey=p, server=server) zPrime2,_ = query(password, w, t, previousPubkey=p, server=server) #create ersatz salt a = passlib.utils.ab64_decode(ersatzHashGen._compute_ersatz_hash(password)) zPrime1 = vpop.wrap(pyrelic.vpop.update(vpop.unwrapY(zPrime1), long(a.encode('hex'),16))) a = passlib.utils.ab64_decode(hash.pbkdf2_sha1.encrypt(password, salt=t, rounds=5000)) zPrime2 = vpop.wrap(pyrelic.vpop.update(vpop.unwrapY(zPrime2), long(a.encode('hex'),16))) if z == zPrime1: return 1 elif z == zPrime2: return 2 else: return 0 #check ersatz password else: hashedPW = pbkdf2_sha1.encrypt(password, salt=t, rounds=5000) zPrime,_ = query(hashedPW, w, t, previousPubkey=p, server=server) zPrime = vpop.wrap(pyrelic.vpop.update(vpop.unwrapY(zPrime), long(hashedPW.encode('hex'),16))) #zPrime,_ = query(password, w, t, previousPubkey=p, server=server) return z == zPrime
def eval(self,w,t,pw): """ Runs an eval and returns the result. """ # Blind and serialize the pw r,x = vpop.blind(pw) x = vpop.wrap(x) # Call the URL and verify the response response = self.client.get(VpopAdvTest.urlEval.format(w,t,x)) ySerial = str(self.check(response, "y")) # Deserialize and de-blind the result. y = vpop.unwrapY(ySerial) return vpop.deblind(r,y)
def testProof(self): """ Ensures the proof is valid. """ # Make an eval request r,x = vpop.blind(pw) xWrap = vpop.wrap(x) url = VpopEvalTest.urlTemplate.format(w,t,xWrap) r = self.parseResponse(self.client.get(url)) # Deserialize the items needed to verify the proof. y = vpop.unwrapY(r["y"]) pi = (vpop.unwrapP(r["p"]), vpop.unwrapC(r["c"]), vpop.unwrapU(r["u"]) ) # Test the proof self.assertTrue( vpop.verify(x, t, y, pi) )
def query(password, w, t, server=defaultServer, previousPubkey=None): """ Queries the a Pythia PRF service and verifies the server's ZKP. @returns (z,p) where: @z is the encrypted password and @p is the server's pubkey bound to clientId Raises an exception if there are any problems interacting with the service or if the server's ZKP fails verification. """ # Blind the password r, x = vpop.blind(password) xSerialized = vpop.wrap(x) # Query the service via HTTP(S) GET response = fetch(queryUrlTemplate.format(server, w, t, xSerialized)) # Grab the required fields from the response. p, y, c, u = extract(response, ["p", "y", "c", "u"]) # Check the pubkey if previousPubkey and previousPubkey != p: print "previous: " + previousPubkey print "p: " + p raise Exception( "Server-provided pubkey doesn't match previous pubkey.") # Deserialize the response fields p, y, c, u = (vpop.unwrapP(p), vpop.unwrapY(y), vpop.unwrapC(c), vpop.unwrapU(u)) pi = (p, c, u) # Verify the result by checking the proof vpop.verify(x, t, y, pi) # Deblind the result z = vpop.deblind(r, y) # Return the important fields in serialied form z, p = vpop.wrap(z), vpop.wrap(p) return z, p
def query(password, w, t, server=defaultServer, previousPubkey=None): """ Queries the a Pythia PRF service and verifies the server's ZKP. @returns (z,p) where: @z is the encrypted password and @p is the server's pubkey bound to clientId Raises an exception if there are any problems interacting with the service or if the server's ZKP fails verification. """ # Blind the password r,x = vpop.blind(password) xSerialized = vpop.wrap(x) # Query the service via HTTP(S) GET response = fetch(queryUrlTemplate.format(server,w,t,xSerialized)) # Grab the required fields from the response. p,y,c,u = extract(response, ["p","y","c","u"]) # Check the pubkey if previousPubkey and previousPubkey != p: print "previous: " + previousPubkey print "p: "+ p raise Exception("Server-provided pubkey doesn't match previous pubkey.") # Deserialize the response fields p,y,c,u = (vpop.unwrapP(p), vpop.unwrapY(y), vpop.unwrapC(c), vpop.unwrapU(u)) pi = (p,c,u) # Verify the result by checking the proof vpop.verify(x, t, y, pi) # Deblind the result z = vpop.deblind(r,y) # Return the important fields in serialied form z,p = vpop.wrap(z), vpop.wrap(p) return z,p