2

I'm working on a sharing protocol, and the handshake, authentication etc. is done with RSA keys. By default I use 4096 bit keys, but it seems the beginning and end of any key generated are the same, how worried should I be?

This phenomenon happens both on Windows and Linux.

The python code generating the keys is roughly this:

from Crypto.PublicKey import RSA
from Crypto import Random

random_generator = Random.new().read
prv = RSA.generate(4096, random_generator)

Some example keys I generated (snipped), two on Windows, one on Linux:

30820222300d06092a864886f70d01010105000382020f003082020a0282020100b420065527689ff14a115a9c1b63bf79294407bf621d4ab...0da370203010001
30820222300d06092a864886f70d01010105000382020f003082020a0282020100b39291f674eddfe8d8571b856bf7f83c01ca8ba231f16e8...678590203010001
30820222300d06092a864886f70d01010105000382020f003082020a02820201009a2bec7fad52fe7c50cce509b3406b8ff981a626f28082e...0e98d0203010001

As you can see, the some 66 first and 10 last nibbles are identical, over 300 bits.

Should I ditch the rng for some other or am I just too paranoid?

3
  • If you are using PyCrypto, note that it was last updated in 2014. There are newer forks such as pycryptodome that are mostly compatible with the PyCrypto API. Not sure if it will help with your specific problem though. – multithr3at3d Dec 19 '20 at 13:56
  • Can you show the statement that you used to print the private key, which produced the snipped output that you posted? – mti2935 Dec 19 '20 at 15:38
  • 3
    What you show are the encoded public keys, not private. (@mti2935) For all RSA keys of a fixed size over 2040 and using e=F4 as is now conventional, the first 24 bytes of X.509/SPKI in DER and the first 9 and last 5 bytes of PKCS1 RSAPublicKey in DER are the same. If you compared private key encodings you would get some but not all of the same similarities because some of the elements in a privatekey vary in length -- only a little, but enough to change the DER headers – dave_thompson_085 Dec 20 '20 at 2:36
6

The two large primes that make up the RSA private key are different each time you run the script.

I added a line to the end of your script, to output the RSA private key in PEM format produced by the script:

from Crypto.PublicKey import RSA
from Crypto import Random

random_generator = Random.new().read
prv = RSA.generate(4096, random_generator)

print(prv.exportKey().decode())

Then, I saved the script as genrsa.py. If you run genrsa.py, you'll see that it produces an RSA private key, in PEM format.

Try running the script, and redirect the output to a file called privatekey.pem:

 python3 genrsa.py > privatekey.pem

Now, use openssl to examine the contents of privatekey.pem:

openssl rsa -noout -text -inform PEM -in privatekey.pem

Look at the two primes. Then, repeat the steps above, and compare the two primes created in the second run to those created in the first run. The two pairs are very different.

With regard to the question about why the beginning and ending bytes of the PEM file produced are always the same - this has to do with the RSA format itself, and the ASN.1 and DER encoding standards that are used to create PEM files. See https://stackoverflow.com/questions/18039401/how-can-i-transform-between-the-two-styles-of-public-key-format-one-begin-rsa for more information.

For more information on the anatomy of an RSA private key PEM file, and how you can examine the underlying components of the private key contained in the file, see: https://crypto.stackexchange.com/questions/45151/anatomy-of-an-rsa-private-key.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.