pquerna / otp

TOTP library for Go

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Problems with TOTP SHA512

Fale opened this issue · comments

Hi,
I use the following code (which is very similar to this example, if not for line 19 (which I added), line 38 (which I added), and the cycle (lines 56 and 64) which I added to simplify testing with multiple clients:

package main

import (
	"github.com/pquerna/otp"
	"github.com/pquerna/otp/totp"

	"bufio"
	"bytes"
	"fmt"
	"image/png"
	"io/ioutil"
	"os"
)

func display(key *otp.Key, data []byte) {
	fmt.Printf("Issuer:       %s\n", key.Issuer())
	fmt.Printf("Account Name: %s\n", key.AccountName())
	fmt.Printf("Secret:       %s\n", key.Secret())
	fmt.Printf("URL:          %s\n", key.URL())
	fmt.Println("Writing PNG to qr-code.png....")
	ioutil.WriteFile("qr-code.png", data, 0644)
	fmt.Println("")
	fmt.Println("Please add your TOTP to your OTP Application now!")
	fmt.Println("")
}

func promptForPasscode() string {
	reader := bufio.NewReader(os.Stdin)
	fmt.Print("Enter Passcode: ")
	text, _ := reader.ReadString('\n')
	return text
}

func main() {
	key, err := totp.Generate(totp.GenerateOpts{
		Issuer:      "Example.com",
		AccountName: "alice@example.com",
		Algorithm:   otp.AlgorithmSHA512,
	})
	if err != nil {
		panic(err)
	}
	// Convert TOTP key into a PNG
	var buf bytes.Buffer
	img, err := key.Image(200, 200)
	if err != nil {
		panic(err)
	}
	png.Encode(&buf, img)

	// display the QR code to the user.
	display(key, buf.Bytes())

	// Now Validate that the user's successfully added the passcode.
	fmt.Println("Validating TOTP...")
	for {
		passcode := promptForPasscode()
		valid := totp.Validate(passcode, key.Secret())
		if valid {
			println("Valid passcode!")
		} else {
			println("Invalid passocde!")
		}
	}
}

In a test run, this is what it outputs:

Issuer:       Example.com
Account Name: alice@example.com
Secret:       N3K5NHE26HHXP2CL
URL:          otpauth://totp/Example.com:alice@example.com?algorithm=SHA512&digits=6&issuer=Example.com&period=30&secret=N3K5NHE26HHXP2CL

qr-code

I tried to add the QRCode to Google Authenticator (on Android), FreeOTP (on Android), Google Authenticator (on iOS), FreeOTP (on iOS), gopass (on Linux).

On multiple tests, FreeOTP (on both Android and iOS), Google Authenticator on iOS and gopass agree on the generated OTPs, while Google Authenticator on Android does not.
Only the code from Google Authenticator on Android is recognised as right.

Now, I'm not sure if this is a problem on the server side or on the client side, so I'm opening the ticket on both the clients (FreeOTP Android, gopass) and the server (github.com/pquerna/otp)

When using a custom Algorithm, like SHA512, you must use totp.ValidateCustom(...). The .Validate() method only works for the SHA1, which is still the default for Google Authenticator compat. I've added an interop test in #27.

An example of interacting with twofactor, which is the underlying library for gopass is here:
https://github.com/pquerna/otp/blob/master/interop/twofactor_test.go

I don't think there is anything else for the otp library to change, if you find any issue please feel free to open another issue or PR.

Thanks a lot for the explanation :-)