Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
shrughes
Oct 11, 2008

(call/cc call/cc)
This is more a human horror than a coding horror, but this thread: http://news.ycombinator.com/item?id=4616704

Adbot
ADBOT LOVES YOU

Golbez
Oct 9, 2002

1 2 3!
If you want to take a shot at me get in line, line
1 2 3!
Baby, I've had all my shots and I'm fine

shrughes posted:

This is more a human horror than a coding horror, but this thread: http://news.ycombinator.com/item?id=4616704

I remember this story. It started a huge argument on a forum where it was me versus a guy who insisted that creating a perfect compressor (i.e. could compress and decompress every kind of file; he never caught on that if that were true, you could compress everything down to 1 byte), and it got so heated he was eventually banned. Did I mention this was an anarcho-capitalist forum? Strange times.

Zamujasa
Oct 27, 2010



Bread Liar
I came across this particular gem while checking if is_numeric() had any stupid gotchas I needed to be aware of. :suspense:

php:
<?
    // Released Under Affero General Public License, Version 3 (AGPL3)
    // Author: [email]holdoffhunger@gmail.com[/email]

$result = "TRUE";

$testable_string = strtolower($string_to_test);
$testable_string_length = strlen($string_to_test);

for($i_string = 0; $i_string < $testable_string_length; $i_string++)
{
    $current_value_to_test = $testable_string[$i_string];
    
    if(    ($current_value_to_test != "0")        &&
        ($current_value_to_test != "1")        &&
        ($current_value_to_test != "2")        &&
        ($current_value_to_test != "3")        &&
        ($current_value_to_test != "4")        &&
        ($current_value_to_test != "5")        &&
        ($current_value_to_test != "6")        &&
        ($current_value_to_test != "7")        &&
        ($current_value_to_test != "8")        &&
        ($current_value_to_test != "9")        &&
        ($current_value_to_test != "a")        &&
        ($current_value_to_test != "b")        &&
        ($current_value_to_test != "c")        &&
        ($current_value_to_test != "d")        &&
        ($current_value_to_test != "e")        &&
        ($current_value_to_test != "f")        )
    {
        $result = "FALSE";
        $i_string = $testable_string_length;
    }
}
?>
:downsbravo:

Opinion Haver
Apr 9, 2007

People releasing really small snippets like that under non-public-domain licenses annoy the poo poo out of me.

A A 2 3 5 8 K
Nov 24, 2003
Illiteracy... what does that word even mean?

Zamujasa posted:

I came across this particular gem while checking if is_numeric() had any stupid gotchas I needed to be aware of. :suspense:

php:
<?
    // Released Under Affero General Public License, Version 3 (AGPL3)
    // Author: [email]holdoffhunger@gmail.com[/email]
...
$result = "TRUE";
?>
:downsbravo:

Wow. I had to see if there was more from this person, and I wasn't disappointed, but now I wonder if it's a troll.

http://www.php.net/manual/de/function.sort.php#104952
http://www.php.net/manual/it/function.filetype.php#108190
http://www.php.net/manual/it/imagick.getversion.php#108585

And my favorite:

http://www.php.net/manual/it/function.unlink.php#104370

quote:

There are two outcomes: (1) It deletes the file, and continues happily along, error message, or not. (2) It can't delete the file, can't modify the permissions, etc., and therefore, the script never completes, or it may throw some PHP errors at you eventually.

Don't people cite all the community contributed code snippets in the PHP documentation as a point in the language's favor?

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

A A 2 3 5 8 K posted:

Wow. I had to see if there was more from this person, and I wasn't disappointed, but now I wonder if it's a troll.
Using AGPL generally means that something is a troll.

GentlemansSleepover
Apr 26, 2010
I want to thank everyone in this thread for giving me the push I needed to force all my applications to use encrypted passwords instead of plain text bullshit sitting in the database. I hated doing it that way from the start, but everyone insisted that they needed to be able to read the passwords in plain text so that they could provide them to users if they called in. At the time, it was easier to just do what the customers wanted and give them plain text passwords, but today I'd had enough. I decided gently caress them, I'm not being blamed for this poo poo getting compromised at some point and thousands of users passwords being out in the wild.

Also, I've always been embarrassed to go back even a couple years and look at the crazy poo poo I wrote - now I'm looking at things as I write them and thinking "what the gently caress is wrong with you? There's a better way to do this." and I credit this thread for shaming me into being a better person. Thanks again everyone, I really appreciate it.

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

GentlemansSleepover posted:

