{"id":843,"date":"2015-11-01T15:41:55","date_gmt":"2015-11-01T19:41:55","guid":{"rendered":"http:\/\/www.logicalzero.com\/blog\/?p=843"},"modified":"2015-11-02T10:52:13","modified_gmt":"2015-11-02T14:52:13","slug":"buttoning-down-security","status":"publish","type":"post","link":"http:\/\/www.logicalzero.com\/blog\/?p=843","title":{"rendered":"Buttoning down security"},"content":{"rendered":"<p><a title=\"iButton Reader 2\" href=\"https:\/\/www.flickr.com\/photos\/27076997@N00\/22562920615\/in\/dateposted-public\/\" data-flickr-embed=\"true\"><img loading=\"lazy\" style=\"float: left; padding: 4px 16px 4px 4px;\" src=\"https:\/\/farm1.staticflickr.com\/612\/22562920615_e432a26035_q.jpg\" alt=\"iButton Reader 2\" width=\"150\" height=\"150\" \/><\/a><script src=\"\/\/embedr.flickr.com\/assets\/client-code.js\" async=\"\" charset=\"utf-8\"><\/script>My employer recently rolled out new security policies, including stricter requirements for passwords. As often the case, strong passwords using the new scheme can be a bit difficult to remember, and the unnatural mix of symbols makes them slow to type. A system with less strict password rules paired with a physical key (the &#8220;something you know\/something you have&#8221; combo) would be more secure and convenient, but it is usually something that needs to be rolled out at a company level. I came up with a compromise.<\/p>\n<p>iButtons are kind of a cool technology, albeit one that never made it out of certain niche markets. Basically, iButtons are <a href=\"https:\/\/en.wikipedia.org\/wiki\/1-Wire\">1-Wire<\/a> chips in ruggedized packages similar to coin cell batteries. They only need two connections &#8212; combined data\/power and ground &#8212; so the battery form factor works well. iButtons have unique 64 bit IDs and can join a 1-Wire &#8220;MicroLAN&#8221; with just a touch to a reader. I&#8217;ve had an assortment of 1-Wire and iButton hardware for a long time but never found a good use for it&#8230; until now.<br \/>\n<!--more--><br \/>\n<em>(Note: again, the code samples cause my theme to render badly in several browsers. My apologies; redoing\/modernizing my blog&#8217;s theme is on the to-do list.)<\/em><\/p>\n<p>The idea is simple: data on the iButton is used to generate simulated keystrokes. I type half of the password, and the iButton &#8216;types&#8217; the rest. In my proof-of-concept, the text generated by the iButton is derived from its ID, which undergoes some secret modification before it is written. I&#8217;ve got enough ID-only iButtons to let me change them every time my password expires for the next several years. I also have some with EEPROM and other forms of memory, so a future version might use that.<\/p>\n<p><a title=\"iButton Reader Electronics, exploded\" href=\"https:\/\/www.flickr.com\/photos\/27076997@N00\/22574138721\/in\/dateposted-public\/\" data-flickr-embed=\"true\"><img loading=\"lazy\" style=\"float: left; padding: 4px 16px 4px 4px;\" src=\"https:\/\/farm1.staticflickr.com\/773\/22574138721_de741121a3_s.jpg\" alt=\"iButton Reader Electronics, exploded\" width=\"75\" height=\"75\" \/><\/a><script src=\"\/\/embedr.flickr.com\/assets\/client-code.js\" async=\"\" charset=\"utf-8\"><\/script><a title=\"iButton Reader, Electronics\" href=\"https:\/\/www.flickr.com\/photos\/27076997@N00\/22376107149\/in\/dateposted-public\/\" data-flickr-embed=\"true\"><img loading=\"lazy\" style=\"float: left; padding: 4px 16px 4px 4px;\" src=\"https:\/\/farm1.staticflickr.com\/738\/22376107149_482b6c16dd_s.jpg\" alt=\"iButton Reader, Electronics\" width=\"75\" height=\"75\" \/><\/a><script src=\"\/\/embedr.flickr.com\/assets\/client-code.js\" async=\"\" charset=\"utf-8\"><\/script>The guts of my prototype are a miniature knock-off of an Arduino Leonardo (based on an ATMega 32U4). <a href=\"https:\/\/www.maximintegrated.com\/en\/products\/comms\/ibutton\/DS9092L.html\" target=\"_blank\">The reader itself<\/a> is &#8216;dumb,&#8217; not much more than two concentric rings of stainless steel with a decorative LED in the middle. The sleek enclosure was something hanging around the office, left over from an old project. A piezo speaker indicates a good or bad read. All in all, it&#8217;s pretty good for a single evening&#8217;s work, using parts I had on hand.<\/p>\n<p>Writing the code was easier than I&#8217;d anticipated. The Arduino OneWire library works better than expected.<\/p>\n<pre class=\"lang:arduino decode:true \">#include &lt;OneWire.h&gt;\r\n\r\n\/\/ Pins. 1-Wire data, LED, and speaker.\r\nconst byte OW_PIN = 2;\r\nconst byte LED_PIN = 10;\r\nconst byte SPEAKER_PIN = 8;\r\n\r\n\/\/ 'Debug' pins. If they are connected, the sketch runs\r\n\/\/ normally. If open, it goes into 'debug' mode\r\nconst byte DEBUG_PIN_IN = 6;\r\nconst byte DEBUG_PIN_OUT =  7;\r\n\r\n\/\/ LED fading stuff. The LED does a 'breathing' effect while the\r\n\/\/ reader is idle, as made popular by Apple products.\r\nconst int LED_DELAY = 10;\r\nconst int LED_INCREMENT = 2;\r\n\r\n\/\/ iButton reader status and interval check.\r\nconst int CHECK_INTERVAL = 250;\r\nconst byte IBUTTON_IDLE = 0;\r\nconst byte IBUTTON_BAD_CRC = 1;\r\nconst byte IBUTTON_OK = 2;\r\n\r\nOneWire  ds(2);\r\nbyte addr[8];\r\nbyte lastStatus = IBUTTON_IDLE;\r\nbool newTouch = false;\r\n\r\nint ledLevel = 255;\r\nint ledFadeDir = 1;\r\nint checkNow = 0;\r\n\r\nbool debug = false;\r\n\r\nvoid setup(void) {\r\n  pinMode(LED_PIN, OUTPUT);\r\n\r\n  \/\/ Check the 'debug' pins. These are jumpered together for normal\r\n  \/\/ operation. Removing the jumper puts the board in 'debug' mode.\r\n  pinMode(DEBUG_PIN_IN, INPUT_PULLUP);\r\n  pinMode(DEBUG_PIN_OUT, OUTPUT);\r\n  digitalWrite(DEBUG_PIN_OUT, LOW);\r\n  debug = digitalRead(DEBUG_PIN_IN);\r\n  digitalWrite(DEBUG_PIN_IN, LOW);\r\n\r\n  if (debug) {\r\n    Serial.begin(19200);\r\n    Serial.println(\"Starting in debug mode...\");\r\n  }\r\n  else {\r\n    tone(8, 200, 200);\r\n    Keyboard.begin();\r\n  }\r\n}\r\n\r\nvoid loop(void) {\r\n  \/\/ LED fading stuff. \r\n  \/\/ Reverse fade direction if it's hit min\/max.\r\n  if (ledLevel+LED_INCREMENT &gt; 255)\r\n    ledFadeDir = -LED_INCREMENT;\r\n  else if (ledLevel-LED_INCREMENT &lt; 0)\r\n     ledFadeDir = LED_INCREMENT;\r\n     \r\n  ledLevel += ledFadeDir;\r\n  analogWrite(LED_PIN, ledLevel);\r\n  delay(LED_DELAY);\r\n\r\n  \/\/ See if it's time to attempt reading the iButton.\r\n  checkNow -= LED_DELAY;\r\n  if (checkNow &gt; 0)\r\n    return;\r\n\r\n  byte buttonStatus = getKeyCode();\r\n  switch (buttonStatus) {\r\n    case IBUTTON_OK:\r\n      \/\/ Only process if the touch is 'new,' not the same one.\r\n      \/\/ Prevents repeatedly sending the ID.\r\n      if (newTouch) {\r\n        sendId();\r\n        \/\/ Make a 'chirp' to indicate a successful read, something\r\n        \/\/ slightly more pleasant than a beep.\r\n        for (int i=600; i&lt;=1400; i+=100) {\r\n          tone(8, i, 15);\r\n          delay(10);\r\n        }\r\n        delay(1000);\r\n      }\r\n      break;\r\n    case IBUTTON_BAD_CRC:\r\n      badCRC();\r\n      break;\r\n    case IBUTTON_IDLE:\r\n      \/\/ If the last two status have been IDLE, the next OK\r\n      \/\/ will have been generated by a new iButton touch.\r\n      newTouch = lastStatus == IBUTTON_IDLE;\r\n      break;\r\n  }\r\n  lastStatus = buttonStatus;\r\n  checkNow += CHECK_INTERVAL;\r\n}\r\n\r\n\r\nbyte getKeyCode() {\r\n  byte data[12];\r\n\r\n  if (!ds.search(addr)) {\r\n    ds.reset_search();\r\n    return IBUTTON_IDLE;\r\n  }\r\n\r\n  if (OneWire::crc8(addr, 7) != addr[7])\r\n    return IBUTTON_BAD_CRC;\r\n\r\n  ds.reset();\r\n  return IBUTTON_OK;\r\n}\r\n\r\n\r\nvoid sendId() {\r\n  if (debug) {\r\n    \/\/ Debug mode: just print the ID to the Serial console.\r\n    for (char i = 7; i &gt; -1; i--) {\r\n      if (i != 7) Serial.print(\" * \");\r\n      if (addr[i] &lt; 0x10) Serial.print(0);\r\n      Serial.print(addr[i], HEX);\r\n    }\r\n    Serial.println(\"\");\r\n    return;\r\n  }\r\n\r\n  \/\/ Normal operation: send ID as keystrokes.\r\n  \/\/ This is stand-in code; my real one does some modification,\r\n  \/\/ but I'm keeping the details secret.\r\n  for (char i = 7; i &gt; -1; i--) {\r\n    if (i != 7) Keyboard.print(\".\");\r\n    if (addr[i] &lt; 0x10) Keyboard.print(\"0\");\r\n    Keyboard.print(addr[i], HEX);\r\n  }\r\n  Keyboard.println(\"\");\r\n}\r\n<\/pre>\n<p>(I used<a href=\"https:\/\/tushev.org\/articles\/arduino\/8\" target=\"_blank\"> this example<\/a> as a guide.)<\/p>\n<p>This was just a proof-of-concept, not something I&#8217;m intending to use, at least not in its current form. Any of my coworkers seeing this can rest easy. It works remarkably well, though, so I may actually use a future iteration.<\/p>\n<p>No schematics for this yet, but it&#8217;s all pretty simple. Will update at some point.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>My employer recently rolled out new security policies, including stricter requirements for passwords. As often the case, strong passwords using the new scheme can be a bit difficult to remember, and the unnatural mix of symbols makes them slow to type. A system with less strict password rules paired with a physical key (the &#8220;something [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[8,6],"tags":[41,16,36,45],"_links":{"self":[{"href":"http:\/\/www.logicalzero.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/843"}],"collection":[{"href":"http:\/\/www.logicalzero.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.logicalzero.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.logicalzero.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.logicalzero.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=843"}],"version-history":[{"count":12,"href":"http:\/\/www.logicalzero.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/843\/revisions"}],"predecessor-version":[{"id":875,"href":"http:\/\/www.logicalzero.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/843\/revisions\/875"}],"wp:attachment":[{"href":"http:\/\/www.logicalzero.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=843"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.logicalzero.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=843"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.logicalzero.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=843"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}