Dites que je voudrais générer un int sécurisé entre 0 et 27 en utilisant:
func Int(Rand io.Reader, max *big.Int) (n *big.Int, err error)
dans le package "crypto/Rand"
.
Comment je ferais ça?
Je ne comprends pas vraiment comment cela fonctionne. Pourquoi ne renvoie-t-il pas l’un des Go ints intégrés au lieu d’un pointeur sur un type big.Int?
MODIFIER:
Cela serait-il considéré comme suffisamment sécurisé pour les jetons?
func getToken(length int) string {
token := ""
codeAlphabet := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
codeAlphabet += "abcdefghijklmnopqrstuvwxyz"
codeAlphabet += "0123456789"
for i := 0; i < length; i++ {
token += string(codeAlphabet[cryptoRandSecure(int64(len(codeAlphabet)))])
}
return token
}
func cryptoRandSecure(max int64) int64 {
nBig, err := Rand.Int(Rand.Reader, big.NewInt(max))
if err != nil {
log.Println(err)
}
return nBig.Int64()
}
func main() {
fmt.Println(getToken(32))
}
Cela produirait quelque chose comme ceci:
qZDbuPwNQGrgVmZCU9A7FUWbp8eIfn0Z
EwZVoQ5D5SEfdhiRsDfH6dU6tAovILCZ
cOqzODVP0GwbiNBwtmqLA78rFgV9d3VT
Si vous générez des jetons sécurisés pour les identifiants de session, les jetons OAuth Bearer, CSRF ou similaires, vous souhaitez générer un jeton de (idéalement) 256 bits (32 octets) ou d'au moins 192 bits (24 octets).
Un jeton avec des valeurs comprises entre (0-27) peut être forcé brutalement en moins d'une seconde et ne peut pas être considéré comme sécurisé.
par exemple.
package main
import (
"crypto/Rand"
"encoding/base64"
)
// GenerateRandomBytes returns securely generated random bytes.
// It will return an error if the system's secure random
// number generator fails to function correctly, in which
// case the caller should not continue.
func GenerateRandomBytes(n int) ([]byte, error) {
b := make([]byte, n)
_, err := Rand.Read(b)
// Note that err == nil only if we read len(b) bytes.
if err != nil {
return nil, err
}
return b, nil
}
// GenerateRandomString returns a URL-safe, base64 encoded
// securely generated random string.
func GenerateRandomString(s int) (string, error) {
b, err := GenerateRandomBytes(s)
return base64.URLEncoding.EncodeToString(b), err
}
func main() {
// Example: this will give us a 44 byte, base64 encoded output
token, err := GenerateRandomString(32)
if err != nil {
// Serve an appropriately vague error to the
// user, but log the details internally.
}
}
La sortie base64 est sécurisée pour les en-têtes, les formulaires HTTP, les corps JSON, etc.
Si vous avez besoin d'un nombre entier, il peut être utile d'expliquer votre cas d'utilisation, car il serait étrange pour un système d'exiger des jetons en tant que droits.
Voici un code de travail:
package main
import (
"fmt"
"crypto/Rand"
"math/big"
)
func main() {
nBig, err := Rand.Int(Rand.Reader, big.NewInt(27))
if err != nil {
panic(err)
}
n := nBig.Int64()
fmt.Printf("Here is a random %T in [0,27) : %d\n", n, n)
}
Mais pour générer un jeton aléatoire, je ferais quelque chose comme ceci:
package main
import (
"crypto/Rand"
"encoding/base32"
"fmt"
)
func main() {
token := getToken(10)
fmt.Println("Here is a random token : ", token)
}
func getToken(length int) string {
randomBytes := make([]byte, 32)
_, err := Rand.Read(randomBytes)
if err != nil {
panic(err)
}
return base32.StdEncoding.EncodeToString(randomBytes)[:length]
}
Si vous n'avez besoin que d'un petit nombre (c'est-à-dire [0, 255]), vous pouvez simplement lire un octet dans la variable Reader
:
b := []byte{0}
if _, err := Rand.Reader.Read(b); err != nil {
panic(err)
}
n := b[0]
fmt.Println(n)
Aire de jeux: http://play.golang.org/p/4VO52LiEVh (l'exemple ne fonctionnera pas ici, je ne sais pas s'il fonctionne comme prévu ou s'il s'agit d'un bogue de terrain de jeu).