1a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch# Author: Trevor Perrin
2a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch# See the LICENSE file for legal information regarding use of this file.
3a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""Class for storing SRP password verifiers."""
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochfrom .utils.cryptomath import *
7a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochfrom .utils.compat import *
8a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochfrom tlslite import mathtls
9a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochfrom .basedb import BaseDB
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VerifierDB(BaseDB):
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """This class represent an in-memory or on-disk database of SRP
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    password verifiers.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    A VerifierDB can be passed to a server handshake to authenticate
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    a client based on one of the verifiers.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    This class is thread-safe.
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __init__(self, filename=None):
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Create a new VerifierDB instance.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @type filename: str
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param filename: Filename for an on-disk database, or None for
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        an in-memory database.  If the filename already exists, follow
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this with a call to open().  To create a new on-disk database,
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        follow this with a call to create().
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BaseDB.__init__(self, filename, "verifier")
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def _getItem(self, username, valueStr):
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (N, g, salt, verifier) = valueStr.split(" ")
33a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        N = bytesToNumber(a2b_base64(N))
34a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        g = bytesToNumber(a2b_base64(g))
35a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        salt = a2b_base64(salt)
36a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        verifier = bytesToNumber(a2b_base64(verifier))
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return (N, g, salt, verifier)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __setitem__(self, username, verifierEntry):
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Add a verifier entry to the database.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @type username: str
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param username: The username to associate the verifier with.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Must be less than 256 characters in length.  Must not already
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        be in the database.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @type verifierEntry: tuple
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param verifierEntry: The verifier entry to add.  Use
49a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        L{tlslite.verifierdb.VerifierDB.makeVerifier} to create a
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        verifier entry.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BaseDB.__setitem__(self, username, verifierEntry)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def _setItem(self, username, value):
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if len(username)>=256:
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise ValueError("username too long")
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        N, g, salt, verifier = value
59a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        N = b2a_base64(numberToByteArray(N))
60a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        g = b2a_base64(numberToByteArray(g))
61a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        salt = b2a_base64(salt)
62a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        verifier = b2a_base64(numberToByteArray(verifier))
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        valueStr = " ".join( (N, g, salt, verifier)  )
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return valueStr
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def _checkItem(self, value, username, param):
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (N, g, salt, verifier) = value
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        x = mathtls.makeX(salt, username, param)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        v = powMod(g, x, N)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return (verifier == v)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def makeVerifier(username, password, bits):
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Create a verifier entry which can be stored in a VerifierDB.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @type username: str
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param username: The username for this verifier.  Must be less
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        than 256 characters in length.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @type password: str
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param password: The password for this verifier.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @type bits: int
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param bits: This values specifies which SRP group parameters
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        to use.  It must be one of (1024, 1536, 2048, 3072, 4096, 6144,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        8192).  Larger values are more secure but slower.  2048 is a
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        good compromise between safety and speed.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @rtype: tuple
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @return: A tuple which may be stored in a VerifierDB.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
92a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        usernameBytes = bytearray(username, "utf-8")
93a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        passwordBytes = bytearray(password, "utf-8")
94a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        return mathtls.makeVerifier(usernameBytes, passwordBytes, bits)
95c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    makeVerifier = staticmethod(makeVerifier)
96