コード例 #1
0
ファイル: totptoken.py プロジェクト: ask0n/privacyidea
    def get_otp(self, current_time=None, do_truncation=True, time_seconds=None, challenge=None):
        """
        get the next OTP value

        :param current_time: the current time, for which the OTP value
        should be calculated for.
        :type current_time: datetime object
        :param time_seconds: the current time, for which the OTP value
        should be calculated for (date +%s)
        :type: time_seconds: int, unix system time seconds
        :return: next otp value, and PIN, if possible
        :rtype: tuple
        """
        otplen = int(self.token.otplen)
        secretHOtp = self.token.get_otpkey()

        hmac2Otp = HmacOtp(secretHOtp, self.get_otp_count(), otplen, self.get_hashlib(self.hashlib))

        if time_seconds is None:
            time_seconds = self._time2float(datetime.datetime.now())
        if current_time:
            time_seconds = self._time2float(current_time)

        # we don't need to round here as we have already float
        counter = int(((time_seconds - self.timeshift) / self.timestep))
        otpval = hmac2Otp.generate(counter=counter, inc_counter=False, do_truncation=do_truncation, challenge=challenge)

        pin = self.token.get_pin()
        combined = "%s%s" % (otpval, pin)
        if get_from_config("PrependPin") == "True":
            combined = "%s%s" % (pin, otpval)

        return 1, pin, otpval, combined
コード例 #2
0
ファイル: totptoken.py プロジェクト: R00tAK/privacyidea
    def get_multi_otp(self, count=0, epoch_start=0, epoch_end=0,
                      curTime=None, timestamp=None):
        """
        return a dictionary of multiple future OTP values
        of the HOTP/HMAC token

        :param count: how many otp values should be returned
        :type count: int
        :param epoch_start: not implemented
        :param epoch_end: not implemented
        :param curTime: Simulate the servertime
        :type curTime: datetime
        :param timestamp: Simulate the servertime
        :type timestamp: epoch time
        :return: tuple of status: boolean, error: text and the OTP dictionary

        """
        otp_dict = {"type": "TOTP", "otp": {}}
        ret = False
        error = "No count specified"

        otplen = int(self.token.otplen)
        secretHOtp = self.token.get_otpkey()

        hmac2Otp = HmacOtp(secretHOtp, self.get_otp_count(),
                           otplen, self.get_hashlib(self.hashlib))

        if curTime:
            # datetime object provided for simulation
            tCounter = self._time2float(curTime)
        elif timestamp:
            # epoch time provided for simulation
            tCounter = int(timestamp)
        else:
            # use the current server time
            tCounter = self._time2float(datetime.datetime.now())

        # we don't need to round here as we have alread float
        counter = int(((tCounter - self.timeshift) / self.timestep))

        otp_dict["shift"] = self.timeshift
        otp_dict["timeStepping"] = self.timeshift

        if count > 0:
            error = "OK"
            for i in range(0, count):
                otpval = hmac2Otp.generate(counter=counter + i,
                                           inc_counter=False)
                timeCounter = ((counter + i) * self.timestep) + self.timeshift
                
                val_time = datetime.datetime.\
                    fromtimestamp(timeCounter).strftime("%Y-%m-%d %H:%M:%S")
                otp_dict["otp"][counter + i] = {'otpval': otpval,
                                                'time': val_time}
            ret = True
            
        return ret, error, otp_dict
コード例 #3
0
    def get_multi_otp(self, count=0, epoch_start=0, epoch_end=0,
                      curTime=None, timestamp=None):
        """
        return a dictionary of multiple future OTP values
        of the HOTP/HMAC token

        :param count: how many otp values should be returned
        :type count: int
        :param epoch_start: not implemented
        :param epoch_end: not implemented
        :param curTime: Simulate the servertime
        :type curTime: datetime
        :param timestamp: Simulate the servertime
        :type timestamp: epoch time
        :return: tuple of status: boolean, error: text and the OTP dictionary

        """
        otp_dict = {"type": "TOTP", "otp": {}}
        ret = False
        error = "No count specified"

        otplen = int(self.token.otplen)
        secretHOtp = self.token.get_otpkey()

        hmac2Otp = HmacOtp(secretHOtp, self.get_otp_count(),
                           otplen, self.get_hashlib(self.hashlib))

        if curTime:
            # datetime object provided for simulation
            tCounter = self._time2float(curTime)
        elif timestamp:
            # epoch time provided for simulation
            tCounter = int(timestamp)
        else:
            # use the current server time
            tCounter = self._time2float(datetime.datetime.now())

        # we don't need to round here as we have alread float
        counter = int(((tCounter - self.timeshift) / self.timestep))

        otp_dict["shift"] = self.timeshift
        otp_dict["timeStepping"] = self.timeshift

        if count > 0:
            error = "OK"
            for i in range(0, count):
                otpval = hmac2Otp.generate(counter=counter + i,
                                           inc_counter=False)
                timeCounter = ((counter + i) * self.timestep) + self.timeshift
                
                val_time = datetime.datetime.\
                    fromtimestamp(timeCounter).strftime("%Y-%m-%d %H:%M:%S")
                otp_dict["otp"][counter + i] = {'otpval': otpval,
                                                'time': val_time}
            ret = True
            
        return ret, error, otp_dict
コード例 #4
0
ファイル: totptoken.py プロジェクト: splashx/privacyidea
    def get_otp(self,
                current_time=None,
                do_truncation=True,
                time_seconds=None,
                challenge=None):
        """
        get the next OTP value

        :param current_time: the current time, for which the OTP value
        should be calculated for.
        :type current_time: datetime object
        :param time_seconds: the current time, for which the OTP value
        should be calculated for (date +%s)
        :type: time_seconds: int, unix system time seconds
        :return: next otp value, and PIN, if possible
        :rtype: tuple
        """
        otplen = int(self.token.otplen)
        secretHOtp = self.token.get_otpkey()

        hmac2Otp = HmacOtp(secretHOtp, self.get_otp_count(), otplen,
                           self.get_hashlib(self.hashlib))

        if time_seconds is None:
            time_seconds = self._time2float(datetime.datetime.now())
        if current_time:
            time_seconds = self._time2float(current_time)

        # we don't need to round here as we have already float
        counter = int(((time_seconds - self.timeshift) / self.timestep))
        otpval = hmac2Otp.generate(counter=counter,
                                   inc_counter=False,
                                   do_truncation=do_truncation,
                                   challenge=challenge)

        pin = self.token.get_pin()
        combined = "{0!s}{1!s}".format(otpval, pin)
        if get_from_config("PrependPin") == "True":
            combined = "{0!s}{1!s}".format(pin, otpval)

        return 1, pin, otpval, combined
