go / expert
Snippet
Erzeugung kryptografisch sicherer Session-IDs
math/rand ist ein deterministischer PRNG mit globaler Seed-Quelle; aus wenigen Ausgaben kann ein Angreifer den Seed rekonstruieren und alle künftigen Tokens vorhersagen. crypto/rand zieht aus dem CSPRNG des Betriebssystems — getrandom unter Linux, RtlGenRandom unter Windows, /dev/urandom unter macOS — und meldet Lesefehler, statt heimlich auf einen schwachen Fallback umzuschalten. Die Bytes mit base64.RawURLEncoding zu kodieren liefert eine kompakte, URL-sichere Zeichenkette ohne Padding. Das 16-Byte-Minimum schützt gegen Birthday-Kollisionen bei realistischen Session-Mengen; 32 Bytes sind in Produktion üblich.
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
package mainimport ("crypto/rand""encoding/base64""fmt")func newToken(nBytes int) (string, error) {if nBytes < 16 {return "", fmt.Errorf("need >=16 bytes, got %d", nBytes)}b := make([]byte, nBytes)if _, err := rand.Read(b); err != nil {return "", fmt.Errorf("crypto/rand: %w", err)}return base64.RawURLEncoding.EncodeToString(b), nil}func main() {tok, err := newToken(32)if err != nil {panic(err)}fmt.Println(tok)}
Erklärung
1
if nBytes < 16 {
Parameter, die zu schwache Tokens erzeugen würden, ablehnen. Validierung an der API-Grenze ist günstiger als ein späteres Audit aller Aufrufstellen.
2
if _, err := rand.Read(b); err != nil {
crypto/rand.Read kann fehlschlagen — etwa wenn der Entropie-Pool des Kernels in einem abgeschotteten Container nicht erreichbar ist. Diesen Fehler nie ignorieren.
3
return "", fmt.Errorf("crypto/rand: %w", err)
%w erlaubt Aufrufern, den zugrunde liegenden io-Fehler über errors.Is zu erkennen, ohne den sicherheitsrelevanten Präfix zu verlieren.
4
base64.RawURLEncoding.EncodeToString(b)
RawURLEncoding nutzt - und _ statt + und / und verzichtet auf =-Padding — sicher in Cookies, Query-Strings und Pfadsegmenten.