Пример #1
0
    def test_02_encrypt_decrypt_eas_base64(self):
        import os
        key = os.urandom(16)
        data = b"This is so secret!"
        s = aes_encrypt_b64(key, data)
        d = aes_decrypt_b64(key, s)
        self.assertEqual(data, d)

        otp_seed = os.urandom(20)
        s = aes_encrypt_b64(key, otp_seed)
        d = aes_decrypt_b64(key, s)
        self.assertEqual(otp_seed, d)

        otp_seed = os.urandom(32)
        s = aes_encrypt_b64(key, otp_seed)
        d = aes_decrypt_b64(key, s)
        self.assertEqual(otp_seed, d)

        # check some data generated with 2.23
        hex_key = 'f84c2ddb09dee2a88194d5ac2156a8e4'
        data = b'secret data'
        enc_data = 'WNfUSNBNZF5kaPfujW8ueUi5Afas47pQ/3FHc3VymWM='
        d = aes_decrypt_b64(binascii.unhexlify(hex_key), enc_data)
        self.assertEqual(data, d)
        enc_data = 'RDDvdAJhCnw/tlYscTxv+6idHAQnQFY5VpUK8SFflYQ='
        d = aes_decrypt_b64(binascii.unhexlify(hex_key), enc_data)
        self.assertEqual(data, d)
Пример #2
0
    def test_02_encrypt_decrypt_eas_base64(self):
        import os
        key = os.urandom(16)
        data = b"This is so secret!"
        s = aes_encrypt_b64(key, data)
        d = aes_decrypt_b64(key, s)
        self.assertEqual(data, d)

        otp_seed = os.urandom(20)
        s = aes_encrypt_b64(key, otp_seed)
        d = aes_decrypt_b64(key, s)
        self.assertEqual(otp_seed, d)

        otp_seed = os.urandom(32)
        s = aes_encrypt_b64(key, otp_seed)
        d = aes_decrypt_b64(key, s)
        self.assertEqual(otp_seed, d)

        # check some data generated with 2.23
        hex_key = 'f84c2ddb09dee2a88194d5ac2156a8e4'
        data = b'secret data'
        enc_data = 'WNfUSNBNZF5kaPfujW8ueUi5Afas47pQ/3FHc3VymWM='
        d = aes_decrypt_b64(binascii.unhexlify(hex_key), enc_data)
        self.assertEqual(data, d)
        enc_data = 'RDDvdAJhCnw/tlYscTxv+6idHAQnQFY5VpUK8SFflYQ='
        d = aes_decrypt_b64(binascii.unhexlify(hex_key), enc_data)
        self.assertEqual(data, d)
Пример #3
0
    def test_02_encrypt_decrypt_eas_base64(self):
        import os
        key = os.urandom(16)
        data = b"This is so secret!"
        s = aes_encrypt_b64(key, data)
        d = aes_decrypt_b64(key, s)
        self.assertEqual(data, d)

        otp_seed = os.urandom(20)
        s = aes_encrypt_b64(key, otp_seed)
        d = aes_decrypt_b64(key, s)
        self.assertEqual(otp_seed, d)

        otp_seed = os.urandom(32)
        s = aes_encrypt_b64(key, otp_seed)
        d = aes_decrypt_b64(key, s)
        self.assertEqual(otp_seed, d)
Пример #4
0
    def test_02_encrypt_decrypt_eas_base64(self):
        import os
        key = os.urandom(16)
        data = "This is so secret!"
        s = aes_encrypt_b64(key, data)
        d = aes_decrypt_b64(key, s)
        self.assertEqual(data, d)

        otp_seed = os.urandom(20)
        s = aes_encrypt_b64(key, otp_seed)
        d = aes_decrypt_b64(key, s)
        self.assertEqual(otp_seed, d)

        otp_seed = os.urandom(32)
        s = aes_encrypt_b64(key, otp_seed)
        d = aes_decrypt_b64(key, s)
        self.assertEqual(otp_seed, d)
Пример #5
0
def parsePSKCdata(xml_data,
                  preshared_key_hex=None,
                  password=None,
                  do_checkserial=False):
    """
    This function parses XML data of a PSKC file, (RFC6030)
    It can read
    * AES-128-CBC encrypted (preshared_key_bin) data
    * password based encrypted data
    * plain text data

    :param xml_data: The XML data
    :type xml_data: basestring
    :param preshared_key_hex: The preshared key, hexlified
    :param password: The password that encrypted the keys
    :param do_checkserial: Check if the serial numbers conform to the OATH
        specification (not yet implemented)

    :return: a dictionary of token dictionaries
        { serial : { otpkey , counter, .... }}
    """

    tokens = {}
    #xml = BeautifulSoup(xml_data, "lxml")
    xml = strip_prefix_from_soup(BeautifulSoup(xml_data, "lxml"))

    if xml.keycontainer.encryptionkey and \
            xml.keycontainer.encryptionkey.derivedkey:
        # If we have a password we also need a tag EncryptionKey in the
        # KeyContainer
        preshared_key_hex = derive_key(xml, password)

    key_packages = xml.keycontainer.findAll("keypackage")
    for key_package in key_packages:
        token = {}
        key = key_package.key
        try:
            token["description"] = key_package.deviceinfo.manufacturer.string
        except Exception as exx:
            log.debug("Can not get manufacturer string {0!s}".format(exx))
        serial = key["id"]
        try:
            serial = key_package.deviceinfo.serialno.string.strip()
        except Exception as exx:
            log.debug("Can not get serial string from device info {0!s}".format(exx))
        algo = key["algorithm"]
        token["type"] = algo.split(":")[-1].lower()
        parameters = key.algorithmparameters
        token["otplen"] = parameters.responseformat["length"] or 6
        try:
            token["hashlib"] = parameters.suite["hashalgo"] or "sha1"
        except Exception as exx:
            log.warning("No compatible suite contained.")
        try:
            if key.data.secret.plainvalue:
                secret = key.data.secret.plainvalue.string
                token["otpkey"] = hexlify_and_unicode(base64.b64decode(secret))
            elif key.data.secret.encryptedvalue:
                encryptionmethod = key.data.secret.encryptedvalue.encryptionmethod
                enc_algorithm = encryptionmethod["algorithm"].split("#")[-1]
                if enc_algorithm.lower() != "aes128-cbc":
                    raise ImportException("We only import PSKC files with "
                                          "AES128-CBC.")
                enc_data = key.data.secret.encryptedvalue.ciphervalue.text
                enc_data = enc_data.strip()
                secret = aes_decrypt_b64(binascii.unhexlify(preshared_key_hex), enc_data)
                if token["type"].lower() in ["hotp", "totp"]:
                    token["otpkey"] = hexlify_and_unicode(secret)
                elif token["type"].lower() in ["pw"]:
                    token["otpkey"] = to_unicode(secret)
                else:
                    token["otpkey"] = to_unicode(secret)
        except Exception as exx:
            log.error("Failed to import tokendata: {0!s}".format(exx))
            log.debug(traceback.format_exc())
            raise ImportException("Failed to import tokendata. Wrong "
                                  "encryption key? %s" % exx)
        if token["type"] in ["hotp", "totp"] and key.data.counter:
            token["counter"] = key.data.counter.text.strip()
        if token["type"] == "totp":
            if key.data.timeinterval:
                token["timeStep"] = key.data.timeinterval.text.strip()
            if key.data.timedrift:
                token["timeShift"] = key.data.timedrift.text.strip()

        tokens[serial] = token
    return tokens
