EnochRoot has asked for the wisdom of the Perl Monks concerning the following question:

Because Crypt::Eksblowfish::Bcrypt doesn't support the $2y$ bcrypt variant, I'm using htpasswd to do it. Is this function a safe way to sanitize the user input, a password, by using IPC::System::Simple's capturex(@args)? I'll then be storing this in a DB and having apache authenticate off it using AuthBasicProvider dbd in the vhost:
sub generate_apache_bcrypt_hash { my($plaintext) = @_; my $bcrypt_hash = ''; try { $bcrypt_hash = capturex("/bin/htpasswd","-nbB","''", $plaintext); } catch { print STDERR "generate_apache_bcrypt_hash = '$_'\n" if $DEBUG; }; # remove: # - extra 3 chars at the front # - 1 trailing spaces # - line break $bcrypt_hash = substr $bcrypt_hash,3; chomp($bcrypt_hash); chop($bcrypt_hash); return $bcrypt_hash }

Replies are listed 'Best First'.
Re: sanitize user input for system() call
by oiskuu (Hermit) on May 19, 2015 at 20:29 UTC

    But what prevents you from adjusting the Crypt::Eksblowfish::Bcrypt result?

    my $user = "admin"; my $password = "hunter2"; sub rnd_salt { local $/ = \16; open my $fh, '</dev/urandom'; scalar <$ +fh> } use Crypt::Eksblowfish::Bcrypt qw(bcrypt en_base64); my $param = '$2a$05$' . en_base64(rnd_salt()); my $pass = bcrypt($password, $param); $pass =~ s/^\$2a/\$2y/; print "$user:$pass";

    Update. As far as I can tell, "2x" and "2y" disambiguate between buggy and non-buggy bcrypt implementations. The "2a" in Eksblowfish module is the non-buggy variant.

    Update3. Looking further, it appears the current Crypt::Eksblowfish::Bcrypt (version 0.009) produces the non-buggy hashed output as per original spec. The crypt_blowfish implementation/spec for the "2a" hash, however, has meanwhile changed. There is now a (very small) subset of passwords for which the "2a" and "2y" hashes diverge. I must say, this whole affair does not inspire much confidence. My advice is not to use, and not to support, any of the qw(2a 2x 2y) labels, where not unavoidable. The 2a is just fubar, the 2x broken, and 2y redundant. Use the new designation "2b", which incidentally is equivalent to "2y".

    Uh-oh. There's also this "feature" that affects passwords longer than 72 characters (fixed in "2b"). Crypt::Eksblowfish::Bcrypt gets that one right, too.

    Summary: the only thing Crypt::Eksblowfish::Bcrypt needs to do is change the hash label from "2a" to "2b", and it's good.

      oiskuu - yeah, I saw that. However looking at Crypt_(C) wikipedia page, "2a" is ambiguous. I felt dirty swapping in 2y when I'm really creating a 2a variant. I decided explicitly calling htpasswd which uses non-ambigiously, safe 2y.

      Response to updates - Wowza! You really went the extra mile on analyzing the Crypt::Eksblowfish::Bcrypt implementation - thank you! That's totally cool. I'll strongly consider removing the capturex() call given all your research. thanks again!
Re: sanitize user input for system() call (yes)
by tye (Sage) on May 19, 2015 at 19:13 UTC

    Yes, the module documentation leads me to believe that this approach would be safe.

    - tye        

      Tye - thanks! It's been about 14 years since I touched perl and this is code will be going to a production server, so I don't want to mess it up! After all my researching and blundering about, I think I averaged about 15 min/per line of a 10 line function ;)
Re: sanitize user input for system() call
by Anonymous Monk on May 19, 2015 at 20:59 UTC
      Totally! Hence my trepidation. However, that thread cites the capturex() call that I ended up using.