{"id":330,"date":"2011-10-02T23:56:26","date_gmt":"2011-10-02T23:56:26","guid":{"rendered":"http:\/\/41j.com\/blog\/?p=330"},"modified":"2011-10-02T23:56:48","modified_gmt":"2011-10-02T23:56:48","slug":"unobservable-pin-and-password-entry","status":"publish","type":"post","link":"https:\/\/41j.com\/blog\/2011\/10\/unobservable-pin-and-password-entry\/","title":{"rendered":"Unobservable pin and password entry"},"content":{"rendered":"<p>This is a combination of two blog posts from Linuxjunk. The general idea to to create a pin and password entry system where even if you want watch the whole process and you know exactly what the user typed in, you still can&#8217;t unambiguously guess their password. I think it&#8217;s a pretty neat idea.<\/p>\n<p>A one to many mapping is created between password symbols and the numbers you type in. That means the value you type in could come from any of a number of password characters. The mapping should be random so that the values you enter every time will be different. Given enough observations of course the attacker could identify the password, but it offers some security and could offer some advantage over challenge and response type systems.<\/p>\n<p>I have two pieces of code, one from pin entry and one from alphabetic password entry.<\/p>\n<h2>Unobservable pin entry<\/h2>\n<p>The following is a command line, number mapping based version of the technique described at http:\/\/dapl.me\/pinsecurity.html. It&#8217;s just a proof of concept, but I think Dans general idea is pretty neat. It could be a viable alternative to challenge and response type systems, and having this as a PAM module would be neat.<\/p>\n<p>The following code is just a proof of concept. But it presents the user with two lists of numbers. The user PIN is hard coded as 1803 in this example. The first line shows the numbers 0 through 9. The second a random list of numbers.<\/p>\n<p>The user enters numbers matching mapping from the first line to the second. Using this method it&#8217;s impossible for an observer to unambiguously guess the users pin.<\/p>\n<p>Here&#8217;s an example run:<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\n0,1,2,3,4,5,6,7,8,9,\r\n2,4,3,3,0,2,4,3,3,4,\r\nplease enter pin: 4323\r\n<\/pre>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n#include &lt;iostream&gt;\r\n#include &lt;vector&gt;\r\n\r\nusing namespace std;\r\n\r\nint main() {\r\n\r\n int valid_pw&#x5B;5];\r\n valid_pw&#x5B;0] = 1;\r\n valid_pw&#x5B;1] = 8;\r\n valid_pw&#x5B;2] = 0;\r\n valid_pw&#x5B;3] = 3;\r\n\r\n int random_mapping&#x5B;10];\r\n\r\n for(size_t n=0;n&lt;10;n++) {\r\n   random_mapping&amp;#91;n&amp;#93; = rand()%5;\r\n }\r\n\r\n for(size_t n=0;n&lt;10;n++) {\r\n   cout &lt;&lt; n &lt;&lt; &quot;,&quot;;\r\n }\r\n cout &lt;&lt; endl;\r\n\r\n for(size_t n=0;n&lt;10;n++) {\r\n   cout &lt;&lt; random_mapping&amp;#91;n&amp;#93; &lt;&lt; &quot;,&quot;;\r\n }\r\n cout &lt;&lt; endl;\r\n\r\n cout &lt;&lt; &quot;please enter pin: &quot;;\r\n\r\n int get_pw&amp;#91;4&amp;#93;;\r\n\r\n \/\/ get pw...\r\n string input_line;\r\n getline(cin, input_line);\r\n\r\n for(size_t n=0;n&lt;4;n++) {\r\n   string singlechar;\r\n   singlechar  += input_line&amp;#91;n&amp;#93;;\r\n   get_pw&amp;#91;n&amp;#93; = atoi(singlechar.c_str());\r\n }\r\n\r\n \/\/ validate pw\r\n bool pass = true;\r\n for(size_t n=0;n&lt;4;n++) {\r\n\r\n   \/\/ find all locations with this mapping\r\n   vector&lt;int&gt; valid_locs;\r\n   for(size_t i=0;i&lt;10;i++) {\r\n     if(random_mapping&amp;#91;i&amp;#93; == get_pw&amp;#91;n&amp;#93;) valid_locs.push_back(i);\r\n   }\r\n\r\n\r\n   \/\/ if any match valid_pw&amp;#91;n&amp;#93; then the password is ok.\r\n   bool thispass=false;\r\n   for(size_t i=0;i&lt;valid_locs.size();i++) {\r\n     \/\/ cout &lt;&lt; &quot;valid: &quot; &lt;&lt; valid_locs&amp;#91;i&amp;#93; &lt;&lt; endl;\r\n     if(valid_locs&amp;#91;i&amp;#93; == valid_pw&amp;#91;n&amp;#93;) thispass=true;\r\n   }\r\n   if(thispass == false) pass = false;\r\n }\r\n cout &lt;&lt; endl;\r\n\r\n if(pass) cout &lt;&lt; &quot;password valid&quot;   &lt;&lt; endl;\r\n     else cout &lt;&lt; &quot;password invalid&quot; &lt;&lt; endl;\r\n}\r\n&amp;#91;\/sourcecode&amp;#93;\r\n\r\n&lt;h2&gt;Unobservable alphabetic password entry&lt;\/h2&gt;\r\n\r\nThis version allows you to use alphabetic passwords. It takes a command line argument which is the true password. When run it displays the following prompt:\r\n\r\n&#x5B;sourcecode language=&quot;bash&quot;]\r\n$ .\/a.out test\r\n| a | b | c | d | e | f | g | h | i | j | k | l | m | \r\n| 1 | 5 | 0 | 5 | 4 | 6 | 8 | 2 | 0 | 9 | 6 | 7 | 9 | \r\n\r\n| n | o | p | q | r | s | t | u | v | w | x | y | z | \r\n| 4 | 4 | 8 | 3 | 4 | 0 | 3 | 5 | 9 | 7 | 3 | 2 | 1 | \r\n\r\nplease enter pin: 3403\r\npassword valid\r\n<\/pre>\n<p>#include <iostream><br \/>\n#include <vector><\/p>\n<p>using namespace std;<\/p>\n<p>void display_mapping(size_t start,size_t end,vector<int> random_mapping) {<br \/>\n  cout << \"| \";\n  for(size_t n=start;n<end;n++) {\n    string singlechar;\n    singlechar += 'a' + n;\n    cout << singlechar << \" | \";\n  }\n  cout << endl;\n\n  cout << \"| \";\n  for(size_t n=start;n<end;n++) {\n    cout << random_mapping[n] << \" | \";\n  }\n  cout << endl;\n}\n\nint main(int argc,char **argv) {\n\n const int entry_alphabet_size    = 10;\n const int password_alphabet_size = 26;\n\n \/\/ read valid password from commandline\n vector<char> valid_pw;<br \/>\n string valid_pw_str = argv[1];<\/p>\n<p> for(size_t n=0;n<valid_pw_str.size();n++) {\n   string singlechar;\n   singlechar  += valid_pw_str[n];\n   valid_pw.push_back(singlechar.c_str()[0]);\n }\n\n \/\/ build random mapping, use each entry symbol the same (or as close as) number of times.\n vector<int> random_mapping(26,-1);<\/p>\n<p> srand(time(NULL));<br \/>\n for(size_t n=0;n<entry_alphabet_size;n++) {\n   for(size_t i=0;i<(password_alphabet_size\/entry_alphabet_size);i++) {\n     bool unset = true;\n     for(;unset;) {\n       size_t position = rand()%password_alphabet_size;\n       if(random_mapping[position] == -1) { random_mapping[position] = n; unset = false; }\n     }\n   }\n }\n\n for(size_t n=0;n<password_alphabet_size;n++) {\n   if(random_mapping[n] == -1) random_mapping[n] = rand()%entry_alphabet_size;\n }\n\n \/\/ display mapping for user\n display_mapping(0,13 ,random_mapping);\n cout << endl;\n display_mapping(13,26,random_mapping);\n cout << endl;\n\n\n\n cout << \"please enter pin: \";\n\n vector<int> get_pw;<\/p>\n<p> \/\/ get pw&#8230;<br \/>\n string input_line;<br \/>\n getline(cin, input_line);<\/p>\n<p> for(size_t n=0;n<input_line.size();n++) {\n   string singlechar;\n   singlechar  += input_line[n];\n   get_pw.push_back(atoi(singlechar.c_str()));\n }\n\n \/\/ validate pw\n bool pass = true;\n if(valid_pw.size() != get_pw.size()) {\n   pass = false;\n } else {\n   for(size_t n=0;n<valid_pw.size();n++) {\n\n     \/\/ find all locations with this mapping\n     vector<char> valid_locs;<br \/>\n     for(size_t i=0;i<26;i++) {\n       if(random_mapping[i] == get_pw[n]) valid_locs.push_back('a' + i);\n     }\n\n     \/\/ if any match valid_pw[n] then the password is ok.\n     bool thispass=false;\n     for(size_t i=0;i<valid_locs.size();i++) {\n       if(valid_locs[i] == valid_pw[n]) thispass=true;\n     }\n     if(thispass == false) pass = false;\n   }\n }\n\n if(pass) cout << \"password valid\"   << endl;\n     else cout << \"password invalid\" << endl;\n}\n[\/sourcecode]\n<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a combination of two blog posts from Linuxjunk. The general idea to to create a pin and password entry system where even if you want watch the whole process and you know exactly what the user typed in, you still can&#8217;t unambiguously guess their password. I think it&#8217;s a pretty neat idea. A [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[1],"tags":[],"class_list":["post-330","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1RRoU-5k","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/posts\/330","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/comments?post=330"}],"version-history":[{"count":2,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/posts\/330\/revisions"}],"predecessor-version":[{"id":332,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/posts\/330\/revisions\/332"}],"wp:attachment":[{"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/media?parent=330"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/categories?post=330"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/tags?post=330"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}