web-dev-qa-db-fra.com

Comment puis-je générer un int aléatoire en utilisant le package "crypto/Rand"?

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
15
Aiden

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. 

17
elithrar

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]
}
16
HectorJ

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).

0
Ainar-G