   } else if (command == "set time") {
     setTime();
   } else if (command == "key") {
-    Serial.println(key);
+    printHash(key, 20);
+    Serial.println();
+  }
+}
+
+// From https://code.google.com/p/google-authenticator/source/browse/libpam/base32.c
+int base32_decode(const uint8_t *encoded, uint8_t *result, int bufSize) {
+  int buffer = 0;
+  int bitsLeft = 0;
+  int count = 0;
+  for (const uint8_t *ptr = encoded; count < bufSize && *ptr; ++ptr) {
+    uint8_t ch = *ptr;
+    if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == '-') {
+      continue;
+    }
+    buffer <<= 5;
+
+    // Deal with commonly mistyped characters
+    if (ch == '0') {
+      ch = 'O';
+    } else if (ch == '1') {
+      ch = 'L';
+    } else if (ch == '8') {
+      ch = 'B';
+    }
+
+    // Look up one base32 digit
+    if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
+      ch = (ch & 0x1F) - 1;
+    } else if (ch >= '2' && ch <= '7') {
+      ch -= '2' - 26;
+    } else {
+      return -1;
+    }
+
+    buffer |= ch;
+    bitsLeft += 5;
+    if (bitsLeft >= 8) {
+      result[count++] = buffer >> (bitsLeft - 8);
+      bitsLeft -= 8;
+    }
+  }
+  if (count < bufSize) {
+    result[count] = '\000';
+  }
+  return count;
+}
+
+void totp(uint8_t* secret, const size_t len, const long time, char token[TOKEN_LENGTH]) {
+  long timestamp = time / INTERVAL;
+  uint8_t input[8] = { 0x00, 0x00, 0x00, 0x00 };
+  input[4] = (timestamp >> 24) & 0xff;
+  input[5] = (timestamp >> 16) & 0xff;
+  input[6] = (timestamp >> 8) & 0xff;
+  input[7] = timestamp & 0xff;
+  
+  Sha1.initHmac(secret, len);
+  Sha1.write(input, 8);
+  uint8_t* hash = Sha1.resultHmac();
+  
+  uint8_t offset = hash[19] & 0xf;
+  
+  unsigned long thing = ((hash[offset] & 0x7f) << 24)
+                      | ((hash[offset + 1] & 0xff) << 16)
+                      | ((hash[offset + 2] & 0xff) << 8)
+                      | ((hash[offset + 3] & 0xff));
+  
+  for (int i = TOKEN_LENGTH - 1; i >= 0; i--) {
+    token[i] = (thing % 10) + '0';
+    thing /= 10;
   }
 }
 

#include <DS3231.h>
#include <SPI.h>
#include <SD.h>

#define BUTTON_PIN 42
#define SD_PIN 4
#define KEY_FILE "key.txt"

DS3231 rtc(SDA, SCL);
String key = "";
int previousButtonState = HIGH;

// Gets a UNIX timestamp from the RTC

  if (Serial.available()) {
    command();
  } else if (buttonState == HIGH && previousButtonState == LOW) {
    char token[TOKEN_LENGTH];
    totp(key, 20, getTimestamp(), token);
    Keyboard.print(token);
  } else {
    delay(100);
  }
