1
$\begingroup$

I have a web app (a register and login system) written already but i am now improving it. One of its design goals was high security.

I have some use cases of md5 and sha1 in it and now i am in doubt if i seriously need to replace them (and with what and how).

I mention that uses here and please tell me if i should replace which cases why and with what other algorithm (please also mention the necessary bit length that u think is the minimum acceptable). but consider that i don't want to get it too hard; e.g. concatenating the output of sha256 to 128 bits for replacing an md5 invocation seems ok too me (i have asked about that before and seems there is consensus that that is considered secure enough for most practical cases considering i am writing a php app running on real world web servers (I think NSA or hackers can breach via those layers, PHP and web server environment, more easily)), so i don't insist on the latest and top secure standards and don't want to use complicated/bulky algorithms just to reduce a hash output length from 256 to 128!


usage 1:

md5 is used to mix several independent keys to form a single 128 bit key to be used in AES128+HMAC encryption (same key is used for enc and hmac; yes i know it is considered bad practice, but not really serious so far).

sample code:

$aes->setKey(pack('H*', md5($GLOBALS['pepper'].$GLOBALS['site_encr_key'].$GLOBALS['client_sess_key'])));

usage 2:

sha1 is used to mix several sources of entropy obtained from client request parameters to be used in the current crypto operation. this extra entropy is stored too and later used in almost all other crypto operations. Neccessary to mention that, all crypto operations have their own newly generated sufficient entropy (at least 128 bits) and the clients' requests entropy is used only as an extra (it can be useful in case some main sources of entropy fail to provide sufficient real entropy for whatever reason or in the rare case that a good standard crypto random generator isn't available in the execution environment).

see my sample code for gathering request entropy:

$request_entropy=sha1(microtime().$pepper.$_SERVER['REMOTE_ADDR'].$_SERVER['REMOTE_PORT'].$_SERVER['HTTP_USER_AGENT'].serialize($_POST).serialize($_GET).serialize($_COOKIE));

this entropy is then combined with the entropy of the past clients' requests and stored in database:

$query="update `site_vars` set `value`=sha1(concat(`value`, '$request_entropy')) where name='entropy'";

usage 3:

sha1 is used in my crypto random number generator function to get a random integer (random numbers generated by this function are then used in other more useful sub-functions, random_bytes and random_string, to generate random strings/tokens and crypto keys in my program).

see the code excerpts for details:

extract(unpack('Nrandom', pack('H*', sha1(openssl_random_pseudo_bytes(4).$entropy.microtime()))));
    return abs($random) % ($max - $min) + $min; 

...

extract(unpack('Nrandom', pack('H*', sha1(fread($urandom, 4).$entropy.microtime()))));
// $urandom is an open file handle to /dev/urandom
    return abs($random) % ($max - $min) + $min;

...

if(function_exists('mcrypt_create_iv') and version_compare(PHP_VERSION, '5.3.0', '>=')) {
    @$tmp16=mcrypt_create_iv(4, MCRYPT_DEV_URANDOM);
	    if($tmp16!==false) {
        extract(unpack('Nrandom', pack('H*', sha1($tmp16.$entropy.microtime()))));
        return abs($random) % ($max - $min) + $min;
    }
}

...

extract(unpack('Nrandom', pack('H*', sha1(mt_rand(0, 0x7FFFFFFF).$entropy.microtime()))));
    //mt_rand is only used as a fallback in case other CSPRNGs (openssl_random_pseudo_bytes, /dev/urandom, mcrypt_create_iv) aren't available in the environment
    return abs($random) % ($max - $min) + $min;
$\endgroup$
  • 1
    $\begingroup$ I'm downvoting this for the simple fact that you asked a question, got an answer you didn't like from a respected community member, and jumped to defend your original decisions. While libraries like OpenSSL have had vulnerabilities, anything you write yourself is infinitely more likely to contain more and worse ones. Triply so given the cryptographic voodoo in the code you've provided. I sincerely encourage you to heed tylo's advice and scrap your code entirely for something that has high-level APIs for accomplishing your particular security goals. $\endgroup$ – Stephen Touset Mar 23 '15 at 18:28
  • 2
    $\begingroup$ As a concrete example, your entire method for generating request entropy is bunk. Literally every value being used (besides a single static value) is attacker-controlled. $\endgroup$ – Stephen Touset Mar 23 '15 at 18:28
  • $\begingroup$ @Stephen Touset, first, I don't rely on this entropy as the main randomness source, but just as an extra (maybe like the 'belts and suspenders' metaphor). that extra entropy is accumulated/combined in its database field via combined sha1 hashing over time from every user in every request; a user can know his own request parameters but not the previous ones from other users' requests, so he absolutely can not know what the present entropy bit string is (unless he is a guy that has eavesdroped and recorded every request entering the system from the begining so far). $\endgroup$ – user40602 Mar 23 '15 at 20:27
  • $\begingroup$ Only when the user's request is the first request ever entering the system he can calculate the extra entropy bits (sha1 hash of his request parameters), but even then it is useless to him. And even that scenario is almost impossible in practice, because the admin is the first user registering/working with the system, and so no other guy can be the first, so the entropy pool is accumulated with some unpredictable entropy by admin activities already. $\endgroup$ – user40602 Mar 23 '15 at 20:27
  • $\begingroup$ Second, this extra entropy serves a second important purpose too: it defends each user against other users/hackers. There are many secret tokens generated per user that their secrecy against the user himself is not necessary (and many times cannot be kept away from the user anyway) but it is critical that they are not knowable by other users/hackers. For example when a user registers or logs into the system, this extra entropy contributes to generating an autologin key, password hash salt, antixsrf token, etc. for that user. $\endgroup$ – user40602 Mar 23 '15 at 20:27
