0

I'm trying to generate a 2048 bit long prime number, this is my code so far:

#!/bin/bash

generate_random() {
    hex=$(head -c 256 /dev/urandom | xxd -p)
    bc <<< "ibase=16; $hex"
}

p=$(generate_random)

echo "$p"

While running the script I get (standard_in) 1: syntax error followed by random zeroes.

Anyone knows what is causing this error and how can I fix it? I've tried with bash -x, but it doesn't add any useful information.

STerliakov
  • 4,983
  • 3
  • 15
  • 37
chyxo
  • 19
  • 4
  • What should `$hex` contain and what should `bc` output? – Cyrus Dec 29 '22 at 15:14
  • @Cyrus `$hex` contains a random number generated by `/dev/urandom` in hex format. `bc` convert the hex string stored in `$hex` to a decimal number – chyxo Dec 29 '22 at 15:20
  • Hint: you can simplify the problem by doing a `bc <<< "ibase=16; 868f"`, which would also show this error. If you would run this with -x turned on, you would see how the input to `bc` actually looks like. – user1934428 Dec 29 '22 at 16:03

2 Answers2

3

First, bc understands only upper-case letters as hex digits (at least by default). Second, you have separators in your xxd output, so you generate multiple numbers with bc later.

This should work:

#!/bin/bash

generate_random() {
    hex=$(head -c 256 /dev/urandom | xxd -p -u | tr -d '\n')
    bc <<< "ibase=16; $hex"
}

p=$(generate_random)
echo "$p"

-u flag to xxd instructs it to output upper-case letters as digits, and tr removes separators.

Example output:

84404284040092528807148386035025161100484110236893077703095592941720\
00537078513504880246726730474236368181068985417211434943913923235822\
01284401417146606673073772989889733010524123703686975444423088406509\
44767677616371794606797386146855833950295071249000795855185540560405\
62673903614333076371092344026999031152809898928396395497832309795471\
93897215963003601022703133486344387720277877558264139632520964120681\
97764906669023878701319760947789227343517474218584987497204300184084\
62846775760153647010072072799120566180042021620262646969602253704108\
06274157727080642084167983313757899766696995668747042179553171962777\
5716

To remove newline separators and backslashes, you can do

p_joined=$(echo "$p" | sed -z 's=\\\n==g')
echo "$p_joined"

instead.

STerliakov
  • 4,983
  • 3
  • 15
  • 37
0

An alternative way might be

printf -v hex '%s' $(od -v -An -N256 -x /dev/urandom)
read dec < <(bc <<< "ibase=16; ${hex^^}")
echo $dec
M. Nejat Aydin
  • 9,597
  • 1
  • 7
  • 17