From 5bc8ff087a723deb1d4ae38eb8db11c57e11a77d Mon Sep 17 00:00:00 2001
From: Pierre Carrier <pierre@gcarrier.fr>
Date: Thu, 14 Nov 2013 02:29:27 -0800
Subject: [PATCH] Support for "irregular" secret lengths

I realized whilst turning 2FA for Dropbox that they use a secret length
that's not a multiplier of 8, which breaks Go's base32 decoder.
---
 gauth.go | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/gauth.go b/gauth.go
index 059e334..a2038bd 100644
--- a/gauth.go
+++ b/gauth.go
@@ -16,13 +16,22 @@ import (
 )
 
 func TimeStamp() (int64, int) {
-        time := time.Now().Unix()
-	return time / 30, int(time % 30);
+	time := time.Now().Unix()
+	return time / 30, int(time % 30)
+}
+
+func normalizeSecret(sec string) string {
+	noPadding := strings.ToUpper(strings.Replace(sec, " ", "", -1))
+	padLength := 8 - (len(noPadding) % 8)
+	if padLength < 8 {
+		return noPadding + strings.Repeat("=", padLength)
+	} else {
+		return noPadding
+	}
 }
 
 func AuthCode(sec string, ts int64) (string, error) {
-	normalizedSec := strings.ToUpper(strings.Replace(sec, " ", "", -1))
-	key, err := base32.StdEncoding.DecodeString(normalizedSec)
+	key, err := base32.StdEncoding.DecodeString(sec)
 	if err != nil {
 		return "", err
 	}
@@ -77,12 +86,13 @@ func main() {
 	prevTS := currentTS - 1
 	nextTS := currentTS + 1
 
-        fmt.Println("           prev   curr   next");
-	for name, secret := range cfg {
+	fmt.Println("           prev   curr   next")
+	for name, rawSecret := range cfg {
+		secret := normalizeSecret(rawSecret)
 		prevToken := authCodeOrDie(secret, prevTS)
 		currentToken := authCodeOrDie(secret, currentTS)
 		nextToken := authCodeOrDie(secret, nextTS)
 		fmt.Printf("%-10s %s %s %s\n", name, prevToken, currentToken, nextToken)
 	}
-        fmt.Printf("[%-29s]\n", strings.Repeat("=", progress));
+	fmt.Printf("[%-29s]\n", strings.Repeat("=", progress))
 }