pquerna / otp

TOTP library for Go
Apache License 2.0
2.26k stars 222 forks source link

Avoid float division in TOTP code #86

Open KamilaBorowska opened 1 year ago

KamilaBorowska commented 1 year ago

This mostly doesn't matter because 64-bit floats can represent 53-bit integers (and currently UNIX timestamps are 32 bits), but still, no reason to work with floats when integers will work fine.

This avoids Year 285618384 problem :).

egonelbre commented 12 months ago

Also, there's a slight bug on M1 processors due to float and uint conversions being platform dependent. https://go.dev/ref/spec#Conversions

On M1 Mac the uint64(float64) conversion can end up returning 0. Here's an example program.

package main

import (
    "math"
    "time"
)

func main() {
    period := uint(30)
    x := time.Time{}
    counter := int64(math.Floor(float64(x.Unix()) / float64(period)))
    counter2 := uint64(math.Floor(float64(x.Unix()) / float64(period)))
    println(counter, counter2)
    // Output: -2071186560 0
}
KamilaBorowska commented 12 months ago

@egonelbre

TOTP algorithm doesn't support timestamps before Unix epoch (time.Time{} is year 1). Doesn't really matter as time moves forwards, so this shouldn't be possible in practice.