Хэш — функция в Spark SQL-Разные строки, все с одним и тем же сгенерированным хэшем

#apache-spark #hash #apache-spark-sql

Вопрос:

Я хочу создать другой хэш для каждого электронного письма, однако я обнаружил, что создаю один и тот же хэш для разных электронных писем, например:

 select hash('pipohecho@hotmail.com'),
       hash('rozas_huertas@hotmail.com'),
       hash('miguelilloooooooooouu@hotmail.com'),
       hash('rjdzpmsyi@hotmail.com'),
       hash('pepe@hotmail.com')
 

введите описание изображения здесь

Эти случаи: hash('pipohecho@hotmail.com'), hash('rozas_huertas@hotmail.com'), hash('miguelilloooooooooouu@hotmail.com'), hash('rjdzpmsyi@hotmail.com') сгенерируйте один и тот же хэш -1517714944 , затем у меня есть два вопроса:

  1. Как это возможно?
  2. Как я могу сгенерировать уникальный хэш для каждого электронного письма с помощью Spark SQL?

Спасибо

Ответ №1:

Кажется, здесь есть статья о столкновении вероятностей хэша.


Попробуйте использовать любую xxhash64(from spark-3),md5,sha2 из функций, чтобы получить уникальное хэш-значение.

Example:

 spark.sql("""select xxhash64('pipohecho@hotmail.com'),
       xxhash64('rozas_huertas@hotmail.com'),
       xxhash64('miguelilloooooooooouu@hotmail.com'),
       xxhash64('rjdzpmsyi@hotmail.com'),
       xxhash64('pepe@hotmail.com')""").show()

# ------------------------------- ----------------------------------- ------------------------------------------- ------------------------------- -------------------------- 
#|xxhash64(pipohecho@hotmail.com)|xxhash64(rozas_huertas@hotmail.com)|xxhash64(miguelilloooooooooouu@hotmail.com)|xxhash64(rjdzpmsyi@hotmail.com)|xxhash64(pepe@hotmail.com)|
# ------------------------------- ----------------------------------- ------------------------------------------- ------------------------------- -------------------------- 
#|6332927369894443419            |-8140372026824474906               |-9124920009896762502                       |1936246589584419991            |954028670536665140        |
# ------------------------------- ----------------------------------- ------------------------------------------- ------------------------------- -------------------------- 


spark.sql("""select md5('pipohecho@hotmail.com'),
       md5('rozas_huertas@hotmail.com'),
       md5('miguelilloooooooooouu@hotmail.com'),
       md5('rjdzpmsyi@hotmail.com'),
       md5('pepe@hotmail.com')""").show()

# ------------------------------------------ ---------------------------------------------- ------------------------------------------------------ ------------------------------------------ ------------------------------------- 
#|md5(CAST(pipohecho@hotmail.com AS BINARY))|md5(CAST(rozas_huertas@hotmail.com AS BINARY))|md5(CAST(miguelilloooooooooouu@hotmail.com AS BINARY))|md5(CAST(rjdzpmsyi@hotmail.com AS BINARY))|md5(CAST(pepe@hotmail.com AS BINARY))|
# ------------------------------------------ ---------------------------------------------- ------------------------------------------------------ ------------------------------------------ ------------------------------------- 
#|7ce30aa0209335873f79e64c2eb465ff          |9d58c495ab87f2e3a4a9adc6c8fbbb76              |c283a7c6f09712fc5ba4ea30334e2c25                      |6766da691171aa5c56a70b89bd4590fa          |ab888b1a15b420b410d23b927a370013     |
# ------------------------------------------ ---------------------------------------------- ------------------------------------------------------ ------------------------------------------ ------------------------------------- 


spark.sql("""select sha2('pipohecho@hotmail.com',256),
       sha2('rozas_huertas@hotmail.com',256),
       sha2('miguelilloooooooooouu@hotmail.com',256),
       sha2('rjdzpmsyi@hotmail.com',256),
       sha2('pepe@hotmail.com',256)""").show()

# ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- 
#|sha2(CAST(pipohecho@hotmail.com AS BINARY), 256)                |sha2(CAST(rozas_huertas@hotmail.com AS BINARY), 256)            |sha2(CAST(miguelilloooooooooouu@hotmail.com AS BINARY), 256)    |sha2(CAST(rjdzpmsyi@hotmail.com AS BINARY), 256)                |sha2(CAST(pepe@hotmail.com AS BINARY), 256)                     |
# ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- 
#|02068bc029cd26888a4ba630ecfa91b4afc2bf72c4adeabcfcd32459529c61bb|391af34e53d82ce8f12a1396d5ae74d96f3ea583cf3fd864816b29586ed002f8|fde18d7d27497717a8a77a0eace29ad5dbcb7319637be033c3e66a068a2bd983|b07300bee7e68326143c40f75b608201f5db667a18bb73b63f9f909454521753|921efc4884d3c8a32899c079024386641564ec0d0966cc059429bbd33770e421|
# ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- 
 

Ответ №2:

Текущая реализация hash in Spark использует MurmurHash, более конкретно MurmurHash3. MurmurHash, а также функция xxHash, доступная xxhash64 в Spark 3.0.0 , является некриптографической хэш-функцией, что означает, что она не была специально разработана для того, чтобы ее было трудно инвертировать или чтобы она не допускала столкновений. Как MurmurHash, так и xxHash должны быть очень быстрыми, обеспечивая при этом достаточно хороший разброс значений хэша, чтобы они могли быть полезны для поиска на основе хэша. Типичным использованием таких функций хеширования является реализация хэш-таблицы, в которой ключ сопоставляется с ячейкой, и каждая ячейка содержит связанный список пар ключ/значение (kvp). В этом случае столкновения не являются фатальными — они просто приводят к более длинным спискам kvp, для прохождения которых требуется больше времени. Существует обширный криптоанализ MurmurHash.

Как предложил @NotNull, вместо этого вам следует использовать криптографическую хэш-функцию, такую как SHA-2 или MD5. Я бы также посоветовал избегать использования MD5, если хэш-значения когда-либо где-либо хранились, и засолять электронные письма перед хэшированием фиксированным, но случайным образом выбранным (например, во время развертывания) секретом:

 select sha2(concat('39u!6fgs3#', 'email@domain.com'), 256)
--       fixed salt ---^^^     value ---^^^
 

Засолка значений перед их хэшированием делает невозможным, чтобы кто-то, кто не знает значения соли, грубо изменил хэши, если они каким-то образом просочатся.