I want to thank everyone in this thread for giving me the push I needed to force all my applications to use encrypted passwords instead of plain text bullshit sitting in the database. I hated doing it that way from the start, but everyone insisted that they needed to be able to read the passwords in plain text so that they could provide them to users if they called in. At the time, it was easier to just do what the customers wanted and give them plain text passwords, but today I'd had enough. I decided gently caress them, I'm not being blamed for this poo poo getting compromised at some point and thousands of users passwords being out in the wild.

Also, I've always been embarrassed to go back even a couple years and look at the crazy poo poo I wrote - now I'm looking at things as I write them and thinking "what the gently caress is wrong with you? There's a better way to do this." and I credit this thread for shaming me into being a better person. Thanks again everyone, I really appreciate it.

You're not supposed to store encrypted passwords, that is only a little better than storing them in plaintext. Use a one-way hash function.

shrughes
Oct 11, 2008

(call/cc call/cc)

hieronymus posted:

You're not supposed to store encrypted passwords, that is only a little better than storing them in plaintext. Use a one-way hash function.

What one-way hash function would you recommend?

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

shrughes posted:

What one-way hash function would you recommend?

perhaps i meant cryptographic when i said one way. SHA-256 hasn't been compromised, may as well go with that. Compute the hash based on the concatenation of salt (possibly time when password was entered + arbitrary string) + user password. That way no one knows the password and they can't plug your database into freerainbowtables.com.

The Gripper
Sep 14, 2004
i am winner

hieronymus posted:

You're not supposed to store encrypted passwords, that is only a little better than storing them in plaintext. Use a one-way hash function.
And to continue on this, it's always better to let a user reset their password than provide them their existing password, not just for the security of *your* system, but for security of the user in general if they reused their password elsewhere.

Opinion Haver
Apr 9, 2007

hieronymus posted:

perhaps i meant cryptographic when i said one way. SHA-256 hasn't been compromised, may as well go with that. Compute the hash based on the concatenation of salt (possibly time when password was entered + arbitrary string) + user password. That way no one knows the password and they can't plug your database into freerainbowtables.com.

No. Use something like bcrypt or scrypt that's designed to be slow to calculate, to slow down brute-force attacks.

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

yaoi prophet posted:

No. Use something like bcrypt or scrypt that's designed to be slow to calculate, to slow down brute-force attacks.

Ugg, I googled this and found http://hashcat.net/oclhashcat-plus

So yep, I am embarrassingly wrong about SHA-256.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
That is normal.

Number one rule of security: You're always wrong, even when you're aware of this rule.

Lurchington
Jan 2, 2003

Forums Dragoon
we moved to bcrypt for one of our products and was surprised to learn that it truncates password characters after 72. That seems reasonable, but still, figured I would have heard of that by now.

Malloc Voidstar
May 7, 2007

Fuck the cowboys. Unf. Fuck em hard.
code:
/* Schneier specifies a maximum key length of 56 bytes.
 * This ensures that every key bit affects every cipher
 * bit.  However, the subkeys can hold up to 72 bytes.
 * Warning: For normal blowfish encryption only 56 bytes
 * of the key affect all cipherbits.
 */

GentlemansSleepover
Apr 26, 2010

hieronymus posted:

You're not supposed to store encrypted passwords, that is only a little better than storing them in plaintext. Use a one-way hash function.

Sorry, wasn't clear about that, I did use a one-way hash. And now I'm not sure if the way I did it is the best possible solution, looking into new methods now.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Lurchington posted:

we moved to bcrypt for one of our products and was surprised to learn that it truncates password characters after 72. That seems reasonable, but still, figured I would have heard of that by now.

I was unaware of this. But couldn't you MD5 the password and then bcrypt() it, and still gain all the benefits?

edit: or would that leave you vulnerable to people generating collisions? I not clever at this cryptographic theory stuff. At any rate, pretend I asked: could you gain the benefits of bcrypt by applying it after applying an inexpensive hash function of your choice

Hammerite fucked around with this message at 16:18 on Oct 6, 2012

Jonnty
Aug 2, 2007

The enemy has become a flaming star!

Hammerite posted:

I was unaware of this. But couldn't you MD5 the password and then bcrypt() it, and still gain all the benefits?

No, because that's just essentially like having a password policy which is "32 hex characters only" making them much easier to crack. Sure, you then have to crack the md5 hashes after that, but I'd imagine both steps together are easier than cracking a single completely unknown bcrypted password.

e: having said that, I suspect that at 32 characters the differences you're talking about are orders of magnitudes of centuries or something

Jonnty fucked around with this message at 16:22 on Oct 6, 2012

Zhentar
Sep 28, 2003

Brilliant Master Genius

hieronymus posted:

SHA-256 hasn't been compromised, may as well go with that.

hieronymus posted:

So yep, I am embarrassingly wrong about SHA-256.

