def run(self, secret, salt, keylen):
        """
        run scrypt kdf for specified secret, salt, and keylen

        .. note::

            * time cost is ``O(n * r * p)``
            * mem cost is ``O(n * r)``
        """
        # stretch salt into initial byte array via pbkdf2
        iv_bytes = self.iv_bytes
        input = pbkdf2_hmac("sha256", secret, salt, rounds=1, keylen=iv_bytes)

        # split initial byte array into 'p' mflen-sized chunks,
        # and run each chunk through smix() to generate output chunk.
        smix = self.smix
        if self.p == 1:
            output = smix(input)
        else:
            # XXX: *could* use threading here, if really high p values encountered,
            #      but would tradeoff for more memory usage.
            smix_bytes = self.smix_bytes
            output = b"".join(
                smix(input[offset:offset + smix_bytes])
                for offset in range(0, iv_bytes, smix_bytes))

        # stretch final byte array into output via pbkdf2
        return pbkdf2_hmac("sha256", secret, output, rounds=1, keylen=keylen)
示例#2
0
文件: scram.py 项目: dragoncsc/HDsite
    def derive_digest(cls, password, salt, rounds, alg):
        """helper to create SaltedPassword digest for SCRAM.

        This performs the step in the SCRAM protocol described as::

            SaltedPassword  := Hi(Normalize(password), salt, i)

        :type password: unicode or utf-8 bytes
        :arg password: password to run through digest

        :type salt: bytes
        :arg salt: raw salt data

        :type rounds: int
        :arg rounds: number of iterations.

        :type alg: str
        :arg alg: name of digest to use (e.g. ``"sha-1"``).

        :returns:
            raw bytes of ``SaltedPassword``
        """
        if isinstance(password, bytes):
            password = password.decode("utf-8")
        # NOTE: pbkdf2_hmac() will encode secret & salt using utf-8,
        #       and handle normalizing alg name.
        return pbkdf2_hmac(alg, saslprep(password), salt, rounds)
示例#3
0
 def test_known(self):
     """test reference vectors"""
     for row in self.pbkdf2_test_vectors:
         correct, secret, salt, rounds, keylen = row[:5]
         digest = row[5] if len(row) == 6 else "sha1"
         result = pbkdf2_hmac(digest, secret, salt, rounds, keylen)
         self.assertEqual(result, correct)
示例#4
0
    def derive_digest(cls, password, salt, rounds, alg):
        """helper to create SaltedPassword digest for SCRAM.

        This performs the step in the SCRAM protocol described as::

            SaltedPassword  := Hi(Normalize(password), salt, i)

        :type password: unicode or utf-8 bytes
        :arg password: password to run through digest

        :type salt: bytes
        :arg salt: raw salt data

        :type rounds: int
        :arg rounds: number of iterations.

        :type alg: str
        :arg alg: name of digest to use (e.g. ``"sha-1"``).

        :returns:
            raw bytes of ``SaltedPassword``
        """
        if isinstance(password, bytes):
            password = password.decode("utf-8")
        # NOTE: pbkdf2_hmac() will encode secret & salt using utf-8,
        #       and handle normalizing alg name.
        return pbkdf2_hmac(alg, saslprep(password), salt, rounds)
示例#5
0
 def test_known(self):
     """test reference vectors"""
     for row in self.pbkdf2_test_vectors:
         correct, secret, salt, rounds, keylen = row[:5]
         digest = row[5] if len(row) == 6 else "sha1"
         result = pbkdf2_hmac(digest, secret, salt, rounds, keylen)
         self.assertEqual(result, correct)
示例#6
0
    def generate_symmetric_key(self, server_component, client_component,
                               options=None):
        """
        Generate a composite key from a server and client component
        using a PBKDF2-based scheme.

        :param server_component: The component usually generated by privacyIDEA
        :type server_component: hex string
        :param client_component: The component usually generated by the
            client (e.g. smartphone)
        :type client_component: hex string
        :param options:
        :return: the new generated key as hex string
        :rtype: str
        """
        # As /token/init has already been called before, self.hashlib
        # is already set.
        keysize = keylen[self.hashlib]
        rounds = int(self.get_tokeninfo('2step_difficulty'))
        decoded_client_component = binascii.unhexlify(client_component)
        expected_client_size = int(self.get_tokeninfo('2step_clientsize'))
        if expected_client_size != len(decoded_client_component):
            raise ParameterError('Client Secret Size is expected to be {}, but is {}'.format(
                expected_client_size, len(decoded_client_component)
            ))
        # Based on the two components, we generate a symmetric key using PBKDF2
        # We pass the hex-encoded server component as the password and the
        # client component as the salt.
        secret = pbkdf2_hmac(digest='sha1',
                             secret=server_component.lower(),
                             salt=decoded_client_component,
                             rounds=rounds,
                             keylen=keysize)
        return hexlify_and_unicode(secret)
