http://www.perlmonks.org?node_id=1050530

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

Omniscient Monks,

iīm wondering about the following issue:
.. use Digest::MD5 qw(md5 md5_hex md5_base64); .. # md5 salt my $salt = "any_salt"; #constructor sub new { my ($class) = @_; my $self = $class->SUPER::new(); $self->{_NAME} = $_[1]; $self->{_PASSWORD} = $_[2]; bless $self, $class and return $self; } sub ENCRYPT { return "[" . md5_base64( md5_hex( md5( "[" . $salt . $_[0] ) ) ) . + "]"; } ...
IMHO this argument should be true
$user->ENCRYPT("test") eq User::ENCRYPT("test")
but it isnīt!
User::ENCRYPT = [pFEzt3UedzYAtjFwAGLDRQ] $User->ENCRYPT = [TmLr4v17FTUVqcO+Gb2K/Q]
each time i execute it, $User->ENCRYPT returns another hash... so what happens?!

kindly perlig

$perlig =~ s/pec/cep/g if 'errors expected';

Replies are listed 'Best First'.
Re: Digest::MD5 variation problem?
by Your Mother (Archbishop) on Aug 22, 2013 at 14:28 UTC

    $_[0] when used with methods contains the caller; the object. So you're hashing (not encrypting exactly) something like HASH(0x96d7c28) and it will be different for most every object and run.

Re: Digest::MD5 variation problem?
by Corion (Patriarch) on Aug 22, 2013 at 14:25 UTC

    Have you inspected the value of $_[0] for the different calls?

    It's generally not advisable to implement "OO-and-functional" calling styles. In the case of User::Encrypt(), what user does the function operate on?

      IMHO User::Encrypt is static. And $User->ENCRYPT is OO. uuuuhh i got it..
      $_[0] is $User if i do $User->ENCRYPT('test')
      $_[0] is 'test' if i do User::ENCRYPT('test')
      -.- %&#§!! ;)
      $perlig =~ s/pec/cep/g if 'errors expected';
Re: Digest::MD5 variation problem?
by zork42 (Monk) on Aug 23, 2013 at 06:31 UTC
    Hi perlig. I was wondering, is there any reason why sub ENCRYPT has this

    return "[" . md5_base64( md5_hex( md5( "[" . $salt . $_[0] ) ) ) . "]";

    when this would suffice:

    return "[" . md5_base64( "[" . $salt . $_[0] ) . "]";

    ?
      use Digest::MD5 qw(md5 md5_hex md5_base64); print "[" . md5_base64( md5_hex( md5( "[" . 'test' ) ) ) . "]\n"; print "[" . md5_base64( "[" . 'test' ) . "]\n";
      will output
      [3Pa22aZpZCVQ+ZE1bfCMdQ] [llqG4cA/pfE1Ii5TekVThQ]
      ignorance is no excuse - but a trigger for questions ;) as you said: yes, it should suffice :D:D:D
      i tried to make it really well md5īd ;)
      kindly
      $perlig =~ s/pec/cep/g if 'errors expected';
        i tried to make it really well md5īd ;)
        1. I think 1 application of MD5 would do the job as I don't think MD5 hashes can be reversed at present. ie MD5 has not been cracked yet apart from "collision" attacks.
          However there are much more secure hashes like SHA-2.
          See http://en.wikipedia.org/wiki/MD5#Security, and http://en.wikipedia.org/wiki/SHA-2

        2. There are reasons why you might want to do a very large number of repeated invocations of a hash function. This is called Key stretching (see "(A)" below)
          However, "very large" is a lot more than 3 ;). Maybe 1,000s or much, much more.
          eg maybe see how many invocations you can do in 0.1 sec or 1 sec on the target system, and use that number of hash invocations.
          Adjust bcrypt cost to prevent future password hash attacks proposes a method which will keep password hashes strong, even as CPU speeds increase.

        3. Also, you should ideally use a large salt that is different for each user. (see "(B)" below)

        From http://en.wikipedia.org/wiki/Cryptographic_hash_function#Password_verification:
        Password verification

        A related application is password verification. Storing all user passwords as cleartext can result in a massive security breach if the password file is compromised. One way to reduce this danger is to only store the hash digest of each password. To authenticate a user, the password presented by the user is hashed and compared with the stored hash. (Note that this approach prevents the original passwords from being retrieved if forgotten or lost, and they have to be replaced with new ones.) The password is often concatenated with a random, non-secret salt value before the hash function is applied. The salt is stored with the password hash. (B) Because users have different salts, it is not feasible to store tables of precomputed hash values for common passwords. (A) Key stretching functions, such as PBKDF2, Bcrypt or Scrypt, typically use repeated invocations of a cryptographic hash to increase the time required to perform brute force attacks on stored password digests.

        Main article: http://en.wikipedia.org/wiki/Password_cracking

        I hope this is of interest! :)
        print "[" . md5_base64( md5_hex( md5( "[" . 'test' ) ) ) . "]\n";

        i tried to make it really well md5īd ;)

        Sorry, but this is just plain stupid. The innermost md5 reduces (or expands) all input to 128 bit. md5_hex around this very likely reduces its input to less than 128 bits (I would be really surprised if all 2^128 possible 128 bit arguments for the MD5 function would result in 2^128 different results). Representing the result in hex adds adds 128 constant bits, so at least half of the input for md5_base64 is constant. Ideally, this would reduce the output of md5_base64 to 2^64 possible values, but due to the previous hash functions, it is likely that the there are far less different values, so the probability for collisions rises. Or shorter: different passwords can result in the same hash value.

        zork42++ told you how to properly handle passwords, mainly salting and using strong hash functions. MD5 was strong decades ago, now it should be considered weak.

        zork42 also told you about key stretching. Implemented properly, it improves the encryption quality. Read the Wikipeda article. Or just look at the code examples in that article: The key stretching does not add constant bits, but varying bits from the input.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)