GNU/Linux >> Tutoriels Linux >  >> Linux

Comment générer des nombres aléatoires dans le shell BusyBox

$RANDOM et od sont des fonctionnalités facultatives dans BusyBox, je suppose, compte tenu de votre question, qu'elles ne sont pas incluses dans votre fichier binaire. Vous mentionnez dans un commentaire que /dev/urandom est présent, c'est bien, cela signifie que ce que vous devez faire est de récupérer des octets sous une forme utilisable, et non le problème beaucoup plus difficile de la mise en œuvre d'un générateur de nombres aléatoires. Notez que vous devez utiliser /dev/urandom et non /dev/random , voir Est-ce qu'un rand de /dev/urandom est sécurisé pour une clé de connexion ?.

Si vous avez tr ou sed , vous pouvez lire les octets de /dev/urandom et supprimez tout octet qui n'est pas un caractère souhaitable. Vous aurez également besoin d'un moyen d'extraire un nombre fixe d'octets d'un flux :soit head -c (nécessitant FEATURE_FANCY_HEAD à activer) ou dd (nécessitant dd à compiler). Plus vous supprimez d'octets, plus cette méthode sera lente. Pourtant, générer des octets aléatoires est généralement assez rapide par rapport au fork et à l'exécution de binaires externes, donc en supprimer beaucoup ne fera pas beaucoup de mal. Par exemple, l'extrait de code suivant produira un nombre aléatoire entre 0 et 65535 :

n=65536
while [ $n -ge 65536 ]; do
  n=1$(</dev/urandom tr -dc 0-9 | dd bs=5 count=1 2>/dev/null)
  n=$((n-100000))
done

Notez qu'en raison de la mise en mémoire tampon, tr va traiter un peu plus d'octets que ce que dd finira par tenir. tr de BusyBox lit un tampon (au moins 512 octets) à la fois et vide son tampon de sortie chaque fois que le tampon d'entrée est entièrement traité, de sorte que la commande ci-dessus lira toujours au moins 512 octets à partir de /dev/urandom (et très rarement plus puisque la prise attendue de 512 octets d'entrée est de 20 chiffres décimaux).

Si vous avez besoin d'une chaîne imprimable unique, supprimez simplement les caractères non ASCII et peut-être certains caractères de ponctuation ennuyeux :

nonce=$(</dev/urandom tr -dc A-Za-z0-9-_ | head -c 22)

Dans cette situation, j'envisagerais sérieusement d'écrire un petit programme C dédié. En voici un qui lit quatre octets et affiche le nombre décimal correspondant. Il ne repose sur aucune fonction libc autre que les wrappers pour les appels système read et write , vous pouvez donc obtenir un très petit fichier binaire. La prise en charge d'une variable cap passée sous forme d'entier décimal sur la ligne de commande est laissée en exercice; cela vous coûtera des centaines d'octets de code (pas quelque chose dont vous devez vous soucier si votre cible est assez grande pour exécuter Linux).

#include <stddef.h>
#include <unistd.h>
int main () {
    int n;
    unsigned long x = 0;
    unsigned char buf[4];
    char dec[11]; /* Must fit 256^sizeof(buf) in decimal plus one byte */
    char *start = dec + sizeof(dec) - 1;
    n = read(0, buf, sizeof(buf));
    if (n < (int)sizeof(buf)) return 1;
    for (n = 0; n < (int)sizeof(buf); n++) x = (x << 8 | buf[n]);
    *start = '\n';
    if (x == 0) *--start = '0';
    else while (x != 0) {
        --start;
        *start = '0' + (x % 10);
        x = x / 10;
    }
    while (n = write(1, start, dec + sizeof(dec) - start),
           n > 0 && n < dec + sizeof(dec) - start) {
        start += n;
    }
    return n < 0;
}

</dev/urandom sed 's/[^[:digit:]]\+//g' | head -c10

Linux
  1. Quelle est la taille du tampon de tuyau ?

  2. Comment afficher différemment les caractères de contrôle (^c, ^d, ^[, …) dans le shell ?

  3. Comment détecter si le shell est contrôlé depuis Ssh ?

  4. CentOS / RHEL :Comment changer le shell de connexion de l'utilisateur

  5. Comment changer le shell par défaut sous Linux

Comment comparer des nombres et des chaînes dans le script shell Linux

Comment installer Fish, le shell interactif convivial, sous Linux

Comment changer le shell par défaut dans le système Linux

Comment générer un mot de passe aléatoire sous Linux en utilisant /dev/random

Des moyens simples pour générer un mot de passe aléatoire sur Linux Shell

Comment compter le nombre d'octets dans un fichier, regroupant les mêmes octets ?