That's because "compromised" doesn't mean poo poo for passwords. Cryptographic hashes are designed to make it difficult to intentionally create a different input that will result in the same output. If you can reasonably generate two inputs with the same output, then your hash has been compromised. This does not matter at all if you're trying to crack passwords.

Lurchington
Jan 2, 2003

Forums Dragoon

Hammerite posted:

I was unaware of this. But couldn't you MD5 the password and then bcrypt() it, and still gain all the benefits?

edit: or would that leave you vulnerable to people generating collisions? I not clever at this cryptographic theory stuff. At any rate, pretend I asked: could you gain the benefits of bcrypt by applying it after applying an inexpensive hash function of your choice

It's an interesting thought, but the only way I make sense of the whole cryptography thing is to assume that combining two of more types of hashing makes the whole thing worse than doing the "best" one. So I'm not sure.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
Actually, I suppose 36 characters (based on using UTF-16) isn't so bad as to require extra steps, so maybe it's not really that big a deal.

You could even apply a rule like: work out how many characters of the password fit in 72 bytes when it is represented as UTF-8, and if it is less than 36, convert it to UTF-16 and use that instead... or does that have some kind of pitfall?

Malloc Voidstar
May 7, 2007

Fuck the cowboys. Unf. Fuck em hard.
It's like padding the key with zeros.

Progressive JPEG
Feb 19, 2003

Before hashing, you should also salt the password, against eg a username plus an arbitrary string.

Here's a good article explaining what salting is good for (pg 3), and why bulk hash algorithms (md5/sha1/similar) aren't the best choice for encrypting passwords (pg4), among lots of other info. I recommend reading the whole thing.

Repeat hashing is typically done against the same algorithm. Eg repeat a given hash algorithm a few thousand times instead of just once. I think bcrypt does this, for example. But I think this is mainly just performed in order to make it more computationally intensive to bruteforce; there's otherwise little effective increase in security.

Hammerite posted:

You could even apply a rule like: work out how many characters of the password fit in 72 bytes when it is represented as UTF-8, and if it is less than 36, convert it to UTF-16 and use that instead... or does that have some kind of pitfall?
I don't think that would really help things. It doesn't increase the number of permutations that a cracker would need to iterate over; they could just do the same thing on their end when bruteforcing. If they have your encrypted passwords, it's not a stretch to assume that they also have your code.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

beoba posted:

I don't think that would really help things. It doesn't increase the number of permutations that a cracker would need to iterate over; they could just do the same thing on their end when bruteforcing. If they have your encrypted passwords, it's not a stretch to assume that they also have your code.

If you read my post, I am solely concerned with the restriction on bcrypt that the password must be at most 72 bytes in length. I was not proposing that idea as a way of improving the obscurity of the hashing scheme, nor am I proposing it as a way of improving the difficulty of breaking the hashing scheme, except in so far as if a user creates a password that is heavy on 3+ byte UTF-8 characters, you would be able to make use of a longer prefix of that password.

edit: But I was forgetting about the salt. That restricts the size of passwords still further. It is quite peculiar that you don't hear much about this limitation of the bcrypt algorithm.

Hammerite fucked around with this message at 17:03 on Oct 6, 2012

Zhentar
Sep 28, 2003

Brilliant Master Genius

Hammerite posted:

It is quite peculiar that you don't hear much about this limitation of the bcrypt algorithm.

Probably because is doesn't matter. If you pick a work factor so that each hash calculation takes about one second, and then you restrict your 72 character password to only numbers that are smaller than two, then we're still talking around 100 trillion years of CPU time to brute force your password.

Lurchington
Jan 2, 2003

Forums Dragoon

Zhentar posted:

Probably because is doesn't matter. If you pick a work factor so that each hash calculation takes about one second, and then you restrict your 72 character password to only numbers that are smaller than two, then we're still talking around 100 trillion years of CPU time to brute force your password.

Yeah, I had brought it up in the first place, but I still think it doesn't matter. It's just the kind of point that you'd normally expect to be flogged over and over in cryptography holy wars.

Strong Sauce
Jul 2, 2003

You know I am not really your father.





bcrypt already salts and works. use bcrypt.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
Everyone on this page: Stop trying to implement your own encryption mechanisms and/or password storage mechanisms. Stop trying to improve on existing technologies, you're most likely not. Cryptography is like, legit, hard.

Do not preprocess your passwords/plaintext in any way before inputting them to the library function.

nielsm
Jun 1, 2009



Wheany posted:

Everyone on this page: Stop trying to implement your own encryption mechanisms and/or password storage mechanisms. Stop trying to improve on existing technologies, you're most likely not. Cryptography is like, legit, hard.

Do not preprocess your passwords/plaintext in any way before inputting them to the library function.

A million times this.

