BCrypt говорит, что длинные пароли одинаковы - проблема со мной, самоцветом или областью криптографии?
Я экспериментировал с BCrypt и обнаружил следующее. Если это важно, я использую ruby 1.9.2dev (транк 27-04-2010, 30-04) [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
Сначала я подумал, что, как только пароли получат определенную длину, различия будут просто потеряны во всем хешировании, и только если они будут очень разными (т. Е. Другой длины), они будут признаны различными. Из того, что я знаю о хэш-функциях, мне это показалось не очень правдоподобным, но лучшего объяснения я не увидел.
Затем я попытался укоротить каждую из длинных строк, чтобы увидеть, где BCrypt начнет различать их, и обнаружил, что если я укороту каждую из длинных строк до 100 символов или около того, начнется последняя попытка ('passwor') возвращая истину, а также. Так что теперь я не знаю, что думать.
Чем это объясняется?
2 ответа
Хорошей новостью является то, что математические основы шифрования не были распущены.:)
Плохая новость заключается в том, что в bcrypt.c есть ограничение длины ключа 8 битов, которое молча терпит неудачу:
uint8_t key_len, salt_len, logr, minor;
Тогда позже:
key_len = strlen(key) + (minor >= 'a' ? 1 : 0);
То, что вы передаёте для шифрования, - это 263 символа, но в итоге он думает, что его всего 8. Так что вы получаете сравнение только по самой первой части строки.
Тем не менее, это прекрасно работает для меня, когда я сокращаю длину long_string
s, так что если вы действительно получаете проблему в диапазоне ниже 255, которая может быть связана с чем-то другим.
P-массив Blowfish состоит из 18 4-байтовых целых чисел. BCrypt XORs этот массив с паролем + null, затем повторяет процедуру до конца. Скажем, мой пароль был 12345, он будет XOR P-массив на 12345(ноль)12345(ноль)12345(ноль) и т. Д...
Полное описание EksBlowfish здесь. Короче говоря, BCrypt использует только первые 72 байта.