示例#7
0
文件: utils.py 项目: RPI-HPC/totp-cgi
def decrypt_secret(b64str, pincode):
    # split the secret into components
    try:
        (scheme, salt, ciphertext) = b64str.split('$')

        salt = base64.b64decode(salt)
        ciphertext = base64.b64decode(ciphertext)

    except (ValueError, TypeError):
        raise totpcgi.UserSecretError('Failed to parse encrypted secret')

    key = pbkdf2_hmac('sha256', pincode, salt, KDF_ITER, KEY_SIZE * 2)

    aes_key = key[:KEY_SIZE]
    hmac_key = key[KEY_SIZE:]

    sig_size = hashlib.sha256().digest_size
    sig = ciphertext[-sig_size:]
    data = ciphertext[:-sig_size]

    # verify hmac sig first
    if hmac.new(hmac_key, data, hashlib.sha256).digest() != sig:
        raise totpcgi.UserSecretError('Failed to verify hmac!')

    iv_bytes = data[:AES_BLOCK_SIZE]
    data = data[AES_BLOCK_SIZE:]

    cypher = AES.new(aes_key, AES.MODE_CBC, iv_bytes)
    data = cypher.decrypt(data)
    padlen = bytearray((data[-1], ))[0]
    secret = data[:-padlen].decode('utf-8')

    logger.debug('Decryption successful')

    return secret
示例#8
0
def derive_key(xml, password):
    """
    Derive the encryption key from the password with the parameters given
    in the XML soup.

    :param xml: The XML
    :param password: the password
    :return: The derived key, hexlified
    """
    if not password:
        raise ImportException("The XML KeyContainer specifies a derived "
                              "encryption key, but no password given!")

    keymeth = xml.keycontainer.encryptionkey.derivedkey.keyderivationmethod
    derivation_algo = keymeth["algorithm"].split("#")[-1]
    if derivation_algo.lower() != "pbkdf2":
        raise ImportException("We only support PBKDF2 as Key derivation "
                              "function!")
    salt = keymeth.find("salt").text.strip()
    keylength = keymeth.find("keylength").text.strip()
    rounds = keymeth.find("iterationcount").text.strip()
    r = pbkdf2_hmac('sha1',
                    to_utf8(password),
                    base64.b64decode(salt),
                    rounds=int(rounds),
                    keylen=int(keylength))
    return binascii.hexlify(r)
示例#9
0
文件: utils.py 项目: RPI-HPC/totp-cgi
def encrypt_secret(strdata, pincode):
    data = strdata.encode('utf-8')
    salt = os.urandom(SALT_SIZE)

    # derive a twice-long key from pincode
    key = pbkdf2_hmac('sha256', pincode, salt, KDF_ITER, KEY_SIZE * 2)

    # split the key in two, one used for AES, another for HMAC
    aes_key = key[:KEY_SIZE]
    hmac_key = key[KEY_SIZE:]

    pad = AES_BLOCK_SIZE - len(data) % AES_BLOCK_SIZE
    data += pad * bytearray((pad, ))
    iv_bytes = os.urandom(AES_BLOCK_SIZE)
    cypher = AES.new(aes_key, AES.MODE_CBC, iv_bytes)
    data = iv_bytes + cypher.encrypt(data)
    sig = hmac.new(hmac_key, data, hashlib.sha256).digest()

    # jab it all together in a base64-encrypted format
    b64str = ('aes256+hmac256$' +
              base64.b64encode(salt).decode('utf-8').replace('\n', '') + '$' +
              base64.b64encode(data + sig).decode('utf-8').replace('\n', ''))

    logger.debug('Encrypted secret: %s', b64str)

    return b64str
示例#10
0
文件: keybag.py 项目: ydkhatri/pyaff4
 def create(password):
     salt = Random.get_random_bytes(saltSize)
     vek = Random.get_random_bytes(keysize)
     #print("VEK: " + str(binascii.hexlify(vek)))
     kek = digest.pbkdf2_hmac("sha256", password, salt, iterations, keysize);
     wrapped_key = aes_wrap_key(kek, vek)
     #print("WrappedKey: " + str(binascii.hexlify(wrapped_key)))
     return PasswordWrappedKeyBag(salt, iterations, keysize, wrapped_key)
 def test_30_2step_otpkeyformat(self):
     serial = "2step3"
     db_token = Token(serial, tokentype="hotp")
     db_token.save()
     token = HotpTokenClass(db_token)
     token.update({
         "2stepinit": "1",
         "2step_clientsize": "12",
         "hashlib": "sha512",
     })
     self.assertEqual(token.token.rollout_state, "clientwait")
     self.assertEqual(token.get_tokeninfo("2step_clientsize"), "12")
     # fetch the server component for later tests
     server_component = binascii.unhexlify(
         token.token.get_otpkey().getKey())
     # generate a 12-byte client component
     client_component = b'abcdefghijkl'
     checksum = hashlib.sha1(client_component).digest()[:4]
     # wrong checksum
     with warnings.catch_warnings():
         warnings.simplefilter('ignore', category=DeprecationWarning)
         self.assertRaisesRegexp(
             ParameterError, "Incorrect checksum", token.update, {
                 "otpkey":
                 b32encode_and_unicode(b"\x37" + checksum[1:] +
                                       client_component).strip("="),
                 "otpkeyformat":
                 "base32check",
             })
     # construct a secret
     token.update({
         "otpkey":
         b32encode_and_unicode(checksum + client_component).strip("="),
         "otpkeyformat":
         "base32check",
         # the following values are ignored
         "2step_serversize":
         "23",
         "2step_difficulty":
         "666666",
         "2step_clientsize":
         "13"
     })
     # check the generated secret
     secret = binascii.unhexlify(token.token.get_otpkey().getKey())
     # check the correct lengths
     self.assertEqual(len(server_component), 64)  # because of SHA-512
     self.assertEqual(len(client_component), 12)
     self.assertEqual(len(secret), 64)  # because of SHA-512
     # check the secret has been generated according to the specification
     expected_secret = pbkdf2_hmac('sha1',
                                   binascii.hexlify(server_component),
                                   client_component, 10000, len(secret))
     self.assertEqual(secret, expected_secret)
     self.assertTrue(token.token.active)
