Comparing String to Avoid Time Based Attacks

sunday-snippet · Mar 27, 2022 · ~3 min
Sunday Snippet #10 comparing string to avoid time based attacks
Sunday Snippet #10 comparing string to avoid time based attacks

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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)
}

Test

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$ 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

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.

· · ·

Love This Content?

Any kind of supports is greatly appreciated! Kindly support me via Bitcoin, Ko-fi, Trakteer, or just continue to read another content. You can write a response via Webmention and let me know the URL via Telegraph.

Drop Your Comment Below