Пример #6
0
def parsePSKCdata(xml_data,
                  preshared_key_hex=None,
                  password=None,
                  do_checkserial=False):
    """
    This function parses XML data of a PSKC file, (RFC6030)
    It can read
    * AES-128-CBC encrypted (preshared_key_bin) data
    * password based encrypted data
    * plain text data

    :param xml_data: The XML data
    :type xml_data: basestring
    :param preshared_key_hex: The preshared key, hexlified
    :param password: The password that encrypted the keys
    :param do_checkserial: Check if the serial numbers conform to the OATH
        specification (not yet implemented)

    :return: a dictionary of token dictionaries
        { serial : { otpkey , counter, .... }}
    """

    tokens = {}
    #xml = BeautifulSoup(xml_data, "lxml")
    xml = strip_prefix_from_soup(BeautifulSoup(xml_data, "lxml"))

    if xml.keycontainer.encryptionkey and \
            xml.keycontainer.encryptionkey.derivedkey:
        # If we have a password we also need a tag EncryptionKey in the
        # KeyContainer
        preshared_key_hex = derive_key(xml, password)

    key_packages = xml.keycontainer.findAll("keypackage")
    for key_package in key_packages:
        token = {}
        key = key_package.key
        try:
            token["description"] = key_package.deviceinfo.manufacturer.string
        except Exception as exx:
            log.debug("Can not get manufacturer string {0!s}".format(exx))
        serial = key["id"]
        try:
            serial = key_package.deviceinfo.serialno.string.strip()
        except Exception as exx:
            log.debug(
                "Can not get serial string from device info {0!s}".format(exx))
        algo = key["algorithm"]
        token["type"] = algo.split(":")[-1].lower()
        parameters = key.algorithmparameters
        token["otplen"] = parameters.responseformat["length"] or 6
        try:
            token["hashlib"] = parameters.suite["hashalgo"] or "sha1"
        except Exception as exx:
            log.warning("No compatible suite contained.")
        try:
            if key.data.secret.plainvalue:
                secret = key.data.secret.plainvalue.string
                token["otpkey"] = binascii.hexlify(base64.b64decode(secret))
            elif key.data.secret.encryptedvalue:
                encryptionmethod = key.data.secret.encryptedvalue.encryptionmethod
                enc_algorithm = encryptionmethod["algorithm"].split("#")[-1]
                if enc_algorithm.lower() != "aes128-cbc":
                    raise ImportException("We only import PSKC files with "
                                          "AES128-CBC.")
                enc_data = key.data.secret.encryptedvalue.ciphervalue.text
                enc_data = enc_data.strip()
                secret = aes_decrypt_b64(binascii.unhexlify(preshared_key_hex),
                                         enc_data)
                token["otpkey"] = binascii.hexlify(secret)
        except Exception as exx:
            log.error("Failed to import tokendata: {0!s}".format(exx))
            log.debug(traceback.format_exc())
            raise ImportException("Failed to import tokendata. Wrong "
                                  "encryption key? %s" % exx)
        if token["type"] in ["hotp", "totp"] and key.data.counter:
            token["counter"] = key.data.counter.text.strip()
        if token["type"] == "totp":
            if key.data.timeinterval:
                token["timeStep"] = key.data.timeinterval.text.strip()
            if key.data.timedrift:
                token["timeShift"] = key.data.timedrift.text.strip()

        tokens[serial] = token
    return tokens