3
$\begingroup$

Do you know the article If You’re Typing the Letters A-E-S Into Your Code You’re Doing It Wrong? This is basically the same, but with a focus on hashes.

There is a quite important misconception in your system:

  • you stated "One of its design goals was high security."
  • and then you start implementing your selfmade algorithms, even stating: "same key is used for enc and hmac; yes i know it is considered bad practice, but not really serious so far"

So, what is your goal here? Actual high security, in a real application? Here a few pointers, if that is actually the goal:

  • You should probably start by throwing out all those parts, which you designed yourself, and start utilizing proper crypto libraries and the correct primitives. E.g. key derivation functions exist for a reason.
  • Randomness (which you call entropy) is nothing to be taken lightly. Just because you implemented a system, you can't figure out how to break yourself, doesn't mean it is secure. Use a cryptographically secure random number generator and be done with it.
  • Key management is actually a quite critical topic, which is overlooked quite often. E.g. depending on your application, it can be bad if the keys are stored in the same location as user data, etc. If you can utilize a crypto library to handle the key management, all the better.

Your own suggestion of replacing MD5 and SHA-1 with a truncated version of SHA-256 would be a step in the correction direction (better without truncation), as it would be a lie to call anything based on MD5 and SHA-1 highly secure. However, this is just a minor step, and your actual problems go way deeper than that.

$\endgroup$
  • $\begingroup$ man i have rather good knowledge in cryptography. i am studying crypto for several years. i have seen many mistakes/weaknesses/bugs/holes even in apparently professional crypto libs. not to mention openssl heartbleed and NSA plots (keywords: Bullrun, Dual_EC_DRBG, RSA BSAFE) nowadays. even before these, finding a good, complete, trusty lib for every needed crypto operation for every programming env was difficult enough (quite sometimes impossible in practice). i wrote this prog several years ago. these days the status seems really better, but i think still far from good/required. $\endgroup$ – user40602 Mar 23 '15 at 16:12
  • $\begingroup$ then in the past, i searched for good/complete/professional crypto libs in php, among several, i decided upon phpseclib (others were back by a rather large margin). In practice, no other choices existed! i downloaded phpseclib, tested it, studied its source. in my tests, i found several bugs in its AES operations, reported them, the author (Jim Wigginton) eliminated them and merged the changes into phpseclib's official repository. $\endgroup$ – user40602 Mar 23 '15 at 16:13
  • $\begingroup$ Also my CSPRNG is indeed a modified version of phpseclib's CSPRNG. i think i asked about my modifs from him (in its support forum), he didn't warn me about any serious flaws. before that, I also had suggested some improvs to his CSPRNG (like adding mcrypt_create_iv to possible randomness sources); i think he made some of them. i think, before that, his CSPRNG wasn't strong enough for crypto (and thus was undermining the whole crypto lib). it was using too limited possible sources and falling back to PHP's mt_rand (not a CSPRNG) silently, fallback was indeed quite probable on envs like Windows. $\endgroup$ – user40602 Mar 23 '15 at 16:15
  • $\begingroup$ Also my 'request entropy gathering mechanism' is indeed the idea of Jim Wigginton (phpseclib's author), with sha1 codes almost exactly from him! maybe i added some other things like the storing/merging into database part. i don't remember exactly. $\endgroup$ – user40602 Mar 23 '15 at 16:15
  • $\begingroup$ Honestly, I have no idea about crypto libraries in PHP. But it seems, you are using the basic commands, while (at least today) the library also supports higher level protocols, like $cipher = new Crypt_AES(CRYPT_AES_MODE_CTR);and you can use PBKDF2, etc. However, this still doesn't say anything about the quality of that library, e.g. a question on security-SE talks about this. But if you want to achieve your high security, you should invest time in researching this. $\endgroup$ – tylo Mar 23 '15 at 16:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.