0 Tage Serie
go / expert
Snippet

Timing-sichere Token-Verifikation mit crypto/subtle

Ein naiver Vergleich wie bytes.Equal oder == auf zwei Strings bricht beim ersten Unterschied ab. Angreifer im Netz können diesen frühen Abbruch messen und einen MAC byteweise erraten — der passende Präfix wächst, sobald die Antwortzeit steigt. subtle.ConstantTimeCompare führt denselben Vergleich durch, liest aber stets alle Bytes und faltet das Ergebnis in einen einzigen Akkumulator: die Laufzeit hängt nur von der Länge, nicht vom Inhalt ab. Rückgabewert 1 bedeutet gleich, 0 bedeutet ungleich. Einsetzen bei HMAC-Tags, Passwort-Hashes, Session-Tokens und anderen geheimen Byte-Folgen.

snippet.go
go
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
package main
import (
"crypto/hmac"
"crypto/sha256"
"crypto/subtle"
"fmt"
)
func sign(key, msg []byte) []byte {
m := hmac.New(sha256.New, key)
m.Write(msg)
return m.Sum(nil)
}
func verify(provided, expected []byte) bool {
// bytes.Equal short-circuits on the first mismatch and
// would leak the matching prefix length via wall-clock
// timing. ConstantTimeCompare always touches every byte.
return subtle.ConstantTimeCompare(provided, expected) == 1
}
func main() {
key := []byte("server-secret")
want := sign(key, []byte("user=42"))
got := make([]byte, len(want)) // attacker's guess
fmt.Println("ok:", verify(got, want))
}
Erklärung
1
m := hmac.New(sha256.New, key)
hmac.New bindet das Geheimnis an die Hash-Konstruktion; der entstehende Tag ist ohne key nicht fälschbar — genau das prüft der Verifier.
2
subtle.ConstantTimeCompare(provided, expected)
Iteriert über jedes Byte mit XOR-und-OR-Akkumulation. Unterschiedliche Längen liefern sofort 0, aber gleichlange Eingaben kosten stets dieselbe Zeit.
3
== 1
Die Funktion liefert int (1 oder 0) statt bool — der explizite Vergleich gegen 1 dokumentiert den Constant-Time-Vertrag an der Aufrufstelle.
4
got := make([]byte, len(want))
Ein Null-Byte-Kandidat steht stellvertretend für den Rateversuch eines Angreifers; produktiv käme er als X-Signature-Header über die Leitung.