Пример #7
0
def parsePSKCdata(xml_data,
                  preshared_key_hex=None,
                  password=None,
                  validate_mac='check_fail_hard',
                  do_checkserial=False):
    """
    This function parses XML data of a PSKC file, (RFC6030)
    It can read
    * AES-128-CBC encrypted (preshared_key_bin) data
    * password based encrypted data
    * plain text data

    :param xml_data: The XML data
    :type xml_data: basestring
    :param preshared_key_hex: The preshared key, hexlified
    :param password: The password that encrypted the keys
    :param do_checkserial: Check if the serial numbers conform to the OATH
        specification (not yet implemented)
    :param validate_mac: Operation mode of hmac validation. Possible values:
        - 'check_fail_hard' : If an invalid hmac is encountered no token gets parsed.
        - 'check_fail_soft' : Skip tokens with invalid MAC.
        - 'no_check' : Hmac of tokens are not checked, every token is parsed.

    :return: tuple of a dictionary of token dictionaries and a list of serial of not imported tokens
        { serial : { otpkey , counter, .... }}, [serial, serial, ...]
    """

    abort = False

    not_imported_serials = []
    tokens = {}
    xml = strip_prefix_from_soup(BeautifulSoup(xml_data, "lxml"))

    if not xml.keycontainer:
        raise ImportException("No KeyContainer found in PSKC data. Could not "
                              "import any tokens.")
    if xml.keycontainer.encryptionkey and \
            xml.keycontainer.encryptionkey.derivedkey:
        # If we have a password we also need a tag EncryptionKey in the
        # KeyContainer
        preshared_key_hex = derive_key(xml, password)

    key_packages = xml.keycontainer.findAll("keypackage")
    for key_package in key_packages:
        token = {}
        key = key_package.key
        try:
            token["description"] = key_package.deviceinfo.manufacturer.string
        except Exception as exx:
            log.debug("Can not get manufacturer string {0!s}".format(exx))
        serial = key["id"]
        try:
            serial = key_package.deviceinfo.serialno.string.strip()
        except Exception as exx:
            log.debug(
                "Can not get serial string from device info {0!s}".format(exx))
        algo = key["algorithm"]
        token["type"] = algo.split(":")[-1].lower()
        parameters = key.algorithmparameters
        token["otplen"] = parameters.responseformat["length"] or 6
        try:
            token["hashlib"] = parameters.suite["hashalgo"] or "sha1"
        except Exception as exx:
            log.warning("No compatible suite contained.")
        try:
            if key.data.secret.plainvalue:
                secret = key.data.secret.plainvalue.string
                token["otpkey"] = hexlify_and_unicode(base64.b64decode(secret))
            elif key.data.secret.encryptedvalue:
                encryptionmethod = key.data.secret.encryptedvalue.encryptionmethod
                enc_algorithm = encryptionmethod["algorithm"].split("#")[-1]
                if enc_algorithm.lower() != "aes128-cbc":
                    raise ImportException("We only import PSKC files with "
                                          "AES128-CBC.")
                enc_data = key.data.secret.encryptedvalue.ciphervalue.text
                enc_data = enc_data.strip()

                preshared_key = binascii.unhexlify(preshared_key_hex)

                secret = aes_decrypt_b64(preshared_key, enc_data)

                if token["type"].lower() in ["hotp", "totp"]:
                    token["otpkey"] = hexlify_and_unicode(secret)
                elif token["type"].lower() in ["pw"]:
                    token["otpkey"] = to_unicode(secret)
                else:
                    token["otpkey"] = to_unicode(secret)

                if validate_mac != 'no_check':
                    # Validate MAC:
                    encrypted_mac_key = xml.keycontainer.find("mackey").text
                    mac_key = aes_decrypt_b64(preshared_key, encrypted_mac_key)

                    enc_data_bin = base64.b64decode(enc_data)
                    hm = hmac.new(key=mac_key,
                                  msg=enc_data_bin,
                                  digestmod=hashlib.sha1)
                    mac_value_calculated = b64encode_and_unicode(hm.digest())

                    mac_value_xml = key.data.find('valuemac').text.strip()

                    is_invalid = not hmac.compare_digest(
                        mac_value_xml, mac_value_calculated)

                    if is_invalid and validate_mac == 'check_fail_hard':
                        abort = True
                    elif is_invalid and validate_mac == 'check_fail_soft':
                        not_imported_serials.append(serial)
                        continue

        except Exception as exx:
            log.error("Failed to import tokendata: {0!s}".format(exx))
            log.debug(traceback.format_exc())
            raise ImportException("Failed to import tokendata. Wrong "
                                  "encryption key? %s" % exx)

        if token["type"] in ["hotp", "totp"] and key.data.counter:
            token["counter"] = key.data.counter.text.strip()
        if token["type"] == "totp":
            if key.data.timeinterval:
                token["timeStep"] = key.data.timeinterval.text.strip()
            if key.data.timedrift:
                token["timeShift"] = key.data.timedrift.text.strip()

        tokens[serial] = token

    if abort:
        not_imported_serials = tokens.keys()
        tokens = {}  # reset tokens

    return tokens, not_imported_serials