示例#12
0
    def testExtractWrappedKey(self):
        wrapped = binascii.unhexlify("5934f7d07e75f5ab55b9051ebd39331dbfba3c597589b203728043577bf93badeb9f07f528c8bd95")
        target_kek = binascii.unhexlify("9bc68a8c80a008d758de97cebc7ec39d6274512e3ddbdd5baf4eb8557ab7e58f")
        target_vek = binascii.unhexlify("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")

        g = rdflib.Graph()
        g.parse(data=keybagturtle, format="turtle")
        kb = keybag.PasswordWrappedKeyBag.load(g)

        key = "password"
        kek = digest.pbkdf2_hmac("sha256", key, kb.salt, kb.iterations, kb.keySizeBytes);
        self.assertEquals(target_kek, kek)
        vek = aes_unwrap_key(kek, kb.wrappedKey)
        self.assertEquals(target_vek, vek)
示例#13
0
 async def add_mattermost_server(self, host, team, password):
     curs = db.cursor()
     curs.execute("SELECT host, team, password FROM mattermost_accounts WHERE user=?", (self.internal_id, ))
     if curs.fetchall():
         await self.reply('Sorry, no support for multiple servers yet')
         return
     key = pbkdf2_hmac('sha256', self.actual_password, self.nick, 10000)
     iv = Random.new().read(AES.block_size)
     cipher = AES.new(key, AES.MODE_CFB, iv)
     msg = iv + cipher.encrypt(password)
     curs.execute("INSERT INTO mattermost_accounts (user, host, team, password) VALUES (?,?,?,?)", (self.internal_id, host, team, base64.b64encode(msg)))
     db.commit()
     await self.reply('New server added')
     await self.connect_to_mattermost()
示例#14
0
    def raw(cls, secret, user):
        """encode password using msdcc v2 algorithm

        :type secret: unicode or utf-8 bytes
        :arg secret: secret

        :type user: str
        :arg user: username to use as salt

        :returns: returns string of raw bytes
        """
        from passlib.crypto.digest import pbkdf2_hmac
        secret = to_unicode(secret, "utf-8", param="secret").encode("utf-16-le")
        user = to_unicode(user, "utf-8", param="user").lower().encode("utf-16-le")
        tmp = md4(md4(secret).digest() + user).digest()
        return pbkdf2_hmac("sha1", tmp, user, 10240, 16)
示例#15
0
    def testDecrypt(self):

        g = rdflib.Graph()
        g.parse(data=keybagturtle, format="turtle")
        kb = keybag.PasswordWrappedKeyBag.load(g)

        key = "password"
        kek = digest.pbkdf2_hmac("sha256", key, kb.salt, kb.iterations, kb.keySizeBytes);
        vek = aes_unwrap_key(kek, kb.wrappedKey)

        key1 = vek[0:16]
        key2 = vek[16:]
        tweak = codecs.decode('00', 'hex')

        cipher = python_AES.new((key1, key2), python_AES.MODE_XTS)
        text = cipher.decrypt(target_ciphertext, tweak)

        self.assertEqual(src[0:len(src)], text[0:len(src)])
示例#16
0
    def raw(cls, secret, user):
        """encode password using msdcc v2 algorithm

        :type secret: unicode or utf-8 bytes
        :arg secret: secret

        :type user: str
        :arg user: username to use as salt

        :returns: returns string of raw bytes
        """
        from passlib.crypto.digest import pbkdf2_hmac
        secret = to_unicode(secret, "utf-8",
                            param="secret").encode("utf-16-le")
        user = to_unicode(user, "utf-8",
                          param="user").lower().encode("utf-16-le")
        tmp = md4(md4(secret).digest() + user).digest()
        return pbkdf2_hmac("sha1", tmp, user, 10240, 16)
示例#17
0
 async def connect_to_mattermost(self):
     curs = db.cursor()
     curs.execute("SELECT host, team, password FROM mattermost_accounts WHERE user=?", (self.internal_id, ))
     servers = curs.fetchall()
     if len(servers) == 0:
         await self.reply('No mattermost servers configured yet, not connecting to anything')
     elif len(servers) == 1:
         for host, team, pwd in servers:
             await self.reply('Connecting to server {0}'.format(host))
             # Decrypt the password. Strart by un-b64ing it
             key = pbkdf2_hmac('sha256', self.actual_password, self.nick, 10000)
             msg = base64.b64decode(pwd)
             dec = AES.new(key, AES.MODE_CFB, msg[:16])
             password = dec.decrypt(msg[16:]).decode('utf8')
             self.team_name = team
             asyncio.ensure_future(self.mattermost_handler(host, password))
     else:
         await self.reply('XXX: Multiple servers not implemented yet')
