{"id":21719,"date":"2023-09-26T20:32:17","date_gmt":"2023-09-26T16:32:17","guid":{"rendered":"https:\/\/me-en.kaspersky.com\/blog\/?p=21719"},"modified":"2023-09-26T20:32:17","modified_gmt":"2023-09-26T16:32:17","slug":"how-to-store-passwords","status":"publish","type":"post","link":"https:\/\/me-en.kaspersky.com\/blog\/how-to-store-passwords\/21719\/","title":{"rendered":"Password storage as the cornerstone of security"},"content":{"rendered":"<p>By now, as the end of the first quarter of the 21st century draws near, everyone is surely aware that user passwords are digital gold, and that protecting them is a key aspect of ensuring data security and privacy. Yet despite this, not all companies store passwords properly still.<\/p>\n<p>In this post we look at how NOT to store user passwords, and what methods are used by services that take security seriously.<\/p>\n<h2>The wrong way: storing passwords in plaintext<\/h2>\n<p>The simplest method is to store passwords in an unencrypted database. When a user tries to sign in, authentication is just a matter of matching what they enter against what\u2019s in the database.<\/p>\n<p>But there\u2019s always a risk that attackers might steal this database one way or another \u2014 for example, by exploiting vulnerabilities in the database software. Or a password table might get stolen by an ill-intentioned employee with high access privileges. Also leaked or intercepted employee credentials could be used to steal passwords. Put simply, there are plenty of scenarios where things can go pear-shaped. Remember: data stored in open form is precisely that \u2014 open.<\/p>\n<h2>A slightly better way: encrypted passwords<\/h2>\n<p>What if you store passwords in encrypted form? Not a bad idea at first glance, but it doesn\u2019t work great in practice. After all, if you store encrypted passwords in the database, they have to be decrypted each and every time to compare them with user input.<\/p>\n<p>And that means the encryption key will be somewhere close by. If that\u2019s the case, this key can easily fall into hackers\u2019 hands along with the password database. So, that defeats the whole purpose: the cybercriminals will be able to quickly decrypt this database and get passwords in plaintext, so we end up back where we started.<\/p>\n<p>As cryptographers jest in all seriousness, encryption doesn\u2019t solve the problem of data privacy \u2014 it just makes it a problem of secure key storage. You can come up with some sort of cunning schemes that may reduce the risks, but in general it won\u2019t be possible to reliably secure passwords this way.<\/p>\n<h2>The proper way: storing password hashes<\/h2>\n<p>The best method is not to store passwords at all. If you don\u2019t have something \u2014 it can\u2019t get stolen, right?<\/p>\n<p>But how to check whether a signing-in user has entered the correct password? That\u2019s where <a href=\"https:\/\/en.wikipedia.org\/wiki\/Hash_function\" target=\"_blank\" rel=\"nofollow noopener\">hash functions<\/a> come into play: special cryptographic algorithms that scramble any data into a fixed-length string of bits in a predictable but irreversible way.<\/p>\n<p><em>Predictable<\/em> here means that the same data is always converted into the same hash. And <em>irreversible<\/em> means that it\u2019s completely impossible to recover the hashed data from the hash. That\u2019s what any online service does if it cares about user data even just a tiny bit and values its reputation.<\/p>\n<p>When a user creates a password during registration \u2014 not the password itself but its hash is stored in the database along with the username. Then, during the sign-in process this hash is compared against the hash of the password entered by the user. If they match, it means the passwords are the same.<\/p>\n<p>In the event of a database leak, it\u2019s not the passwords that the attackers get hold of, but their hashes, from which the original data cannot be recovered (irreversibility, remember?). Of course, this is a vast improvement security-wise, but it\u2019s still too soon to rejoice: if the cybercriminals get their hands on the hashes, they might attempt a brute-force attack.<\/p>\n<h2>The even better way: salted hashes<\/h2>\n<p>After obtaining your database, the hackers might try to extract the passwords through brute force. This means taking a combination of characters, calculating its hash, and looking for matches across all entries in the database. If no matches are found, they\u2019ll try another combination, and so on. If there\u2019s a match, the password that was used to calculate the hash in the database is now known.<\/p>\n<p>Worse still, the process of cracking hashed passwords can be sped up considerably by means of so-called rainbow tables. Rainbow tables are huge data arrays with precalculated hash functions for most frequently met passwords. As such, they make it easy to search for matches in the stolen database. And it\u2019s all done automatically, of course, so the password-cracking process becomes too quick for comfort.<\/p>\n<p>However, there is some good news: it\u2019s impossible to calculate the hashes of all possible character combinations in advance \u2014 a complete <a href=\"https:\/\/en.wikipedia.org\/wiki\/Rainbow_table\" target=\"_blank\" rel=\"nofollow noopener\">rainbow table<\/a> for any hashing algorithm will take up more disk space than there is on the planet. Even for the not-overly-reliable MD5 algorithm, such a hypothetical table would contain (deep breath) 340\u00a0282\u00a0366\u00a0920\u00a0938\u00a0463\u00a0463\u00a0374\u00a0607\u00a0431\u00a0768\u00a0211\u00a0456 records. Which is why only the most common combinations get included in rainbow tables. <\/p>\n<p>To combat the use of rainbow tables, cryptographers came up with a solution that utilizes another important property of hash functions: even the tiniest change in the source text alters the hashing result beyond all recognition.<\/p>\n<p>Before a password hash is computed and written to the database, a random set of characters (called a salt) is added to it. This way, the databased hashes are modified to the extent that even the <a href=\"https:\/\/www.kaspersky.com\/blog\/25-worst-passwords-2014\/7239\/\" target=\"_blank\" rel=\"noopener nofollow\">most basic, obvious and frequently used passwords<\/a> like \u201c12345678\u201d and \u201cpassword\u201d cannot be brute-forced with rainbow tables.<\/p>\n<p>The simplest variant uses the same salt for all passwords. But the most hack-resistant one creates a separate salt for each individual record. The beauty of this approach is that salts can be stored in the same database with no additional risk: knowing the salt does not make the attackers\u2019 task much easier. To crack the hashes, they will still have to apply pure brute force \u2014 go through every single combination.<\/p>\n<p>The more online services adopt this <em>non-storage of passwords<\/em> method, the less likely a mass theft of user credentials (and the subsequent trouble associated with account hacking) will occur. <\/p>\n<input type=\"hidden\" class=\"category_for_banner\" value=\"mdr\"><input type=\"hidden\" class=\"placeholder_for_banner\" data-cat_id=\"mdr\" value=\"16952\">\n","protected":false},"excerpt":{"rendered":"<p>How online services should store user passwords, and how to minimize the damage in the event of a leak or hack.<\/p>\n","protected":false},"author":2726,"featured_media":21720,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1318,1916,1917],"tags":[1474,566,82,563,1183,976,187,97,321],"class_list":{"0":"post-21719","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-business","8":"category-enterprise","9":"category-smb","10":"tag-accounts","11":"tag-cryptography","12":"tag-hacking","13":"tag-hash","14":"tag-leaks","15":"tag-online-services","16":"tag-passwords","17":"tag-security-2","18":"tag-technology"},"hreflang":[{"hreflang":"en-ae","url":"https:\/\/me-en.kaspersky.com\/blog\/how-to-store-passwords\/21719\/"},{"hreflang":"en-in","url":"https:\/\/www.kaspersky.co.in\/blog\/how-to-store-passwords\/26286\/"},{"hreflang":"en-us","url":"https:\/\/usa.kaspersky.com\/blog\/how-to-store-passwords\/28961\/"},{"hreflang":"en-gb","url":"https:\/\/www.kaspersky.co.uk\/blog\/how-to-store-passwords\/26568\/"},{"hreflang":"es-mx","url":"https:\/\/latam.kaspersky.com\/blog\/how-to-store-passwords\/26693\/"},{"hreflang":"es","url":"https:\/\/www.kaspersky.es\/blog\/how-to-store-passwords\/29183\/"},{"hreflang":"ru","url":"https:\/\/www.kaspersky.ru\/blog\/how-to-store-passwords\/36161\/"},{"hreflang":"x-default","url":"https:\/\/www.kaspersky.com\/blog\/how-to-store-passwords\/49101\/"},{"hreflang":"fr","url":"https:\/\/www.kaspersky.fr\/blog\/how-to-store-passwords\/21014\/"},{"hreflang":"pt-br","url":"https:\/\/www.kaspersky.com.br\/blog\/how-to-store-passwords\/21802\/"},{"hreflang":"de","url":"https:\/\/www.kaspersky.de\/blog\/how-to-store-passwords\/30524\/"},{"hreflang":"ru-kz","url":"https:\/\/blog.kaspersky.kz\/how-to-store-passwords\/26839\/"},{"hreflang":"en-au","url":"https:\/\/www.kaspersky.com.au\/blog\/how-to-store-passwords\/32570\/"},{"hreflang":"en-za","url":"https:\/\/www.kaspersky.co.za\/blog\/how-to-store-passwords\/32223\/"}],"acf":[],"banners":"","maintag":{"url":"https:\/\/me-en.kaspersky.com\/blog\/tag\/passwords\/","name":"passwords"},"_links":{"self":[{"href":"https:\/\/me-en.kaspersky.com\/blog\/wp-json\/wp\/v2\/posts\/21719","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/me-en.kaspersky.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/me-en.kaspersky.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/me-en.kaspersky.com\/blog\/wp-json\/wp\/v2\/users\/2726"}],"replies":[{"embeddable":true,"href":"https:\/\/me-en.kaspersky.com\/blog\/wp-json\/wp\/v2\/comments?post=21719"}],"version-history":[{"count":2,"href":"https:\/\/me-en.kaspersky.com\/blog\/wp-json\/wp\/v2\/posts\/21719\/revisions"}],"predecessor-version":[{"id":21722,"href":"https:\/\/me-en.kaspersky.com\/blog\/wp-json\/wp\/v2\/posts\/21719\/revisions\/21722"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/me-en.kaspersky.com\/blog\/wp-json\/wp\/v2\/media\/21720"}],"wp:attachment":[{"href":"https:\/\/me-en.kaspersky.com\/blog\/wp-json\/wp\/v2\/media?parent=21719"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/me-en.kaspersky.com\/blog\/wp-json\/wp\/v2\/categories?post=21719"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/me-en.kaspersky.com\/blog\/wp-json\/wp\/v2\/tags?post=21719"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}