コード例 #5
0
ファイル: ocra.py プロジェクト: segfault/privacyidea
class OCRA(object):
    def __init__(self, ocrasuite, key=None, security_object=None):
        """
        Creates an OCRA Object that can be used to calculate OTP response or
        verify a response.

        :param ocrasuite: The ocrasuite description
        :type ocrasuite: str
        :param security_object: A privacyIDEA security object, that can be
            used to look up the key in the database
        :type security_object: secObject as defined in privacyidea.lib.crypto
        :param key: The HMAC Key
        :type key: binary
        :return: OCRA Object
        """
        self.ocrasuite_obj = OCRASuite(ocrasuite)
        self.ocrasuite = ocrasuite
        self.key = key
        self.security_obj = security_object

        digits = self.ocrasuite_obj.truncation
        self.hmac_obj = HmacOtp(secObj=self.security_obj,
                                digits=digits,
                                hashfunc=SHA_FUNC.get(self.ocrasuite_obj.sha))

    def create_data_input(self,
                          question,
                          pin=None,
                          pin_hash=None,
                          counter=None,
                          timesteps=None):
        """
        Create the data_input to be used in the HMAC function
        In case of QN the question would be "111111"
        In case of QA the question would be "123ASD"
        In case of QH the question would be "BEEF"

        The question is transformed internally.

        :param question: The question can be
        :type question: str

        :param pin_hash: The hash of the pin
        :type pin_hash: basestring (hex)
        :param timesteps: timestemps
        :type timesteps: hex string
        :return: data_input
        :rtype: bytes
        """
        # In case the ocrasuite comes as a unicode (like from the webui) we
        # need to convert it!
        data_input = to_bytes(self.ocrasuite) + b'\0'
        # Check for counter
        if self.ocrasuite_obj.counter == "C":
            if counter:
                counter = int(counter)
                counter = struct.pack('>Q', int(counter))
                data_input += counter
            else:
                raise Exception(
                    "The ocrasuite {0!s} requires a counter".format(
                        self.ocrasuite))
        # Check for Question
        if self.ocrasuite_obj.challenge_type == "QN":
            # question contains only numeric values
            hex_q = '{0:x}'.format(int(question))
            hex_q += '0' * (len(hex_q) % 2)
            bin_q = binascii.unhexlify(hex_q)
            bin_q += b'\x00' * (128 - len(bin_q))
            data_input += bin_q
        elif self.ocrasuite_obj.challenge_type == "QA":
            # question contains alphanumeric characters
            bin_q = to_bytes(question)
            bin_q += b'\x00' * (128 - len(bin_q))
            data_input += bin_q
        elif self.ocrasuite_obj.challenge_type == "QH":
            # qustion contains hex values
            bin_q = binascii.unhexlify(question)
            bin_q += b'\x00' * (128 - len(bin_q))
            data_input += bin_q

        # in case of PIN
        if self.ocrasuite_obj.signature_type == "P":
            if pin_hash:
                data_input += binascii.unhexlify(pin_hash)
            elif pin:
                pin_hash = SHA_FUNC.get(self.ocrasuite_obj.signature_hash)(
                    to_bytes(pin)).digest()
                data_input += pin_hash
            else:
                raise Exception("The ocrasuite {0!s} requires a PIN!".format(
                    self.ocrasuite))
        elif self.ocrasuite_obj.signature_type == "T":
            if not timesteps:
                raise Exception(
                    "The ocrasuite {0!s} requires timesteps".format(
                        self.ocrasuite))
            # In case of Time
            timesteps = int(timesteps, 16)
            timesteps = struct.pack('>Q', int(timesteps))
            data_input += timesteps
        elif self.ocrasuite_obj.signature_type == "S":  # pragma: no cover
            # In case of session
            # TODO: Session not yet implemented
            raise NotImplementedError("OCRA Session not implemented, yet.")
        return data_input

    def get_response(self,
                     question,
                     pin=None,
                     pin_hash=None,
                     counter=None,
                     timesteps=None):
        """
        Create an OTP response from the given input values.

        :param question:
        :param pin:
        :param pin_hash:
        :param counter:
        :return:
        """
        data_input = self.create_data_input(question,
                                            pin=pin,
                                            pin_hash=pin_hash,
                                            counter=counter,
                                            timesteps=timesteps)
        r = self.hmac_obj.generate(key=self.key,
                                   challenge=binascii.hexlify(data_input))
        return r

    def check_response(self,
                       response,
                       question=None,
                       pin=None,
                       pin_hash=None,
                       counter=None,
                       timesteps=None):
        """
        Check the given *response* if it is the correct response to the
        challenge/question.

        :param response:
        :param question:
        :param pin:
        :param pin_hash:
        :param counter:
        :param timesteps:
        :return:
        """
        r = self.get_response(question,
                              pin=pin,
                              pin_hash=pin_hash,
                              counter=counter,
                              timesteps=timesteps)
        if r == response:
            return 1
        else:
            return -1
