{"id":11,"date":"2009-03-21T09:01:47","date_gmt":"2009-03-21T09:01:47","guid":{"rendered":"http:\/\/www.vidarholen.net\/contents\/blog\/?p=11"},"modified":"2009-03-21T09:01:47","modified_gmt":"2009-03-21T09:01:47","slug":"password-generation-traps","status":"publish","type":"post","link":"https:\/\/www.vidarholen.net\/contents\/blog\/?p=11","title":{"rendered":"Password generation traps"},"content":{"rendered":"<p>Generating a random password is simple, but generating a secure one is harder if you don&#8217;t know what you&#8217;re doing. When I looked through the password generation algorithm at work, I found (and fixed) several vulnerabilities and bugs, one of which allowed a remote attacker to crack any known account with a generated password in a couple of minutes.<\/p>\n<p>The password generator itself was just inadequate, but an API misunderstanding made it extremely severe:<\/p>\n<p>The following method signature was used for the password generation:<\/p>\n<pre>\r\npublic static string GenerateReadablePassword(int length, int seed) \r\n<\/pre>\n<p>On reading &#8220;int seed&#8221;, your head should be ringing with warning bells. More on that later. The real kicker was the invocation:<\/p>\n<pre>\r\nstring Password = GenerateReadablePassword(10, DateTime.Now.Millisecond);\r\n<\/pre>\n<p>&#8216;<\/p>\n<p>If you&#8217;re familiar with the C# API, you&#8217;re likely rolling on the floor about now. Otherwise, the part about <code>DateTime.Now<\/code> will give you the shivers. And then you realize that this wouldn&#8217;t compile without a cast unless <code>DateTime.Now.Millisecond<\/code> is an int or narrower, which would make for a pretty lousy timestamp. Oh yes&#8230; This is the number of milliseconds into the current second.<\/p>\n<p>A new account got one of 1000 possible passwords, for an effective &#8220;two characters, no uppercase or symbols&#8221; policy. <\/p>\n<p>Even if this had been the proper epoch time in milliseconds, it still wouldn&#8217;t have been secure. There are only 86&nbsp;400&nbsp;000 milliseconds in a day, and only 28 million of them are during office hours. If you can narrow it down to a specific hour, you have 3 million possible ones. And if you can hear the beep of the user&#8217;s e-mail client as the (plain-text) password e-mail is received, you&#8217;re back down to a few thousand. <\/p>\n<p>Going from a timestamp to an actual high quality pseudo-random seed is better, but it still doesn&#8217;t win any prizes. You then have a best case of 2<sup>32<\/sup> possible passwords regardless of how long you specify the password to be. <\/p>\n<p>Another example of this, included in our source code, was a copy of the first google hit for &#8220;generate random password C#&#8221;. I won&#8217;t link to it in case I increase its standing. It&#8217;s a code sample that claims that it &#8220;Generates random password, which complies with the strong password rules&#8221;, and here is an excerpt:<\/p>\n<pre>\r\n        \/\/ Generate 4 random bytes.\r\n        RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();\r\n        rng.GetBytes(randomBytes);\r\n\r\n        \/\/ Convert 4 bytes into a 32-bit integer value.\r\n        int seed = (randomBytes[0] & 0x7f) << 24 |\r\n                    randomBytes[1]         << 16 |\r\n                    randomBytes[2]         <<  8 |\r\n                    randomBytes[3];\r\n\r\n        \/\/ Now, this is real randomization.\r\n        Random  random  = new Random(seed);\r\n<\/pre>\n<p>No, this is not real randomization, this is 31 bits of high quality randomness sprinkled with a snake oil vinaigrette. Any password of any length generated by this function will not be more secure than a proper 5-character alphanumeric password. You have a secure PRNG right there! Use it!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Generating a random password is simple, but generating a secure one is harder if you don&#8217;t know what you&#8217;re doing. When I looked through the password generation algorithm at work, I found (and fixed) several vulnerabilities and bugs, one of which allowed a remote attacker to crack any known account with a generated password in &hellip; <a href=\"https:\/\/www.vidarholen.net\/contents\/blog\/?p=11\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Password generation traps&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true},"categories":[22],"tags":[],"class_list":["post-11","post","type-post","status-publish","format-standard","hentry","category-security"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/www.vidarholen.net\/contents\/blog\/index.php?rest_route=\/wp\/v2\/posts\/11","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.vidarholen.net\/contents\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.vidarholen.net\/contents\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.vidarholen.net\/contents\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.vidarholen.net\/contents\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=11"}],"version-history":[{"count":0,"href":"https:\/\/www.vidarholen.net\/contents\/blog\/index.php?rest_route=\/wp\/v2\/posts\/11\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.vidarholen.net\/contents\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=11"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.vidarholen.net\/contents\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=11"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.vidarholen.net\/contents\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=11"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}