otp icon indicating copy to clipboard operation
otp copied to clipboard

Avoid float division in TOTP code

Open sugar700 opened this issue 2 years ago • 2 comments

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 :).

sugar700 avatar Sep 15 '23 15:09 sugar700

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
}

egonelbre avatar Sep 19 '23 18:09 egonelbre

@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.

sugar700 avatar Sep 19 '23 18:09 sugar700