示例#18
0
 async def add_mattermost_server(self, host, team, password):
     curs = db.cursor()
     curs.execute(
         "SELECT host, team, password FROM mattermost_accounts WHERE user=?",
         (self.internal_id, ))
     if curs.fetchall():
         await self.reply('Sorry, no support for multiple servers yet')
         return
     key = pbkdf2_hmac('sha256', self.actual_password, self.nick, 10000)
     iv = Random.new().read(AES.block_size)
     cipher = AES.new(key, AES.MODE_CFB, iv)
     msg = iv + cipher.encrypt(password)
     curs.execute(
         "INSERT INTO mattermost_accounts (user, host, team, password) VALUES (?,?,?,?)",
         (self.internal_id, host, team, base64.b64encode(msg)))
     db.commit()
     await self.reply('New server added')
     await self.connect_to_mattermost()
示例#19
0
    def _check_pbkdf2sha256(self, password, hash):
        hashParts = hash.split("$")
        if len(hashParts) == 4 and hashParts[0] == "PBKDF2SHA256":
            iterations = int(hashParts[1])
            saltBytes = bytes.fromhex(hashParts[2])
            storedHash = bytes.fromhex(hashParts[3])

            computedHash = pbkdf2_hmac(
                digest="sha256",
                secret=password,
                salt=saltBytes,
                rounds=iterations,
            )

            return storedHash == computedHash
        else:
            self.logger.warning("Unknown seafile hash-format: %s", hash)
            return False
 def test_29_2step_generation_custom(self):
     serial = "2step2"
     db_token = Token(serial, tokentype="hotp")
     db_token.save()
     token = HotpTokenClass(db_token)
     token.update({
         "2stepinit": "1",
         "2step_serversize": "40",
         "2step_difficulty": "12345",
         "2step_clientsize": "12",
         "hashlib": "sha512",
     })
     self.assertEqual(token.token.rollout_state, "clientwait")
     self.assertEqual(token.get_tokeninfo("2step_clientsize"), "12")
     self.assertEqual(token.get_tokeninfo("2step_difficulty"), "12345")
     # fetch the server component for later tests
     server_component = binascii.unhexlify(
         token.token.get_otpkey().getKey())
     # too short
     self.assertRaises(ParameterError, token.update,
                       {"otpkey": binascii.hexlify(b"=" * 8)})
     # generate a 12-byte client component
     client_component = b'abcdefghijkl'
     # construct a secret
     token.update({
         "otpkey": binascii.hexlify(client_component),
         # the following values are ignored
         "2step_serversize": "23",
         "2step_difficulty": "666666",
         "2step_clientsize": "13"
     })
     # check the generated secret
     secret = binascii.unhexlify(token.token.get_otpkey().getKey())
     # check the correct lengths
     self.assertEqual(len(server_component), 40)
     self.assertEqual(len(client_component), 12)
     self.assertEqual(len(secret), 64)  # because of SHA-512
     # check the secret has been generated according to the specification
     expected_secret = pbkdf2_hmac('sha1',
                                   binascii.hexlify(server_component),
                                   client_component, 12345, len(secret))
     self.assertEqual(secret, expected_secret)
     self.assertTrue(token.token.active)
示例#21
0
def pbkdf2(secret, salt, rounds, keylen=None, prf="hmac-sha1"):
    """pkcs#5 password-based key derivation v2.0

    :arg secret:
        passphrase to use to generate key

    :arg salt:
        salt string to use when generating key

    :param rounds:
        number of rounds to use to generate key

    :arg keylen:
        number of bytes to generate.
        if set to ``None``, will use digest size of selected prf.

    :param prf:
        psuedo-random family to use for key strengthening.
        this must be a string starting with ``"hmac-"``, followed by the name of a known digest.
        this defaults to ``"hmac-sha1"`` (the only prf explicitly listed in
        the PBKDF2 specification)

        .. rst-class:: warning

        .. versionchanged 1.7:

            This argument no longer supports arbitrary PRF callables --
            These were rarely / never used, and created too many unwanted codepaths.

    :returns:
        raw bytes of generated key

    .. deprecated:: 1.7

        This has been deprecated in favor of :func:`passlib.crypto.digest.pbkdf2_hmac`,
        and will be removed in Passlib 2.0.  *Note the call signature has changed.*
    """
    if callable(prf) or (isinstance(prf, native_string_types)
                         and not prf.startswith(_HMAC_PREFIXES)):
        raise NotImplementedError(
            "non-HMAC prfs are not supported as of Passlib 1.7")
    digest = prf[5:]
    return pbkdf2_hmac(digest, secret, salt, rounds, keylen)