If you haven't studied cryptography for at least 10 years you are most certainly wrong.
If you have, you probably still made a fault in your reasoning somewhere.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Strong Sauce posted:

bcrypt already salts and works. use bcrypt.

Oh, I see that I was misunderstanding. the salt is obtained from the bcrypt implementation and does not count toward the 72-byte limit.

Still though, I am curious. When you are asking a user to set a password, what is the best procedure to follow? Do you let them enter a long password and silently truncate it to 72 bytes? Do you enforce a limit on the length of the password? (I had thought that both of these were generally considered to be a bad thing to do.) If you do enforce a limit, what limit exactly? 72 bytes is 36 UTF-16 characters, or 24+ UTF-8 characters (but practically speaking passwords probably won't all be composed of 3-byte characters); but then again those numbers presuppose that you do not allow non-BMP characters...

Malloc Voidstar
May 7, 2007

Fuck the cowboys. Unf. Fuck em hard.

Hammerite posted:

Do you enforce a limit on the length of the password? (I had thought that both of these were generally considered to be a bad thing to do.)
Limiting password length is considered a bad thing when it's limited to like <20chars or so. My bank for a long time limited passwords to 8chars, which is awful. Limiting them to 72 bytes is really not an issue.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Aleksei Vasiliev posted:

Limiting password length is considered a bad thing when it's limited to like <20chars or so. My bank for a long time limited passwords to 8chars, which is awful. Limiting them to 72 bytes is really not an issue.

But again, what limit do you impose?

Option 1: You impose a limit of 72 bytes on the UTF-8 representation of the entered password.
Problem: You reject some passwords in a seemingly (to the user) capricious fashion and can't specify a solid upper limit on password length.

Option 2: You impose a limit of 18 characters (18 characters * 4 bytes/character = 72 bytes; non-BMP characters take up 4 bytes in both UTF-8 and UTF-16)
Problem: That's quite a small limit.

Option 3: You impose a limit of 36 characters and disallow non-BMP characters (and run bcrypt on the UTF-16 representation of the password).
Problem: Not too bad, but it seems a little arbitrary to disallow non-BMP characters.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Hammerite posted:

Option 1: You impose a limit of 72 bytes on the UTF-8 representation of the entered password.

It's this.

shrughes
Oct 11, 2008

(call/cc call/cc)
For gently caress's sake, just md5 hash it before throwing it into bcrypt. There's nothing wrong with doing that.

Malloc Voidstar
May 7, 2007

Fuck the cowboys. Unf. Fuck em hard.
bcrypt hash it and throw it into md5

Zamujasa
Oct 27, 2010



Bread Liar

shrughes posted:

For gently caress's sake, just md5 hash it before throwing it into bcrypt. There's nothing wrong with doing that.

Use SHA-512 and the raw binary results instead of hex digits, for 64 bytes of bcrypt goodness. :getin:



Fakedit: Is there a good explanation of how to do this? I'm assuming that it's just using the Blowfish version of php's crypt() function, but if there's a better way and some examples I'm all ears to learning how to do passwords right.

The Gripper
Sep 14, 2004
i am winner
A lot of dudes just don't limit it and let bcrypt or whatever truncate the password, since by the time you're entering 72 byte passwords you're getting more out of the convenience of not having to remember where your longass > 72 byte passphrase ended than you are getting security from that longass passphrase.

shrughes
Oct 11, 2008

(call/cc call/cc)
Yeah it's more of a worry with some retarded computer generated password file that has 20 xml tags before it because java.

Zamujasa posted:

Fakedit: Is there a good explanation of how to do this? I'm assuming that it's just using the Blowfish version of php's crypt() function, but if there's a better way and some examples I'm all ears to learning how to do passwords right.

Not all crypts have blowfish support.

Maybe use phpass and configure it to use bcrypt. It'll do the annoying call to the crypt library for you. The last time I looked at that it would failover to some awful choice if bcrypt were not available, so maybe you should hack the source code to assert that it's actually using bcrypt.

Adbot
ADBOT LOVES YOU

McGlockenshire
Dec 16, 2005

GOLLOCKS!

Zamujasa posted:

Fakedit: Is there a good explanation of how to do this? I'm assuming that it's just using the Blowfish version of php's crypt() function, but if there's a better way and some examples I'm all ears to learning how to do passwords right.

As long as you manually pick a large enough cost parameter, yes, plain old PHP crypt() will do the job fine:

$hash = crypt('password', '$2y$14$putyoursaltherethanks$');

The 14 here is the cost factor. The higher the cost, the longer it's going to take to generate. An increase of one roughly doubles the time spent.

The whole 2a/2x/2y thing has to do with some edge case or another.

Be sure to RTFM and check the constants before using it.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply