BCrypt говорит, что длинные аналогичные пароли эквивалентны - проблема со мной, драгоценным камнем или полем криптографии?

Я экспериментировал с BCrypt и нашел следующее. Если это имеет значение, я запускаю ruby ​​1.9.2dev (2010-04-30 trunk 27557) [i686-linux]

require 'bcrypt' # bcrypt-ruby gem, version 2.1.2

@long_string_1 = 'f287ed6548e91475d06688b481ae8612fa060b2d402fdde8f79b7d0181d6a27d8feede46b833ecd9633b10824259ebac13b077efb7c24563fce0000670834215'
@long_string_2 = 'f6ebeea9b99bcae4340670360674482773a12fd5ef5e94c7db0a42800813d2587063b70660294736fded10217d80ce7d3b27c568a1237e2ca1fecbf40be5eab8'

def salted(string)
  @long_string_1 + string + @long_string_2
end

encrypted_password = BCrypt::Password.create(salted('password'), :cost => 10)
puts encrypted_password #=> $2a$10$kNMF/ku6VEAfLFEZKJ.ZC.zcMYUzvOQ6Dzi6ZX1UIVPUh5zr53yEu

password = BCrypt::Password.new(encrypted_password)

puts password.is_password?(salted('password')) #=> true
puts password.is_password?(salted('passward')) #=> true
puts password.is_password?(salted('75747373')) #=> true
puts password.is_password?(salted('passwor')) #=> false

Сначала я подумал, что, как только пароли дойдут до определенной длины, различия будут просто потеряны во всех хэшированиях, и только если они будут очень разными (т.е. другой длины), они будут распознаны как разные. Для меня это не показалось мне правдоподобным, из того, что я знаю о хэш-функциях, но я не видел лучшего объяснения.

Затем я попытался сократить каждый из long_strings, чтобы увидеть, где BCrypt начнет рассказывать им обособленно, и я обнаружил, что если бы я сократил каждую из длинных строк до 100 символов или около того, последняя попытка ('passwor' ) тоже начнет возвращаться. Так что теперь я не знаю, что думать.

Какое объяснение для этого?

Ответ 1

хорошие новости, математические основы шифрования не были распущены.:)

плохая новость заключается в том, что существует ограничение на 8-разрядную длину ключа в bcrypt.c, которое тихо проваливается

uint8_t key_len, salt_len, logr, minor;

Затем позже:

key_len = strlen(key) + (minor >= 'a' ? 1 : 0);

То, что вы передаете для шифрования, составляет 263 символа, но это заставляет думать, что это всего лишь 8. Таким образом, вы получаете сравнения только с самой первой частью строк.

Однако, он отлично работает для меня, когда я уменьшаю длину long_string s, поэтому, если вы действительно получите проблему в общем диапазоне суб-255, который может быть связан с чем-то другим.

Ответ 2

P-массив Blowfish - 18 4-байтовых целых чисел. BCrypt XOR присваивает этот массив паролем + null, а затем повторяет процедуру до тех пор, пока она не дойдет до конца. Скажем, мой пароль был 12345, он будет XOR P-array на 12345 (null) 12345 (null) 12345 (null) и т.д.

Полное описание EksBlowfish здесь. В короткой версии BCrypt использует только первые 72 байта.