IAM-15: timing-safe-vergleich-als-projektweite-coding-konvention (internal/timingsafe, coding-guideline, audit bestehender vergleichsstellen)
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
// Package timingsafe stellt die kanonische Implementierung der projektweiten
|
||||
// Coding-Konvention aus IAM-15 bereit: jeder Vergleich, der eine
|
||||
// sicherheitsrelevante Zugriffsentscheidung trifft (Passwort-Hash, Token,
|
||||
// Signatur, 2FA-Wiederherstellungscode), nutzt einen timing-safe/constant-time
|
||||
// Vergleich, nie den regulaeren ==-Operator. Siehe docs/CODING-GUIDELINES-CORE.md.
|
||||
//
|
||||
// Bestehende Vergleichsstellen (internal/totp, internal/webhook,
|
||||
// internal/moduleregistry) implementieren dasselbe Muster bereits inline mit
|
||||
// crypto/subtle direkt — dieses Package buendelt es fuer neue Vergleichsstellen,
|
||||
// ersetzt die bestehenden nicht zwangsweise (kein Umbau angrenzender Bereiche).
|
||||
package timingsafe
|
||||
|
||||
import "crypto/subtle"
|
||||
|
||||
// Equal vergleicht zwei Byte-Slices timing-safe. Unterschiedliche Laenge gilt
|
||||
// als "nicht gleich", ohne dass die Laufzeit dabei die Laenge verraet, die
|
||||
// zum Ergebnis gefuehrt hat, mehr als durch den Laengenunterschied ohnehin
|
||||
// unvermeidbar waere.
|
||||
func Equal(a, b []byte) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
return subtle.ConstantTimeCompare(a, b) == 1
|
||||
}
|
||||
|
||||
// EqualString ist die String-Variante von Equal fuer den haeufigen Fall,
|
||||
// dass beide Seiten bereits als string vorliegen (z. B. TOTP-Codes).
|
||||
func EqualString(a, b string) bool {
|
||||
return Equal([]byte(a), []byte(b))
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package timingsafe
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestEqual_SameBytes(t *testing.T) {
|
||||
if !Equal([]byte("geheimnis"), []byte("geheimnis")) {
|
||||
t.Fatal("identische Byte-Slices sollten gleich sein")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEqual_DifferentBytes(t *testing.T) {
|
||||
if Equal([]byte("geheimnis"), []byte("anders123")) {
|
||||
t.Fatal("unterschiedliche Byte-Slices sollten ungleich sein")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEqual_DifferentLength(t *testing.T) {
|
||||
if Equal([]byte("kurz"), []byte("laengererstring")) {
|
||||
t.Fatal("unterschiedliche Laenge sollte immer ungleich sein")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEqual_EmptyVsEmpty(t *testing.T) {
|
||||
if !Equal([]byte(""), []byte("")) {
|
||||
t.Fatal("zwei leere Slices sollten gleich sein")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEqualString_MatchesEqual(t *testing.T) {
|
||||
if !EqualString("abc123", "abc123") {
|
||||
t.Fatal("identische Strings sollten gleich sein")
|
||||
}
|
||||
if EqualString("abc123", "xyz789") {
|
||||
t.Fatal("unterschiedliche Strings sollten ungleich sein")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user