def calc_checksum(self, secret): if isinstance(secret, unicode): secret = secret.encode("utf-8") #parse salt value try: salt_value = h64.decode_int12(self.salt.encode("ascii")) except ValueError: #pragma: no cover - caught by class raise ValueError("invalid chars in salt") #convert first 8 byts of secret string into an integer, key1 = _crypt_secret_to_key(secret) #run data through des using input of 0 result1 = mdes_encrypt_int_block(key1, 0, salt_value, 20) #convert next 8 bytes of secret string into integer (key=0 if secret < 8 chars) key2 = _crypt_secret_to_key(secret[8:]) #run data through des using input of 0 result2 = mdes_encrypt_int_block(key2, 0, salt_value, 5) #done chk = h64.encode_dc_int64(result1) + h64.encode_dc_int64(result2) return chk.decode("ascii")
def raw_ext_crypt(secret, rounds, salt): "ext_crypt() helper which returns checksum only" #decode salt try: salt_value = h64.decode_int24(salt) except ValueError: #pragma: no cover - always caught by class raise ValueError("invalid salt") #validate secret if b('\x00') in secret: #pragma: no cover - always caught by class #builtin linux crypt doesn't like this, so we don't either #XXX: would make more sense to raise ValueError, but want to be compatible w/ stdlib crypt raise ValueError("secret must be string without null bytes") #convert secret string into an integer key_value = _crypt_secret_to_key(secret) idx = 8 end = len(secret) while idx < end: next = idx+8 key_value = mdes_encrypt_int_block(key_value, key_value) ^ \ _crypt_secret_to_key(secret[idx:next]) idx = next #run data through des using input of 0 result = mdes_encrypt_int_block(key_value, 0, salt_value, rounds) #run h64 encode on result return h64.encode_dc_int64(result)
def test_mdes_encrypt_int_block(self): for k, p, c in self.test_des_vectors: k = int(k, 16) p = int(p, 16) c = int(c, 16) result = des.mdes_encrypt_int_block(k, p, salt=0, rounds=1) self.assertEqual(result, c, "key=%r p=%r:" % (k, p))
def test_mdes_encrypt_int_block(self): for k,p,c in self.test_des_vectors: k = int(k,16) p = int(p,16) c = int(c,16) result = des.mdes_encrypt_int_block(k,p, salt=0, rounds=1) self.assertEqual(result, c, "key=%r p=%r:" % (k,p))
def raw_crypt(secret, salt): "pure-python fallback if stdlib support not present" assert len(salt) == 2 #NOTE: technically could accept non-standard salts & single char salt, #but no official spec. try: salt_value = h64.decode_int12(salt) except ValueError: #pragma: no cover - always caught by class raise ValueError("invalid chars in salt") #FIXME: ^ this will throws error if bad salt chars are used # whereas linux crypt does something (inexplicable) with it #convert first 8 bytes of secret string into an integer key_value = _crypt_secret_to_key(secret) #run data through des using input of 0 result = mdes_encrypt_int_block(key_value, 0, salt_value, 25) #run h64 encode on result return h64.encode_dc_int64(result)