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.

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)

The Most Contextual AI Development Assistant

Pieces.app image

Our centralized storage agent works on-device, unifying various developer tools to proactively capture and enrich useful materials, streamline collaboration, and solve complex problems through a contextual understanding of your unique workflow.

👥 Ideal for solo developers, teams, and cross-company projects

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay