def test_03_encrypt_bytes(self):
        """des_encrypt_block()"""
        from passlib.crypto.des import (des_encrypt_block, shrink_des_key,
                                        _pack64, _unpack64)

        # run through test vectors
        for key, plaintext, correct in self.des_test_vectors:
            # convert to bytes
            key = _pack64(key)
            plaintext = _pack64(plaintext)
            correct = _pack64(correct)

            # test 64-bit key
            result = des_encrypt_block(key, plaintext)
            self.assertEqual(result, correct,
                             "key=%r plaintext=%r:" % (key, plaintext))

            # test 56-bit version
            key2 = shrink_des_key(key)
            result = des_encrypt_block(key2, plaintext)
            self.assertEqual(
                result, correct,
                "key=%r shrink(key)=%r plaintext=%r:" % (key, key2, plaintext))

            # test with random parity bits
            for _ in range(20):
                key3 = _pack64(self._random_parity(_unpack64(key)))
                result = des_encrypt_block(key3, plaintext)
                self.assertEqual(
                    result, correct, "key=%r rndparity(key)=%r plaintext=%r:" %
                    (key, key3, plaintext))

        # check invalid keys
        stub = b'\x00' * 8
        self.assertRaises(TypeError, des_encrypt_block, 0, stub)
        self.assertRaises(ValueError, des_encrypt_block, b'\x00' * 6, stub)

        # check invalid input
        self.assertRaises(TypeError, des_encrypt_block, stub, 0)
        self.assertRaises(ValueError, des_encrypt_block, stub, b'\x00' * 7)

        # check invalid salts
        self.assertRaises(ValueError, des_encrypt_block, stub, stub, salt=-1)
        self.assertRaises(ValueError,
                          des_encrypt_block,
                          stub,
                          stub,
                          salt=1 << 24)

        # check invalid rounds
        self.assertRaises(ValueError,
                          des_encrypt_block,
                          stub,
                          stub,
                          0,
                          rounds=0)
Exemple #2
0
def raw_lmhash(secret, encoding="ascii", hex=False):
    """encode password using des-based LMHASH algorithm; returns string of raw bytes, or unicode hex"""
    # NOTE: various references say LMHASH uses the OEM codepage of the host
    #       for its encoding. until a clear reference is found,
    #       as well as a path for getting the encoding,
    #       letting this default to "ascii" to prevent incorrect hashes
    #       from being made w/o user explicitly choosing an encoding.
    if isinstance(secret, unicode):
        secret = secret.encode(encoding)
    ns = secret.upper()[:14] + b"\x00" * (14 - len(secret))
    out = des_encrypt_block(ns[:7], LM_MAGIC) + des_encrypt_block(ns[7:], LM_MAGIC)
    return hexlify(out).decode("ascii") if hex else out
Exemple #3
0
def des_cbc_encrypt(key, value, iv=b'\x00' * 8, pad=b'\x00'):
    value += pad * (-len(value) % 8) # null pad to multiple of 8
    hash = iv # start things off
    for offset in xrange(0,len(value),8):
        chunk = xor_bytes(hash, value[offset:offset+8])
        hash = des_encrypt_block(key, chunk)
    return hash
Exemple #4
0
    def test_03_encrypt_bytes(self):
        """des_encrypt_block()"""
        from passlib.crypto.des import (des_encrypt_block, shrink_des_key,
                                              _pack64, _unpack64)

        # run through test vectors
        for key, plaintext, correct in self.des_test_vectors:
            # convert to bytes
            key = _pack64(key)
            plaintext = _pack64(plaintext)
            correct = _pack64(correct)

            # test 64-bit key
            result = des_encrypt_block(key, plaintext)
            self.assertEqual(result, correct, "key=%r plaintext=%r:" %
                                              (key, plaintext))

            # test 56-bit version
            key2 = shrink_des_key(key)
            result = des_encrypt_block(key2, plaintext)
            self.assertEqual(result, correct, "key=%r shrink(key)=%r plaintext=%r:" %
                                              (key, key2, plaintext))

            # test with random parity bits
            for _ in range(20):
                key3 = _pack64(self._random_parity(_unpack64(key)))
                result = des_encrypt_block(key3, plaintext)
                self.assertEqual(result, correct, "key=%r rndparity(key)=%r plaintext=%r:" %
                                                  (key, key3, plaintext))

        # check invalid keys
        stub = b'\x00' * 8
        self.assertRaises(TypeError, des_encrypt_block, 0, stub)
        self.assertRaises(ValueError, des_encrypt_block, b'\x00'*6, stub)

        # check invalid input
        self.assertRaises(TypeError, des_encrypt_block, stub, 0)
        self.assertRaises(ValueError, des_encrypt_block, stub, b'\x00'*7)

        # check invalid salts
        self.assertRaises(ValueError, des_encrypt_block, stub, stub, salt=-1)
        self.assertRaises(ValueError, des_encrypt_block, stub, stub, salt=1<<24)

        # check invalid rounds
        self.assertRaises(ValueError, des_encrypt_block, stub, stub, 0, rounds=0)
    def raw(cls, secret, encoding=None):
        """encode password using LANMAN hash algorithm.

        :type secret: unicode or utf-8 encoded bytes
        :arg secret: secret to hash
        :type encoding: str
        :arg encoding:
            optional encoding to use for unicode inputs.
            this defaults to ``cp437``, which is the
            common case for most situations.

        :returns: returns string of raw bytes
        """
        if not encoding:
            encoding = cls.default_encoding
        # some nice empircal data re: different encodings is at...
        # http://www.openwall.com/lists/john-dev/2011/08/01/2
        # http://www.freerainbowtables.com/phpBB3/viewtopic.php?t=387&p=12163
        from passlib.crypto.des import des_encrypt_block

        MAGIC = cls._magic
        if isinstance(secret, unicode):
            # perform uppercasing while we're still unicode,
            # to give a better shot at getting non-ascii chars right.
            # (though some codepages do NOT upper-case the same as unicode).
            secret = secret.upper().encode(encoding)
        elif isinstance(secret, bytes):
            # FIXME: just trusting ascii upper will work?
            # and if not, how to do codepage specific case conversion?
            # we could decode first using <encoding>,
            # but *that* might not always be right.
            secret = secret.upper()
        else:
            raise TypeError("secret must be unicode or bytes")
        secret = right_pad_string(secret, 14)
        return des_encrypt_block(secret[0:7], MAGIC) + des_encrypt_block(
            secret[7:14], MAGIC)