示例#22
0
def pbkdf2(secret, salt, rounds, keylen=None, prf="hmac-sha1"):
    """pkcs#5 password-based key derivation v2.0

    :arg secret:
        passphrase to use to generate key

    :arg salt:
        salt string to use when generating key

    :param rounds:
        number of rounds to use to generate key

    :arg keylen:
        number of bytes to generate.
        if set to ``None``, will use digest size of selected prf.

    :param prf:
        psuedo-random family to use for key strengthening.
        this must be a string starting with ``"hmac-"``, followed by the name of a known digest.
        this defaults to ``"hmac-sha1"`` (the only prf explicitly listed in
        the PBKDF2 specification)

        .. rst-class:: warning

        .. versionchanged 1.7:

            This argument no longer supports arbitrary PRF callables --
            These were rarely / never used, and created too many unwanted codepaths.

    :returns:
        raw bytes of generated key

    .. deprecated:: 1.7

        This has been deprecated in favor of :func:`passlib.crypto.digest.pbkdf2_hmac`,
        and will be removed in Passlib 2.0.  *Note the call signature has changed.*
    """
    if callable(prf) or (isinstance(prf, native_string_types) and not prf.startswith(_HMAC_PREFIXES)):
        raise NotImplementedError("non-HMAC prfs are not supported as of Passlib 1.7")
    digest = prf[5:]
    return pbkdf2_hmac(digest, secret, salt, rounds, keylen)
