2010-06-09 54 views
4

J'ai expérimenté avec BCrypt, et trouvé ce qui suit. Si cela importe, je suis en 1.9.2dev rubis (2010-04-30 tronc 27557) [i686-linux]BCrypt dit long, des mots de passe similaires sont équivalents - problème avec moi, la gemme, ou le domaine de la cryptographie?

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 

Au début, je pensais qu'une fois que les mots de passe ont une certaine longueur, les dissemblances serait juste être perdu dans tout le hachage, et seulement si elles étaient très dissemblables (c'est à dire une longueur différente) seraient-ils reconnus comme différents. Cela ne me semblait pas très plausible, d'après ce que je sais des fonctions de hachage, mais je n'ai pas vu une meilleure explication. Ensuite, j'ai essayé de raccourcir chacune des long_strings pour voir où BCrypt commencerait à les distinguer, et j'ai trouvé que si je raccourcissais chacune des longues chaînes à 100 caractères, la dernière tentative ('passwor ') commencerait à redevenir vrai aussi. Alors maintenant je ne sais pas quoi penser.

Quelle est l'explication à cela?

Répondre

7

Les bonnes nouvelles est, les fondements mathématiques de chiffrement n'ont pas été dissous. :)

Les mauvaises nouvelles est qu'il ya un 8-bit key length limit in bcrypt.c qui ne silencieusement:

uint8_t key_len, salt_len, logr, minor; 

Puis, plus tard:

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

Qu'est-ce que vous passez dans pour le chiffrement est de 263 caractères, mais il se termine en pensant que c'est seulement 8. Donc vous obtenez des comparaisons sur seulement la toute première partie des cordes.

Cependant, cela fonctionne très bien pour moi lorsque je réduis la longueur du long_string s, donc si vous rencontrez réellement un problème dans la plage inférieure à 255 qui peut être liée à autre chose.

+2

J'imagine que le correctif sera probablement de rendre bcrypt() retourner NULL quand il y a une clé trop longue. De plus, comme il y a déjà un peu de sel dans la structure des mots de passe et que bcrypt est ostensiblement destiné à résoudre le problème de sécurité qui vous préoccupe, je ne m'occuperais pas de ma propre salaison ici. – HostileFork

+0

Il ne semble pas y avoir une bonne raison pour laquelle 'key_len' est un type si court du tout. – caf

+1

@caf - Je vois beaucoup de lignes de code sur le web. Et un pourcentage malheureusement élevé de ces lignes ne semble pas motivé par de bonnes raisons. :) – HostileFork

5

Le tableau P de Blowfish est long de 18 entiers de 4 octets. BCrypt XORs ce tableau par le mot de passe + null, puis répète la procédure jusqu'à ce qu'il arrive à la fin. Dites que mon mot de passe était 12345, il serait XOR le P-tableau par 12345 (null) 12345 (null) 12345 (null), etc ...

Une description complète de EksBlowfish est here. La version courte est, BCrypt utilise seulement les 72 premiers octets.