dgryski / dgoogauth

Google Authenticator for Go
426 stars 59 forks source link

ComputeCode sometimes returns to few digits #6

Closed g3kk0 closed 6 years ago

g3kk0 commented 6 years ago

The following function sometimes returns 5 digits instead of 6:

https://github.com/dgryski/dgoogauth/blob/96977cbd42e27be71f9f731db6634123de7e861a/googauth.go#L27-L49

e.g.

package main

import (
  "crypto/hmac"
  "crypto/sha1"
  "encoding/base32"
  "encoding/binary"
  "fmt"
  "time"

  "github.com/dgryski/dgoogauth"
)

func main() {
  secret := []byte{'H', 'e', 'l', 'l', 'o', '!', 0xDE, 0xAD, 0xBE, 0xEF}
  secretEnc := base32.StdEncoding.EncodeToString(secret)

  var t0 int64
  t0 = int64(time.Now().Unix() / 2)
  code := dgoogauth.ComputeCode(secretEnc, t0)

  fmt.Printf("code = %+v\n", code)
}

func ComputeCode(secret string, value int64) int {
  key, err := base32.StdEncoding.DecodeString(secret)
  if err != nil {
    return -1
  }

  hash := hmac.New(sha1.New, key)
  err = binary.Write(hash, binary.BigEndian, value)
  if err != nil {
    return -1
  }
  h := hash.Sum(nil)

  offset := h[19] & 0x0f

  truncated := binary.BigEndian.Uint32(h[offset : offset+4])

  truncated &= 0x7fffffff
  code := truncated % 1000000

  return int(code)
}

Outputs the following when looped:

code = 292234
code = 108363
code = 108363
code = 828914
code = 45510
code = 45510
code = 45288
code = 45288
code = 286406
code = 166336
code = 166336
code = 569768
code = 569768
dgryski commented 6 years ago

It needs a leading zero I guess. That can be handled at the output by using a different formatting verb for printf.