DEV Community

Clavin June
Clavin June

Posted on • Originally published at clavinjune.dev on

2 1

Comparing String to Avoid Time Based Attacks

Sunday Snippet #10 comparing string to avoid time based attacks

Code

package foo_test

import (
    "crypto/rand"
    "crypto/subtle"
    "fmt"
    "strings"
    "testing"
    "time"
)

var (
    a      []byte
    length int = 100000
    batch  int = length / 10
)

func init() {
    a = make([]byte, length, length)
    rand.Read(a)
}

func getCopied(changedIndex int) []byte {
    b := make([]byte, length, length)
    copy(b, a)
    b[changedIndex] = byte(1)

    return b
}

func wrapper(fn func(a, b []byte) bool) {
    for i := length - 1; i > 0; i -= batch {
        b := getCopied(i)

        n := time.Now()
        fn(a, b)

        m := time.Since(n)
        fmt.Printf("Differences at Index: %d, time takes: %s\n", i, m.String())
    }
}

func Cmp(a, b []byte) bool {
    return string(a) == string(b)
}

func CmpSub(a, b []byte) bool {
    return subtle.ConstantTimeCompare(a, b) == 1
}

func TestCmp(t *testing.T) {
    fmt.Printf("length of chars: %d\n", length)
    fmt.Println("comparison using: string(a) == string(b)")
    wrapper(Cmp)
    fmt.Println(strings.Repeat("=", 60))
    fmt.Println("comparison using: subtle.ConstantTimeCompare(a, b) == 1")
    wrapper(CmpSub)
}
Enter fullscreen mode Exit fullscreen mode

Test

$ go version
go version go1.18 darwin/arm64
$ go test . -v -count=1
=== RUN   TestCmp
length of chars: 100000
comparison using: string(a) == string(b)
Differences at Index: 99999, time takes: 2.875µs
Differences at Index: 89999, time takes: 2.583µs
Differences at Index: 79999, time takes: 2.375µs
Differences at Index: 69999, time takes: 2.209µs
Differences at Index: 59999, time takes: 1.75µs
Differences at Index: 49999, time takes: 1.5µs
Differences at Index: 39999, time takes: 1.209µs
Differences at Index: 29999, time takes: 958ns
Differences at Index: 19999, time takes: 666ns
Differences at Index: 9999, time takes: 375ns
============================================================
comparison using: subtle.ConstantTimeCompare(a, b) == 1
Differences at Index: 99999, time takes: 50.792µs
Differences at Index: 89999, time takes: 50.583µs
Differences at Index: 79999, time takes: 50.958µs
Differences at Index: 69999, time takes: 50.709µs
Differences at Index: 59999, time takes: 51µs
Differences at Index: 49999, time takes: 51.333µs
Differences at Index: 39999, time takes: 55.875µs
Differences at Index: 29999, time takes: 50.75µs
Differences at Index: 19999, time takes: 51.709µs
Differences at Index: 9999, time takes: 51.167µs
--- PASS: TestCmp (0.00s)
PASS
ok      example 0.092s
Enter fullscreen mode Exit fullscreen mode

Conclusion

Thus, subtle.ConstantTimeCompare(a, b) == 1 is more likely to be safe to use to avoid time-based attacks. Also, to avoid the length of the string to be guessed, you can hash the string first.

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)