Exemple #6
0
    def raw(cls, secret, encoding=None):
        """encode password using LANMAN hash algorithm.

        :type secret: unicode or utf-8 encoded bytes
        :arg secret: secret to hash
        :type encoding: str
        :arg encoding:
            optional encoding to use for unicode inputs.
            this defaults to ``cp437``, which is the
            common case for most situations.

        :returns: returns string of raw bytes
        """
        if not encoding:
            encoding = cls.default_encoding
        # some nice empircal data re: different encodings is at...
        # http://www.openwall.com/lists/john-dev/2011/08/01/2
        # http://www.freerainbowtables.com/phpBB3/viewtopic.php?t=387&p=12163
        from passlib.crypto.des import des_encrypt_block
        MAGIC = cls._magic
        if isinstance(secret, unicode):
            # perform uppercasing while we're still unicode,
            # to give a better shot at getting non-ascii chars right.
            # (though some codepages do NOT upper-case the same as unicode).
            secret = secret.upper().encode(encoding)
        elif isinstance(secret, bytes):
            # FIXME: just trusting ascii upper will work?
            # and if not, how to do codepage specific case conversion?
            # we could decode first using <encoding>,
            # but *that* might not always be right.
            secret = secret.upper()
        else:
            raise TypeError("secret must be unicode or bytes")
        secret = right_pad_string(secret, 14)
        return des_encrypt_block(secret[0:7], MAGIC) + \
               des_encrypt_block(secret[7:14], MAGIC)
Exemple #7
0
def des_cbc_encrypt(key, value, iv=b'\x00' * 8, pad=b'\x00'):
    """performs des-cbc encryption, returns only last block.

    this performs a specific DES-CBC encryption implementation
    as needed by the Oracle10 hash. it probably won't be useful for
    other purposes as-is.

    input value is null-padded to multiple of 8 bytes.

    :arg key: des key as bytes
    :arg value: value to encrypt, as bytes.
    :param iv: optional IV
    :param pad: optional pad byte

    :returns: last block of DES-CBC encryption of all ``value``'s byte blocks.
    """
    value += pad * (-len(value) % 8)  # null pad to multiple of 8
    hash = iv  # start things off
    for offset in irange(0, len(value), 8):
        chunk = xor_bytes(hash, value[offset:offset + 8])
        hash = des_encrypt_block(key, chunk)
    return hash
Exemple #8
0
def des_cbc_encrypt(key, value, iv=b'\x00' * 8, pad=b'\x00'):
    """performs des-cbc encryption, returns only last block.

    this performs a specific DES-CBC encryption implementation
    as needed by the Oracle10 hash. it probably won't be useful for
    other purposes as-is.

    input value is null-padded to multiple of 8 bytes.

    :arg key: des key as bytes
    :arg value: value to encrypt, as bytes.
    :param iv: optional IV
    :param pad: optional pad byte

    :returns: last block of DES-CBC encryption of all ``value``'s byte blocks.
    """
    value += pad * (-len(value) % 8) # null pad to multiple of 8
    hash = iv # start things off
    for offset in irange(0,len(value),8):
        chunk = xor_bytes(hash, value[offset:offset+8])
        hash = des_encrypt_block(key, chunk)
    return hash