def isForHash(self, nthash): plaintext = self.getPlaintext() c1, c2, c3 = self.getCiphertext() k1, k2, k3 = self._getKeysFromHash(nthash) return des.des_encrypt_block(k1, plaintext) == c1 and \ des.des_encrypt_block(k2, plaintext) == c2 and \ des.des_encrypt_block(k3, plaintext) == c3
def test_03_encrypt_bytes(self): "test des_encrypt_block()" from passlib.utils.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 _gen_challenge_response(self, challenge_hash, nt_hash): _nt_hash = b''.join((nt_hash, b'\x00' * 5)) challenge_response = b'' key = des.expand_des_key(_nt_hash[:7]) challenge_response += des.des_encrypt_block(key, challenge_hash) key = des.expand_des_key(_nt_hash[7:14]) challenge_response += des.des_encrypt_block(key, challenge_hash) key = des.expand_des_key(_nt_hash[14:]) challenge_response += des.des_encrypt_block(key, challenge_hash) return challenge_response
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 it's 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
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
def checkKey(plaintext, ciphertext, b1, b2): keyCandidateBytes = chr(b1) + chr(b2) + (chr(0x00) * 5) keyCandidate = des.expand_des_key(keyCandidateBytes) result = des.des_encrypt_block(keyCandidate, plaintext) if result == ciphertext: return keyCandidateBytes
def test_des_encrypt_block(self): for k,p,c in self.test_des_vectors: k = unhexlify(k) p = unhexlify(p) c = unhexlify(c) result = des.des_encrypt_block(k,p) self.assertEqual(result, c, "key=%r p=%r:" % (k,p)) #test 7 byte key #FIXME: use a better key k,p,c = b('00000000000000'), b('FFFFFFFFFFFFFFFF'), b('355550B2150E2451') k = unhexlify(k) p = unhexlify(p) c = unhexlify(c) result = des.des_encrypt_block(k,p) self.assertEqual(result, c, "key=%r p=%r:" % (k,p))
def test_parsing(self): capture = open("tests/pptp.cap") reader = ChapPacketReader(capture) handshakes = MultiChapStateManager() for packet in reader: handshakes.addHandshakePacket(packet) complete = handshakes.getCompletedHandshakes() assert len(complete) == 1 for server in complete: for client in complete[server]: c1, c2, c3 = complete[server][client].getCiphertext() plaintext = complete[server][client].getPlaintext() username = complete[server][client].getUserName() assert username == "moxie" hash = nthash.raw_nthash('bPCFyF2uL1p5Lg5yrKmqmY') print "NT Hash: %s" % binascii.hexlify(hash) key1 = hash[0:7] key1 = des.expand_des_key(key1) key2 = hash[7:14] key2 = des.expand_des_key(key2) key3 = hash[14:16] key3 += (chr(0x00) * 5) key3 = des.expand_des_key(key3) result1 = des.des_encrypt_block(key1, plaintext) result2 = des.des_encrypt_block(key2, plaintext) result3 = des.des_encrypt_block(key3, plaintext) print "DES Encryption 1: %s" % binascii.hexlify(result1) print "C1: %s" % binascii.hexlify(c1) print "C2: %s" % binascii.hexlify(c2) print "C3: %s" % binascii.hexlify(c3) assert result1 == c1 assert result2 == c2 assert result3 == c3
def test_des_encrypt_block(self): for k, p, c in self.test_des_vectors: k = unhexlify(k) p = unhexlify(p) c = unhexlify(c) result = des.des_encrypt_block(k, p) self.assertEqual(result, c, "key=%r p=%r:" % (k, p)) #test 7 byte key #FIXME: use a better key k, p, c = b('00000000000000'), b('FFFFFFFFFFFFFFFF'), b( '355550B2150E2451') k = unhexlify(k) p = unhexlify(p) c = unhexlify(c) result = des.des_encrypt_block(k, p) self.assertEqual(result, c, "key=%r p=%r:" % (k, p))
def test_03_encrypt_bytes(self): """test des_encrypt_block()""" from passlib.utils.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.utils.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)
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 xrange(0,len(value),8): chunk = xor_bytes(hash, value[offset:offset+8]) hash = des_encrypt_block(key, chunk) return hash
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
def test_des(self): result = des.des_encrypt_block('12345678', 'ABCDEFGH') assert binascii.hexlify(result) == "96de603eaed6256f"