fordem Posted yesterday at 09:15 AM Share Posted yesterday at 09:15 AM First of all, this post requires from the user the knowledge and application of Shannon's entropy although it's an old and already college wise embedded topic even if you are not an engineer Shannon's entropy as much as Boltzmann's entropy came to the world with the intent to describe the organization level of a system, more in a sense that high entropy the organization level is low and low entropy the organization level is high. Which also can lead us to fact finding ideas like, if a system is extremely organized it can be easily predictable and if it is extremely disorganized it's hard to predict. So thinking in this concept, i created a password validator, that relates with what i just described. double calculateBitwiseEntropy(const std::string& input) const { int totalBits = input.length() * 8; int ones = 0, zeros = 0; for (unsigned char c : input) { for (int i = 0; i < 8; ++i) { ((c >> i) & 1) ? ++ones : ++zeros;\\number of zeros and ones } } double p1 = static_cast<double>(ones) / totalBits; \\ tackling the average of each sum. double p0 = static_cast<double>(zeros) / totalBits; double entropy = 0.0; if (p1 > 0.0) entropy -= p1 * std::log2(p1); \\based on the average we calculate the shannon's entropy. if (p0 > 0.0) entropy -= p0 * std::log2(p0); return entropy * totalBits; } First thing is calculating the bitwise entropy of the password. Basically we are calculating the number of 0's and 1's, averaging them out and than applying the formula. One important detail although this is a way to calculate randomness it's not a magic wand for example the bit string 11110000, has maximum entropy but it's not really random, so the use of this methodology must be done with parsimony and care. And then comes the validation process where i enforce that business rules should not be forgotten. Things like, min password length, must have lower and upper case characters, must have numbers and symbols. bool validatePassword(const std::string& password, nlohmann::json & reason) const { constexpr int MIN_LENGTH = 8; constexpr double MIN_ENTROPY_RATIO = 0.5; if (password.length() < MIN_LENGTH) { reason["msg"] = "Password must be at least 8 characters."; reason["entropy"]= 0; reason["eratio"]= 0; return false; } bool hasLower = false, hasUpper = false, hasDigit = false, hasSymbol = false; for (unsigned char c : password) { hasLower |= std::islower(c); hasUpper |= std::isupper(c); hasDigit |= std::isdigit(c); hasSymbol |= !std::isalnum(c); } if (!(hasLower && hasUpper && hasDigit && hasSymbol)) { reason["msg"] = "Password must include lowercase, uppercase, digit, and symbol."; reason["entropy"]= 0; reason["eratio"]= 0; return false; } double entropy = calculateBitwiseEntropy(password); double ratio = entropy / (password.length() * 8.0); if (ratio < MIN_ENTROPY_RATIO) { reason["msg"] = "Password score too low. Increase randomness."; reason["entropy"]= entropy; reason["eratio"]= ratio; return false; }else { reason["msg"] = "Password score high enough."; reason["entropy"]= entropy; reason["eratio"]= ratio; return true; } } This set of restrictions enable you to do two things, first the most clear one enforce a password policy and second the entropy will serve an easy way to score the password without using any modules, packages and things like that. Just one thing this implementation may differ a bit in javascript. OK guys, have a nice one and hang tight. Link to comment Share on other sites More sharing options...
Recommended Posts