示例#23
0
    def testWrap(self):
        keysize = 0x20   # in bytes
        key = "password"
        iterations = 147256
        saltSize = 16
        salt = binascii.unhexlify("000102030405060708090a0b0c0d0e0f")


        #hhh = hashlib.pbkdf2_hmac("sha256", key.encode(), salt, iterations, keysize);
        #print(len(hhh))
        #print(binascii.hexlify(hhh))

        kek = digest.pbkdf2_hmac("sha256", key, salt, iterations, keysize);
        print(binascii.hexlify(kek))

        #h = pbkdf2_sha256.encrypt(key, rounds=iterations, salt_size=saltSize)
        # print(h)



        vek = binascii.unhexlify("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
        print(len(vek))
        wrapped_key= aes_wrap_key(kek, vek)
        print(binascii.hexlify(wrapped_key))

        plaintext = src + b'\x00' * (512-len(src))

        #msg = dict_xts_aes['msg%i' % i].decode('hex')
        #key = (dict_xts_aes['key1_%i' % i].decode('hex'), dict_xts_aes['key2_%i' % i].decode('hex'))
        key1 = vek[0:16]
        key2 = vek[16:]
        #cip = dict_xts_aes['cip%i' % i].decode('hex')
        #n = dict_xts_aes['n%i' % i].decode('hex')
        tweak = codecs.decode('00', 'hex')
        print(len(tweak))
        cipher = python_AES.new((key1,key2), python_AES.MODE_XTS)
        ciphertext = cipher.encrypt(plaintext, tweak)

        print(len(ciphertext))
        print(binascii.hexlify(ciphertext))
示例#24
0
 def test_28_2step_generation_default(self):
     serial = "2step"
     db_token = Token(serial, tokentype="hotp")
     db_token.save()
     token = HotpTokenClass(db_token)
     token.update({"2stepinit": "1"})
     # fetch the server component for later tests
     server_component = binascii.unhexlify(token.token.get_otpkey().getKey())
     # generate a 8-byte client component
     client_component = b'abcdefgh'
     # construct a secret
     token.update({"otpkey": binascii.hexlify(client_component)})
     # check the generated secret
     secret = binascii.unhexlify(token.token.get_otpkey().getKey())
     # check the correct lengths
     self.assertEqual(len(server_component), 20)
     self.assertEqual(len(client_component), 8)
     self.assertEqual(len(secret), 20)
     # check the secret has been generated according to the specification
     expected_secret = pbkdf2_hmac('sha1', binascii.hexlify(server_component),
                                   client_component, 10000, 20)
     self.assertEqual(secret, expected_secret)
示例#25
0
 async def connect_to_mattermost(self):
     curs = db.cursor()
     curs.execute(
         "SELECT host, team, password FROM mattermost_accounts WHERE user=?",
         (self.internal_id, ))
     servers = curs.fetchall()
     if len(servers) == 0:
         await self.reply(
             'No mattermost servers configured yet, not connecting to anything'
         )
     elif len(servers) == 1:
         for host, team, pwd in servers:
             await self.reply('Connecting to server {0}'.format(host))
             # Decrypt the password. Strart by un-b64ing it
             key = pbkdf2_hmac('sha256', self.actual_password, self.nick,
                               10000)
             msg = base64.b64decode(pwd)
             dec = AES.new(key, AES.MODE_CFB, msg[:16])
             password = dec.decrypt(msg[16:]).decode('utf8')
             self.team_name = team
             asyncio.ensure_future(self.mattermost_handler(host, password))
     else:
         await self.reply('XXX: Multiple servers not implemented yet')
示例#26
0
def derive_key(xml, password):
    """
    Derive the encryption key from the password with the parameters given
    in the XML soup.

    :param xml: The XML
    :param password: the password
    :return: The derived key, hexlified
    """
    if not password:
        raise ImportException("The XML KeyContainer specifies a derived "
                              "encryption key, but no password given!")

    keymeth= xml.keycontainer.encryptionkey.derivedkey.keyderivationmethod
    derivation_algo = keymeth["algorithm"].split("#")[-1]
    if derivation_algo.lower() != "pbkdf2":
        raise ImportException("We only support PBKDF2 as Key derivation "
                              "function!")
    salt = keymeth.find("salt").text.strip()
    keylength = keymeth.find("keylength").text.strip()
    rounds = keymeth.find("iterationcount").text.strip()
    r = pbkdf2_hmac('sha1', to_utf8(password), base64.b64decode(salt),
                    rounds=int(rounds), keylen=int(keylength))
    return binascii.hexlify(r)
示例#27
0
 def _calc_checksum(self, secret):
     # TODO: find out what crowd's policy is re: unicode
     # crowd seems to use a fixed number of rounds.
     # NOTE: pbkdf2_hmac() will encode secret & salt using utf-8
     return pbkdf2_hmac("sha1", secret, self.salt, 10000, 32)
示例#28
0
 def _calc_checksum(self, secret):
     # TODO: find out what grub's policy is re: unicode
     # NOTE: pbkdf2_hmac() will encode secret & salt using utf-8
     return pbkdf2_hmac("sha512", secret, self.salt, self.rounds, 64)
示例#29
0
    def test_06_force_totp_parameters(self):
        set_policy(
            name="force_2step",
            action=["totp_2step=force", "enrollTOTP=1", "delete"],
            scope=SCOPE.ADMIN,
        )
        set_policy(
            name="2step_params",
            action=[
                "totp_2step_difficulty=12345", "totp_2step_serversize=33",
                "totp_2step_clientsize=11"
            ],
            scope=SCOPE.ENROLL,
        )
        with self.app.test_request_context(
                '/token/init',
                method='POST',
                data={
                    "type": "totp",
                    "genkey": "1",
                    "2stepinit": "0",  # will be forced nevertheless
                    "2step_serversize": "3",
                    "2step_clientsize": "4",
                    "2step_difficulty": "33333",
                    "timeStep": "60",
                    "hashlib": "sha512",
                    "otplen": "8",
                },
                headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = res.json.get("result")
            self.assertTrue(result.get("status") is True, result)
            self.assertTrue(result.get("value") is True, result)
            detail = res.json.get("detail")
            serial = detail.get("serial")
            otpkey_url = detail.get("otpkey", {}).get("value")
            server_component = binascii.unhexlify(otpkey_url.split("/")[2])
            google_url = detail["googleurl"]["value"]
            self.assertIn('2step_difficulty=12345', google_url)
            self.assertIn('2step_salt=11', google_url)
            self.assertIn('2step_output=64', google_url)
        # Authentication does not work yet!
        wrong_otp_value = HmacOtp(digits=8, hashfunc=hashlib.sha512).generate(
            key=server_component, counter=int(time.time() // 60))
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           data={
                                               "serial": serial,
                                               "pass": wrong_otp_value
                                           }):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = res.json
            self.assertTrue(result.get("result").get("status"))
            self.assertFalse(result.get("result").get("value"))
            self.assertEqual(
                result.get("detail").get("message"),
                u'matching 1 tokens, Token is disabled')

        client_component = b"wrongsize"  # 9 bytes
        hex_client_component = binascii.hexlify(client_component)

        # Supply a client secret of incorrect size
        with self.app.test_request_context('/token/init',
                                           method='POST',
                                           data={
                                               "type": "totp",
                                               "serial": serial,
                                               "otpkey": hex_client_component,
                                           },
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 400, res)
            result = res.json.get("result")
            self.assertFalse(result.get("status"))

        client_component = b"correctsize"  # 11 bytes
        hex_client_component = binascii.hexlify(client_component)

        # Now doing the correct 2nd step
        with self.app.test_request_context(
                '/token/init',
                method='POST',
                data={
                    "type": "totp",
                    "serial": serial,
                    "otpkey": hex_client_component,
                    "2step_serversize": "3",  # will have no effect
                    "2step_clientsize": "4",
                    "2step_difficulty": "33333"
                },
                headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = res.json.get("result")
            self.assertTrue(result.get("status") is True, result)
            self.assertTrue(result.get("value") is True, result)
            detail = res.json.get("detail")
            otpkey_url = detail.get("otpkey", {}).get("value")
            otpkey = otpkey_url.split("/")[2]

        # Now try to authenticate
        otpkey_bin = binascii.unhexlify(otpkey)
        otp_value = HmacOtp(digits=8, hashfunc=hashlib.sha512).generate(
            key=otpkey_bin, counter=int(time.time() // 60))
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           data={
                                               "serial": serial,
                                               "pass": otp_value
                                           }):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = res.json.get("result")
            self.assertEqual(result.get("status"), True)
            self.assertEqual(result.get("value"), True)

        # Check serversize
        self.assertEqual(len(server_component), 33)
        # Check that the OTP key is what we expected it to be
        expected_secret = pbkdf2_hmac('sha1',
                                      binascii.hexlify(server_component),
                                      client_component, 12345, 64)
        self.assertEqual(otpkey_bin, expected_secret)

        with self.app.test_request_context('/token/' + serial,
                                           method='DELETE',
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)

        delete_policy("force_2step")
        delete_policy("2step_params")
示例#30
0
    def test_05_init_totp_token(self):
        set_policy(
            name="allow_2step",
            action=["totp_2step=allow", "enrollTOTP=1", "delete"],
            scope=SCOPE.ADMIN,
        )
        with self.app.test_request_context('/token/init',
                                           method='POST',
                                           data={
                                               "type": "totp",
                                               "genkey": "1",
                                               "2stepinit": "1"
                                           },
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = res.json.get("result")
            self.assertTrue(result.get("status") is True, result)
            self.assertTrue(result.get("value") is True, result)
            detail = res.json.get("detail")
            serial = detail.get("serial")
            otpkey_url = detail.get("otpkey", {}).get("value")
            server_component = binascii.unhexlify(otpkey_url.split("/")[2])
            google_url = detail["googleurl"]["value"]
            self.assertIn('2step_difficulty=10000', google_url)
            self.assertIn('2step_salt=8', google_url)
            self.assertIn('2step_output=20', google_url)
            self.assertEqual(detail['2step_difficulty'], 10000)
            self.assertEqual(detail['2step_salt'], 8)
            self.assertEqual(detail['2step_output'], 20)

        client_component = b"VRYSECRT"
        checksum = hashlib.sha1(client_component).digest()[:4]
        base32check_client_component = base64.b32encode(
            checksum + client_component).strip(b"=")

        # Try to do a 2stepinit on a second step will raise an error
        with self.app.test_request_context('/token/init',
                                           method='POST',
                                           data={
                                               "type": "totp",
                                               "2stepinit": "1",
                                               "serial": serial,
                                               "otpkey":
                                               base32check_client_component,
                                               "otpkeyformat": "base32check"
                                           },
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 400)
            result = res.json.get("result")
            self.assertIn(
                '2stepinit is only to be used in the first initialization step',
                result.get("error").get("message"))

        # Invalid base32check will raise an error
        with self.app.test_request_context(
                '/token/init',
                method='POST',
                data={
                    "type": "totp",
                    "2stepinit": "1",
                    "serial": serial,
                    "otpkey": b"A" + base32check_client_component[1:],
                    "otpkeyformat": "base32check"
                },
                headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 400)
            result = res.json.get("result")
            self.assertIn('Malformed base32check data: Incorrect checksum',
                          result.get("error").get("message"))

        # Authentication does not work yet!
        wrong_otp_value = HmacOtp().generate(key=server_component,
                                             counter=int(time.time() // 30))
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           data={
                                               "serial": serial,
                                               "pass": wrong_otp_value
                                           }):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = res.json
            self.assertTrue(result.get("result").get("status"))
            self.assertFalse(result.get("result").get("value"))
            self.assertEqual(
                result.get("detail").get("message"),
                u'matching 1 tokens, Token is disabled')

        # Now doing the correct 2nd step
        with self.app.test_request_context('/token/init',
                                           method='POST',
                                           data={
                                               "type": "totp",
                                               "serial": serial,
                                               "otpkey":
                                               base32check_client_component,
                                               "otpkeyformat": "base32check"
                                           },
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = res.json.get("result")
            self.assertTrue(result.get("status") is True, result)
            self.assertTrue(result.get("value") is True, result)
            detail = res.json.get("detail")
            otpkey_url = detail.get("otpkey", {}).get("value")
            otpkey = otpkey_url.split("/")[2]
            self.assertNotIn('2step', detail)

        # Now try to authenticate
        otpkey_bin = binascii.unhexlify(otpkey)
        otp_value = HmacOtp().generate(key=otpkey_bin,
                                       counter=int(time.time() // 30))
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           data={
                                               "serial": serial,
                                               "pass": otp_value
                                           }):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = res.json.get("result")
            self.assertEqual(result.get("status"), True)
            self.assertEqual(result.get("value"), True)

        # Check that the OTP key is what we expected it to be
        expected_secret = pbkdf2_hmac('sha1',
                                      binascii.hexlify(server_component),
                                      client_component, 10000, 20)
        self.assertEqual(otpkey_bin, expected_secret)

        with self.app.test_request_context('/token/' + serial,
                                           method='DELETE',
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
        delete_policy("allow_2step")
示例#31
0
 def _calc_checksum(self, secret):
     # NOTE: pbkdf2_hmac() will encode secret & salt using utf-8
     return pbkdf2_hmac("sha1", secret, self.salt, self.rounds, 20)
示例#32
0
 def helper(secret=b'password',
            salt=b'salt',
            rounds=1,
            keylen=None,
            digest="sha1"):
     return pbkdf2_hmac(digest, secret, salt, rounds, keylen)
示例#33
0
 def _calc_checksum(self, secret):
     # NOTE: pbkdf2_hmac() will encode secret & salt using UTF8
     return pbkdf2_hmac(self._digest, secret, self.salt, self.rounds, self.checksum_size)
示例#34
0
 def _calc_checksum(self, secret):
     # NOTE: pbkdf2_hmac() will encode secret & salt using UTF8
     return pbkdf2_hmac(self._digest, secret, self.salt, self.rounds,
                        self.checksum_size)
示例#35
0
 def _calc_checksum(self, secret):
     # TODO: find out what grub's policy is re: unicode
     # NOTE: pbkdf2_hmac() will encode secret & salt using utf-8
     return pbkdf2_hmac("sha512", secret, self.salt, self.rounds, 64)
示例#36
0
 def _calc_checksum(self, secret):
     # TODO: find out what crowd's policy is re: unicode
     # crowd seems to use a fixed number of rounds.
     # NOTE: pbkdf2_hmac() will encode secret & salt using utf-8
     return pbkdf2_hmac("sha1", secret, self.salt, 10000, 32)
示例#37
0
 def _calc_checksum(self, secret):
     # NOTE: pbkdf2_hmac() will encode secret & salt using utf-8
     salt = self._get_config()
     result = pbkdf2_hmac("sha1", secret, salt, self.rounds, 24)
     return ab64_encode(result).decode("ascii")
示例#38
0
 def _calc_checksum(self, secret):
     # NOTE: pbkdf2_hmac() will encode secret & salt using utf-8
     salt = self._get_config()
     result = pbkdf2_hmac("sha1", secret, salt, self.rounds, 24)
     return ab64_encode(result).decode("ascii")
示例#39
0
 def _calc_checksum(self, secret):
     # NOTE: pbkdf2_hmac() will encode secret & salt using utf-8
     return pbkdf2_hmac("sha1", secret, self.salt, self.rounds, 20)
示例#40
0
 def helper():
     result = hexlify(
         pbkdf2_hmac("sha1", "abracadabra", "open sesame", 10240, 20))
     assert result == 'e45ce658e79b16107a418ad4634836f5f0601ad1', result
示例#41
0
 def _calc_checksum(self, secret):
     # NOTE: secret & salt will be encoded using UTF-8 by pbkdf2_hmac()
     hash = pbkdf2_hmac(self._digest, secret, self.salt, self.rounds)
     return b64encode(hash).rstrip().decode("ascii")
示例#42
0
 def helper():
     result = hexlify(
         pbkdf2_hmac("sha256", "abracadabra", "open sesame", 10240, 32))
     assert result == 'fadef97054306c93c55213cd57111d6c0791735dcdde8ac32f9f934b49c5af1e', result
示例#43
0
    def test_03_custom_parameters(self):
        set_policy(
            name="enrollhotp",
            action=["enrollHOTP=1", "delete", "hotp_2step=allow"],
            scope=SCOPE.ADMIN,
        )
        with self.app.test_request_context(
                '/token/init',
                method='POST',
                data={
                    "type": "hotp",
                    "genkey": "1",
                    "2stepinit": "1",
                    "2step_serversize": "5",
                    "2step_clientsize": "16",
                    "2step_difficulty": "17898",
                    "hashlib": "sha512",  # force 64-byte secret
                    "otplen": "8",
                },
                headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = res.json.get("result")
            self.assertTrue(result.get("status") is True, result)
            self.assertTrue(result.get("value") is True, result)
            detail = res.json.get("detail")
            serial = detail.get("serial")
            otpkey_url = detail.get("otpkey", {}).get("value")
            server_component = binascii.unhexlify(otpkey_url.split("/")[2])

        client_component = b"wrongsize0"  # 10 bytes
        hex_client_component = binascii.hexlify(client_component)

        # Supply a client secret of incorrect size
        with self.app.test_request_context('/token/init',
                                           method='POST',
                                           data={
                                               "type": "hotp",
                                               "serial": serial,
                                               "otpkey": hex_client_component,
                                           },
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 400, res)
            result = res.json.get("result")
            self.assertFalse(result.get("status"))

        client_component = b"correctsizeABCDE"  # 16 bytes
        hex_client_component = binascii.hexlify(client_component)

        # Now doing the correct 2nd step
        with self.app.test_request_context(
                '/token/init',
                method='POST',
                data={
                    "type": "hotp",
                    "serial": serial,
                    "otpkey": hex_client_component,
                    "2step_serversize": "3",  # will have no effect
                    "2step_clientsize": "4",
                    "2step_difficulty": "33333"
                },
                headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = res.json.get("result")
            self.assertTrue(result.get("status") is True, result)
            self.assertTrue(result.get("value") is True, result)
            detail = res.json.get("detail")
            otpkey_url = detail.get("otpkey", {}).get("value")
            otpkey = otpkey_url.split("/")[2]

        # Now try to authenticate
        otpkey_bin = binascii.unhexlify(otpkey)
        otp_value = HmacOtp(digits=8,
                            hashfunc=hashlib.sha512).generate(key=otpkey_bin,
                                                              counter=1)
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           data={
                                               "serial": serial,
                                               "pass": otp_value
                                           }):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = res.json.get("result")
            self.assertEqual(result.get("status"), True)
            self.assertEqual(result.get("value"), True)

        # Check serversize
        self.assertEqual(len(server_component), 5)
        # Check that the OTP key is what we expected it to be
        expected_secret = pbkdf2_hmac('sha1',
                                      binascii.hexlify(server_component),
                                      client_component, 17898, 64)
        self.assertEqual(otpkey_bin, expected_secret)

        with self.app.test_request_context('/token/' + serial,
                                           method='DELETE',
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)

        delete_policy("enrollhotp")
示例#44
0
 def helper(secret=b'password', salt=b'salt', rounds=1, keylen=None, digest="sha1"):
     return pbkdf2_hmac(digest, secret, salt, rounds, keylen)