コード例 #6
0
ファイル: ocra.py プロジェクト: STRML/privacyidea
class OCRA(object):

    def __init__(self, ocrasuite, key=None, security_object=None):
        """
        Creates an OCRA Object that can be used to calculate OTP response or
        verify a response.

        :param ocrasuite: The ocrasuite description
        :type ocrasuite: basestring
        :param security_object: A privacyIDEA security object, that can be
            used to look up the key in the database
        :type security_object: secObject as defined in privacyidea.lib.crypto
        :param key: The HMAC Key
        :type key: binary
        :return: OCRA Object
        """
        self.ocrasuite_obj = OCRASuite(ocrasuite)
        self.ocrasuite = str(ocrasuite)
        self.key = key
        self.security_obj = security_object

        digits = self.ocrasuite_obj.truncation
        self.hmac_obj = HmacOtp(secObj=self.security_obj,
                                digits=digits,
                                hashfunc=SHA_FUNC.get(self.ocrasuite_obj.sha))

    def create_data_input(self, question, pin=None, pin_hash=None,
                          counter=None, timesteps=None):
        """
        Create the data_input to be used in the HMAC function
        In case of QN the question would be "111111"
        In case of QA the question would be "123ASD"
        In case of QH the question would be "BEEF"

        The question is transformed internally.

        :param question: The question can be
        :type question: basestring

        :param pin_hash: The hash of the pin
        :type pin_hash: basestring (hex)
        :param timesteps: timestemps
        :type timesteps: hex string
        :return: data_input
        :rytpe: binary
        """
        # In case the ocrasuite comes as a unicode (like from the webui) we
        # need to convert it!
        data_input = str(self.ocrasuite) + b'\0'
        # Check for counter
        if self.ocrasuite_obj.counter == "C":
            if counter:
                counter = int(counter)
                counter = struct.pack('>Q', int(counter))
                data_input += counter
            else:
                raise Exception("The ocrasuite {0!s} requires a counter".format(
                                self.ocrasuite))
        # Check for Question
        if self.ocrasuite_obj.challenge_type == "QN":
            # In case of QN
            question = '{0:x}'.format(int(question))
            question += '0' * (len(question) % 2)
            question = binascii.unhexlify(question)
            question += '\0' * (128-len(question))
            data_input += question
        elif self.ocrasuite_obj.challenge_type == "QA":
            question += '\0' * (128-len(question))
            data_input += question
        elif self.ocrasuite_obj.challenge_type == "QH":  # pragma: no cover
            question = binascii.unhexlify(question)
            question += '\0' * (128-len(question))
            data_input += question

        # in case of PIN
        if self.ocrasuite_obj.signature_type == "P":
            if pin_hash:
                data_input += binascii.unhexlify(pin_hash)
            elif pin:
                pin_hash = SHA_FUNC.get(self.ocrasuite_obj.signature_hash)(
                    pin).digest()
                data_input += pin_hash
            else:
                raise Exception("The ocrasuite {0!s} requires a PIN!".format(
                                self.ocrasuite))
        elif self.ocrasuite_obj.signature_type == "T":
            if not timesteps:
                raise Exception("The ocrasuite {0!s} requires timesteps".format(
                                self.ocrasuite))
            # In case of Time
            timesteps = int(timesteps, 16)
            timesteps = struct.pack('>Q', int(timesteps))
            data_input += timesteps
        elif self.ocrasuite_obj.signature_type == "S":  # pragma: no cover
            # In case of session
            # TODO: Session not yet implemented
            raise NotImplementedError("OCRA Session not implemented, yet.")
        return data_input

    def get_response(self, question, pin=None, pin_hash=None, counter=None,
                     timesteps=None):
        """
        Create an OTP response from the given input values.

        :param question:
        :param pin:
        :param pin_hash:
        :param counter:
        :return:
        """
        data_input = self.create_data_input(question,
                                            pin=pin,
                                            pin_hash=pin_hash,
                                            counter=counter,
                                            timesteps=timesteps)
        r = self.hmac_obj.generate(key=self.key,
                                   challenge=binascii.hexlify(data_input))
        return r

    def check_response(self, response, question=None, pin=None,
                       pin_hash=None, counter=None, timesteps=None):
        """
        Check the given *response* if it is the correct response to the
        challenge/question.

        :param response:
        :param question:
        :param pin:
        :param pin_hash:
        :param counter:
        :param timesteps:
        :return:
        """
        r = self.get_response(question, pin=pin, pin_hash=pin_hash,
                              counter=counter, timesteps=timesteps)
        if r == response:
            return 1
        else:
            return -1