• not-of-this-Earth (unregistered)

    TRWTF is Unicode

  • Rope (unregistered) in reply to Larry
    Larry:
    v:
    In fact passwords _should_ be treated differently: you should use a constant time comparison (e.g. not returning once a mismatched character is found as in the above)
    TRWTF is machines that would take more than a nanosecond to process two > 1,000-character passwords.

    My machine must be very old than, because it's two 64-bit cores can only change states 2.4 times in a nanosecond. Assuming 16-bit characters we could possibly process 4 characters per clock tick in one core. Since I have two cores I only get 2.4 * 2 * 4 = 19.2 characters processed in a nanosecond. With Hyperthreading and multiple pipelines the actual result might be better than that, but it will not "process two > 1,000-character passwords" in a nanosecond.

    I envy you and your machine.

  • (cs) in reply to Mike
    Mike:

    I will now claim Mike's law of internet debate: As the number of volleys increases, the probability of a heated rant that includes the unintentionally ironic phrase, "chill out", approaches one.

    Wait, are you saying that I should...You dare turn my phrase around...You...Why...Oh snap.

  • Thomas (unregistered)
            for (int i = 0; i < psswd1.Length; i++)
            {
                if ((psswd1[i] != psswd2[i]) != Boolean.FileNotFound)
                    return false;
            }
            return true;

    fixed.

  • (cs) in reply to frits
    frits:
    SeySayux:
    Obviously, everyone knows that if a.length != b.length you should return false even before starting the loop.

    Correct implementation of equals (for ascii):

    bool equals(String lhs, String rhs) {
         if(rhs.length() != lhs.length()) return false;
         
         for(idx_t i = 0; i < lhs.length(); ++i) {
             if(rhs.at(i) != lhs.at(i)) return false;
         }
         return true;
    }
    

    Please tell me it's correct. It's correct, right?

    You can optimize and use an object comparison. If (object)rhs == (object)lhs you can go ahead and return true immediately.

    Could be a false optimisation though, as in reality users do not compare objects against themselves and you are adding in one extra comparison to optimise the extremely rare case that they do.

    It's similar to checking for self-assignment in C++ operator= overload. Actually preferable not to do so.

  • jc (unregistered) in reply to Steve H
    Steve H:
    BG:
    In TheDailyWTF comment system you can type your password in and it appears as *'s!

    Weird! Where does the completely spurious apostrophe come from?

    Dave Barry explained that to us several years ago: In modern English spelling, the apostrophe is used to warn the reader that an 's' is coming up.

  • (cs) in reply to Cbuttius
    Cbuttius:
    frits:
    SeySayux:
    Obviously, everyone knows that if a.length != b.length you should return false even before starting the loop.

    Correct implementation of equals (for ascii):

    bool equals(String lhs, String rhs) {
         if(rhs.length() != lhs.length()) return false;
         
         for(idx_t i = 0; i < lhs.length(); ++i) {
             if(rhs.at(i) != lhs.at(i)) return false;
         }
         return true;
    }
    

    Please tell me it's correct. It's correct, right?

    You can optimize and use an object comparison. If (object)rhs == (object)lhs you can go ahead and return true immediately.

    Could be a false optimisation though, as in reality users do not compare objects against themselves and you are adding in one extra comparison to optimise the extremely rare case that they do.

    It's similar to checking for self-assignment in C++ operator= overload. Actually preferable not to do so.

    They actually do an object comparison in the library code for String.Equals() in the .Net framework (I looked it up). The reason for this is string interning.

  • Foobar (unregistered)

    pass1 = foo pass2 = foobar

    Access allowed :)

  • Omar (unregistered)

    checkPassword(actualPass, enteredPass): encrypt enteredPass with salt return enteredPass == actualPass

    Assuming you grab the actual pass from the database and encrypt the entered pass correctly.

  • SR (unregistered) in reply to JB
    JB:
    SR:

    isecretlylikejustinbeiber

    i secretly like just in beiber

    what do you mean by "in beiber"?

    I mean *********

  • Lynne Truss (unregistered) in reply to jc

    Oh no it isn't!

  • (cs) in reply to boog
    boog:
    You're also pointing out that there is a key difference in a closed system vs. over a network. Fair enough. Here's a study of timing attacks over a network for you:

    http://www.cs.cmu.edu/~dbrumley/pubs/openssltiming.pdf

    However, Brumley wasn't comparing passwords: he was timing cryptographic operations, operations that took time measured in (small numbers of) microseconds. See the discussion above about timing in realistic processors; a password comparison will take a couple nanoseconds.

    Another link someone posted said they were able to distinguish timings as small as a few microseconds over the open Internet, and about 100 nanoseconds over a local network -- but even the latter number is still two orders of magnitude too long to distinguish the timing from password comparisons.

    Swedish tard:
    Yeah, I mean, whats wrong with calling my car a bike... They are both vehicles.

    You will notice, however, that "bike" can refer to either a bicycle, or, occasionally, a motorcycle, depending on context.

    I would submit that, if you restrict the discussion to passwords, you could say a hash almost certainly is "encrypting" the password, just in a way that is hard for anyone to reverse. There are so many more SHA1 hashes than there are, say, 14-character passwords (if you restrict yourself to printable characters, a 14-character password has ~92 bits of entropy, leaving the hash's target space 2^68 times bigger) that it's very likely that what a user has chosen has no collisions within that space. Which means... it's very likely that, when you know the source is a password, there is only a single remotely likely choice.

    Of course, you may have to brute force to get to it, so there's no easy decryption algorithm. This may rule it out in your mind, but of course, since you haven't actually said what definition of "encryption" you favor, I can't know that.

    Cbuttius:
    Could be a false optimisation though, as in reality users do not compare objects against themselves and you are adding in one extra comparison to optimise the extremely rare case that they do.

    It's similar to checking for self-assignment in C++ operator= overload. Actually preferable not to do so.

    Of course, one of the reasons to check for self-assignment in operator= is a correctness issue; a lot of the time the assignment operator is destructive to the object being assigned to. And if that's the same as the source object, well, you're hosed. And there, your program isn't just "doesn't perform quite as well as it could" if you don't check for self-assignment, you're program is buggy because you omitted this check.

    (Of course, there are other ways around this, like swap with a temporary object and stuff, but operator= isn't always written that way.)

  • Salusa (unregistered)

    Ok, this is driving me a little nuts. Timing attacks are real and do work over the internet. This write-up is good and thorough, even if it discusses HMACs instead of passwords. (Though you can just think of an HMAC as a 20 character password).

    It's also worth noting that the concept of "Local Network" is much wider than you might think. How many sites are hosted by shared hosting providers or by one of the major cloud providers? Guess what: every single other customer of theirs is on your local network.

    So, if you completely trust every other customer of your hosting provider you're fine, right? Well, for now. Congratulations, you'll be fine until they manage to improve the attack, and attacks always improve. Let me repeat one of the cardinal rules of cryptography (which includes things like passwords).

    If you are not an expert in cryptography, never write cryptographic code.

    I swear, I'm going to shoot the next developer who submits their own encryption algorithm or RNG to me.

  • Jay (unregistered) in reply to boog
    boog:
    Anonymous:
    I like to think that there's always a more complicated way to do string comparisons. Comparing byte arrays is a nice over-complication but I've seen better.
    You said it. I'm sure he could have used recursion somewhere.

    Oh, I see the problem now! He failed to convert both strings to XML and check for SQL injection before doing the compare!

  • Biff (unregistered) in reply to jc

    "To avoid confusion, we may occasionally need to use apostrophes to indicate the plural forms of certain letters and expressions that are not commonly found in the plural:

    * Mind your p's and q's.
    * Let's accept the proposal without any if's, and's, or but's.
    

    "

    http://grammar.about.com/od/punctuationandmechanics/tp/GuideApostrophe.htm

  • imennez (unregistered)

    so...

    pass1 = "mypasswd" pass2 = "mypasswdwithalotmore..."

    will be return true in this method, brilliant

  • (cs) in reply to Salusa
    Salusa:
    Ok, this is driving me a little nuts. Timing attacks are real and do work over the internet. This write-up is good and thorough, even if it discusses HMACs instead of passwords. (Though you can just think of an HMAC as a 20 character password).

    He's also discussing it in the context of Java & Python, which I didn't think of before. I could easily see that as making the difference between a measurable and immeasurable difference.

    Some timing information I got locally says that the difference in time of stopping the comparison early in an optimized C++ program is about 10 nsec. An order of magnitude more than I expected, but still an order of magnitude less than what people (incl. your site) say is measurable in the local network.

    Even unoptimized C++ std::string comparisons with (bounds-checked) .at() instead of (unchecked) [] is barely above the 100 ns threshold.

    And a truly optimized implementation (that does word-sized comparisons) may be able to bring the difference even lower.

  • Andrew (unregistered) in reply to The Nerve
    The Nerve:
    Fixed?
    public static bool passwordsMatch(string pass1, string pass2)
    {
        return pass1.Equals(pass2);
    }
    

    Nope, you have written a program that exposes you to a timing attack.

  • Don't understand all of this at all (unregistered)

    Okay, it's all for maintainance... Who knows? Maybe comparison semantics of The Very Special Strings will change some day, so we created separate function for this...

  • Zephyr (unregistered)

    I think we need someone to actually implement a forum system with the **** feature, just for all the confusion it would cause. All you'd have to do is check every word of each new post against the user's pass hash.

  • Scott Meyer (unregistered) in reply to EvanED

    How long is it since all C++ programmers were meant to learn that the check-for-self-assign pattern doesn't work in the face of exceptions, and therefore that, since as an optimisation it is almost always a bad trade-off, its use is almost always indicative of a design error? A decade?

  • (cs) in reply to Scott Meyer
    Scott Meyer:
    How long is it since all C++ programmers were meant to learn that the check-for-self-assign pattern doesn't work in the face of exceptions, and therefore that, since as an optimisation it is almost always a bad trade-off, its use is almost always indicative of a design error? A decade?
    Right, because all code can throw exceptions and all code must deal with exceptions completely gracefully.

    Addendum (2010-09-16 23:30): And the extra work of making code exception-safe is always worth the development time.

  • bash (unregistered) in reply to BG

    hehe,Sombody has been surfing bash i see :-)

  • Vla (unregistered) in reply to DaveAronson
    DaveAronson:
    Larry:
    TRWTF is people who don't understand what encryption is.
    This *might* not be intended to check the password for login purposes. Maybe it's just for checking whether the "password" and "confirm password" fields match, i.e., the user didn't typo.

    But yes, if this is for login authentication, using plaintext passwords, it's been a well-known incredibly stupid practice for many decades....

    I think he's rather refering to the wrong use of the word 'encryption' in the text. Since you can never encrypt something by hashing it. A hash is non-revertable and therefor not a form of encryption.

  • Peter (unregistered) in reply to Markus

    You are right! It works! If I type my password "***********" and then backwards: "regnevalana" you should only be able to see the last version.

  • (cs) in reply to Sales guy
    S*les guy:
    My password is just the letter '*'.
    Its going to be h*rd to re*d comments if *ll '*'s *re repl*ced with *'s.
  • dan (unregistered) in reply to t3h
    t3h:
    Shouldn't you also check the lengths first?
    frits:
    You guys laugh, but this is the exact code the CLR uses for String.Equals(), except they use a loop over a switch for optimization.

    except that strings are passed and compared by reference in CLR.

    I'm hoping you're trolling or have never used .net

  • justvisiting (unregistered) in reply to Dave

    They might actually have a point. If the only way for a user (or attacker) to login is through the web application, they can easily prevent brute force attacks by locking an account for 24 hours after three failed login attempts. This way, even with 6 letter, all lower case, alphabetic passwords it would take thousands of years to brute force it. It sure beats forcing users to write down passwords because they can't possibly memorize dozens of long strings of random non alphanumeric gibberish that they are supposed to change periodically.

  • justvisiting (unregistered) in reply to Dave
    Dave:
    Believe it or not, this is how TD Canada Trust's (Canada's second largest financial institution) online banking works.

    They only allow for a password up to 8 characters. If you enter more than 8 characters the system truncates anything beyond 8 chars and validates.

    Other things about TD Canada Trust's passwords:

    1. Password can only be 5-8 characters in length
    2. no special characters are allowed
    3. System does not differentiate between upper and lower case.

    I've raised these issues with their support team however they state that these faults are actually features. They even said that because hundreds of people forget their passwords that they are willing to sacrifice a little security for ease of use.

    They might actually have a point. If the only way for a user (or attacker) to login is through the web application, they can easily prevent brute force attacks by locking an account for 24 hours after three failed login attempts. This way, even with 6 letter, all lower case, alphabetic passwords it would take thousands of years to brute force it. It sure beats forcing users to write down passwords because they can't possibly memorize dozens of long strings of random non alphanumeric gibberish that they are supposed to change periodically.

  • Kim F. (unregistered) in reply to Ken B.

    Can't tell if you're joking or not :-/

  • Re2KenB. (unregistered) in reply to Ken B.
    Ken B.:
    Scott:
    Okay, so if psswd2 is longer than psswd1 they can still match. WTF!?
    for (int i = 0; i < max(psswd1.Length,psswd2.Length); i++)
    Fixed.

    You get an exception (out of range) if the size of the passwds is different.

    Replacing problems with other problems ist not fixing.

  • Joe (unregistered) in reply to blah

    Do the different versions handle this differently? I haven't checked, I'm just making the point.

  • ano cow (unregistered)

    He get it wrong our manager discovered that passwords are sent in plaintext! Code at our company is

    public class PasswordChecker{ public static int _getary(bool[] ary,int index){ try { return ary[index]; } catch (IndexOutOfRangeException) { return 0; } } public static bool Paswordscheck(Password passwordFirst,Password passwordSecond){ long long pwFirst=0; long long pwSecond=0; byte psswordFirst[]; byte psswordSecond[]; int i; Iterator pwdFirst; Iterator pwdSecond; psswordFirst=IPassword(passwordFirst).getpassword(); psswordSecond=IPassword(passwordSecond).getpassword(); pwdFirst=psswordFirst.iterator(); pwdSecond=psswordSecond.iterator(); while (pwdFirst.hasNext()){//secure first password psswordFirst[i]=''; i=i+1; } i=0; while (pwdSecond.hasNext()){//secure second password pssword2[i]=''; i=i+1; } int sizeofbyte=1; for (i=0;i<1getbitsperbyte();i++) sizeofbyte=2sizeofbyte; for (i=0;i<1getbitsperbyte();i++) pwFirst=pwSecondsizeofbyte+_getary(pssword1[i]); for (i=0;i<1getbitsperbyte();i++) pwFirst=pwSecondsizeofbyte+_getary(pssword2[i]); return pwFirst==pwSecond;//comparsion by 8bytes simutaneusly is very fast };

  • SecurityGuy (unregistered) in reply to The Nerve

    That's actually not OK if you put it in an online system: it is susceptible to a side channel (timing) attack.

    Most .equals method return false when they see that 2 characters don't match. If the first character does not match the function will return immediately. If the measuring can be precise enough you can just test character by character.

    It's better to create two strings of the same length, padded with a character that you may not use. Then compare and only return after all characters have been compared.

  • zdux (unregistered)

    This is not a wtf The strings are probably already hashed containing characters above 128

  • Matt (unregistered) in reply to TheJasper

    No - Darren is entirely correct. The User ID is what it says on the tin, the mechanism by which a user is Identified, to the system itself and often others. The password is the "secret bit" between the user and the system that tells the system that the actor claiming to be that user, actually is. If the user ID was private, then you'd actually need to invent an ID for the user that wasn't private as your original ID would effectively be a second password. No harm in that I suppose - but it would not be a user Id if it was considered private - it's an ID, by definition the mechanism by which you are identified to others

  • Douglastab (unregistered)

    pharmacie en ligne avec ordonnance https://kamagraenligne.com/# acheter mГ©dicament en ligne sans ordonnance

Leave a comment on “Very Special Strings”

Log In or post as a guest

Replying to comment #:

« Return to Article