Search code examples
python-3.xencryptionrsaprivate-key

Error with creating Private Key in Python 3 RSA


I'm trying to create a random RSA Private key in Python but I'm getting a Error message and I don't know what to do. The code I'm using now is from this Thread I created earlier, but I won't work.

Code:

from Crypto import Random
from Crypto.PublicKey import RSA

def random_generator():
    return Random.new().read(32)

private_key = RSA.generate(1024, random_generator)
print(str(private_key))

Error Message:

Traceback (most recent call last):
  File "/home/simon/Python/Projects/FileServer/encrypt.py", line 7, in <module>
    private_key = RSA.generate(1024, random_generator)
  File "/usr/lib/python3/dist-packages/Crypto/PublicKey/RSA.py", line 508, in generate
    obj = _RSA.generate_py(bits, rf, progress_func, e)    # TODO: Don't use legacy _RSA module
  File "/usr/lib/python3/dist-packages/Crypto/PublicKey/_RSA.py", line 50, in generate_py
    p = pubkey.getStrongPrime(bits>>1, obj.e, 1e-12, randfunc)
  File "/usr/lib/python3/dist-packages/Crypto/Util/number.py", line 265, in getStrongPrime
    randfunc)
TypeError: random_generator() takes 0 positional arguments but 1 was given

Solution

  • From the documentation:

    generate(bits, randfunc=None, progress_func=None, e=65537)

    Parameters:

    ...

    • randfunc (callable) - Random number generation function; it should accept a single integer N and return a string of random data N bytes long. If not specified, a new one will be instantiated from Crypto.Random.

    Your random_generator() doesn't take any parameters. It is supposed to take one parameter - the number of byes to return. Also the implementation is bad - you're creating a new instance every time which could seriously weaken the randomness of the numbers it generates.

    But since you're just using a Crypto.Random instance there's no need for you to specify this parameter at all - just leave it out.

    from Crypto.PublicKey import RSA
    
    private_key = RSA.generate(1024)
    print(str(private_key))
    

    If you insist on providing your own randfunc, pass it the bound read method of a Crypto.Random instance:

    from Crypto import Random
    from Crypto.PublicKey import RSA
    
    r = Random.new()
    
    private_key = RSA.generate(1024, r.read)
    print(str(private_key))