PyCrypto: Decrypt only with public key in file (no private+public key)
Question: Hello everyone.

I am trying to play a bit with RSA public and private keys and
encryption/decryption with _PyCrypto_ and I have encountered and issue that
seems kind of strange to me (it probably makes a lot of sense the way it's
working now, but I don't know much about RSA asymmetric encryption and that's
why it's puzzling me). It is the inability I have encountered to decrypt
something having only the public key.

Here's the thing: I have a server and a client. I want the server to
"recognize" and register the client and show it in a list of "known devices".
The client will have the public key of the server and the server will have the
public key of the client, so when the client communicates with the server, it
will encrypt its data with his client's private key and with the server's
public key. By doing this, only the proper server will be able to open the
data (with its private key) and will be able to verify that the sender is
actually the client that claims to be... well... or at least, that's what I
think, because I'm pretty newbie in this asymmetric encryption. The idea is
that when one of those clients wakes up, it will send its public key
(encrypted with the server's public key, of course, but that's probably not
relevant at this point... yet) saying "_Hey, I'm a new client and this is my
public key. Register that key with my UUID_ " and the server will obey,
associating that public key with the client's UUID and use that key to decrypt
data coming from that client. I just want to transmit the client's public key,
keeping its private key secret, secret, secret (it's private, right?)

I am doing some tests with openssl and very simple Python scripts that use
_PyCrypto_ (actually, not even in a server/client architecture or anything...
just trying to encrypt something with a private key and decrypt it with the
public key)

First of all, I have created a public/private key set with:

    
    
    openssl genrsa -out ~/myTestKey.pem -passout pass:"f00bar" -des3 2048
    

Ok, first thing that puzzles me a bit... It generates only one file, with both
the private and the public keys... Well... O'right... whatever. I can extract
the public key with:

    
    
    openssl rsa -pubout -in ~/myTestKey.pem -passin pass:"f00bar" -out ~/myTestKey.pub
    

So I thought I had my couple of private (_private+public, actually_) and
public keys in `~/myTestKey.pem` and `~/myTestKey.pub` respectively. Well...
apparently I'm doing something wrong, because _PyCrypto_ doesn't like this
assembly. And I don't know why.

I have two very simple test scripts, "`encryptor.py`" and "`decryptor.py`".
The "`encryptor.py`" should encrypt something with the private key, and
"`decryptor.py`", decrypt it with the public key. I know... I'm a parangon of
originality...

So, I encrypt the string "_Loren ipsum_ " with my "`encryptor.py`" (with
private key):

\----------- encryptor.py ----------------

    
    
    #!/usr/bin/python
    
    from Crypto.PublicKey import RSA
    
    def encrypt(message):
        externKey="/home/borrajax/myTestKey.pem"
        privatekey = open(externKey, "r")
        encryptor = RSA.importKey(privatekey, passphrase="f00bar")
        encriptedData=encryptor.encrypt(message, 0)
        file = open("/tmp/cryptThingy.txt", "wb")
        file.write(encriptedData[0])
        file.close()
    
    if __name__ == "__main__":
        encryptedThingy=encrypt("Loren ipsum")
    

* * *

And it works fine. Well... I suppose so, because in the file
"`/tmp/cryptThingy.txt`" I get a lot of gibberish. It looks really, really
encrypted to me.

But when I try to decrypt it using just the file that contains just the public
key...

\----------- decryptor.py ---------------

    
    
    #!/usr/bin/python
    
    from Crypto.PublicKey import RSA
    
    def decrypt():
        externKey="/home/borrajax/myTestKey.pub"
        publickey = open(externKey, "r")
        decryptor = RSA.importKey(publickey, passphrase="f00bar")
        retval=None
    
        file = open("/tmp/cryptThingy.txt", "rb")
        retval = decryptor.decrypt(file.read())
        file.close()
        return retval
    
    
    if __name__ == "__main__":
        decryptedThingy=decrypt()   
        print "Decrypted: %s" % decryptedThingy
    

* * *

... _PyCrypto_ yells at me with a:

    
    
      File "/usr/local/lib/python2.7/dist-packages/pycrypto-2.5-py2.7-linux-i686.egg/Crypto/PublicKey/RSA.py", line 107, in _decrypt
        mp = self.key._decrypt(cp)
    TypeError: Private key not available in this object
    

Yeah, of course it's not available! I extracted the public key! It took me 2
hours finding how to do it properly!!

What am I missing? As I said, I'm pretty newbie in this public/private
asymmetric key encryption so I might have a core "conceptual error"... Any
hint will be appreciated.

¡Thank you in advance!


Answer: You have it the wrong way round, you encrypt with the public key, and decrypt
with the private key.

> The publicly available encrypting-key is widely distributed, while the
> private decrypting-key is known only to the recipient. Messages are
> encrypted with the recipient's public key and can be decrypted only with the
> corresponding private key. [Source](https://en.wikipedia.org/wiki/Public-
> key_cryptography#How_it_works)

The idea is that you give the sending side the public key (which anyone can
have, so you can distribute it in the open) then you encrypt the data with it,
then decrypt it on your end with your private key (which only you have). This
way the data stays secure.

You can encrypt something with the private key as the private key contains the
information required to make the public key, but it would be unusual to do so,
as normally the person encrypting the data does _not_ have the private key.

