$RANDOM
e od
sono funzionalità opzionali in BusyBox, presumo data la tua domanda che non siano incluse nel tuo file binario. In un commento menzioni che /dev/urandom
è presente, va bene, significa che ciò che devi fare è recuperare i byte da esso in una forma utilizzabile, e non il problema molto più difficile dell'implementazione di un generatore di numeri casuali. Nota che dovresti usare /dev/urandom
e non /dev/random
, vedi È sicuro un rand da /dev/urandom per una chiave di accesso?.
Se hai tr
o sed
, puoi leggere i byte da /dev/urandom
e scartare qualsiasi byte che non è un carattere desiderabile. Avrai anche bisogno di un modo per estrarre un numero fisso di byte da uno stream:head -c
(richiede FEATURE_FANCY_HEAD
da abilitare) o dd
(richiede dd
da compilare). Più byte scarti, più lento sarà questo metodo. Tuttavia, la generazione di byte casuali di solito è piuttosto veloce rispetto al fork e all'esecuzione di binari esterni, quindi scartarne molti non farà molto male. Ad esempio, il seguente frammento produrrà un numero casuale compreso tra 0 e 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
Nota che a causa del buffering, tr
elaborerà un bel po' di byte in più rispetto a quanto dd
finirà per mantenere. tr
di BusyBox legge un buffer pieno (almeno 512 byte) alla volta e scarica il suo buffer di output ogni volta che il buffer di input è completamente elaborato, quindi il comando precedente leggerà sempre almeno 512 byte da /dev/urandom
(e molto raramente di più poiché il recupero previsto da 512 byte di input è di 20 cifre decimali).
Se hai bisogno di una stringa stampabile univoca, elimina i caratteri non ASCII e forse alcuni fastidiosi caratteri di punteggiatura:
nonce=$(</dev/urandom tr -dc A-Za-z0-9-_ | head -c 22)
In questa situazione, prenderei seriamente in considerazione la possibilità di scrivere un piccolo programma C dedicato. Eccone uno che legge quattro byte e restituisce il numero decimale corrispondente. Non si basa su alcuna funzione libc diversa dai wrapper per le chiamate di sistema read
e write
, quindi puoi ottenere un binario molto piccolo. Il supporto di una variabile cap passata come numero intero decimale sulla riga di comando viene lasciato come esercizio; ti costerà centinaia di byte di codice (non qualcosa di cui devi preoccuparti se il tuo target è abbastanza grande per eseguire 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