Reputation: 434
First things first,
SECURITY DISCLAIMER:
I'm fully aware that if I use private-encryption -> public-decryption the "encrypted" message is is readable for anyone who has access to the so called "public key".
In a normal use case of rsa this would be fatal!
But in my case the "public key" is meant to be private too.
I'm trying to establish an encrypted connection where the full control stays on one party.
One of the partners is untrusted and if he would got compromised I want to be sure no one else can use the interface (to prevent privilege escalation).
As you can see in this use case encryption itself is in fact not the main reason of asymmetric "encrytion".
You actually get an encrypted data stream which can't be manipulated from a third party even if the key is leaked.
My actual communication should run between a node.js and a python environment.
The URSA node lib already has a feature for the private encryption.
Sadly pyCrypto doesn't support that for reasons mentioned above earlier.
I already tried to cheese the lib and used the private exponent to instantiate a public key object but nodejs can't decrypt the result(not a big surprise).
Does anyone know how to tackle this problem?
Is there another way to get python to do actual private key encryption?
Maybe there is another python lib capable of doing so i couldn't find?
Or maybe its possible to get the nodejs lib to decrypt my cheesie private key encryption?
Upvotes: 1
Views: 1362
Reputation: 434
I have found a working solution for me.
I simply hacked an extra method in the signing object of pyCrypto which does exactly what i want.
This works with python 2.7.9 and 3.4 as far as I tested it.
In the file "[...]/Crypto/Signature/PKCS1_v1_5.py"
is the class "PKCS115_SigScheme"
I simply added following method:
def private_encrypt(self, msg):
modBits = Crypto.Util.number.size(self._key.n)
k = ceil_div(modBits,8) # Convert from bits to bytes
PS = bchr(0xFF) * (k - len(msg) - 3)
m = self._key.decrypt(b("\x00\x01") + PS + bchr(0x00) + msg)
S = bchr(0x00)*(k-len(m)) + m
return S
It's just a manipulated copy of the "sign" function.
Usage looks like:
from Crypto.Signature import PKCS1_v1_5
from Crypto.PublicKey import RSA
plain_message="Hi, I'm going to be encrypted with a private key."
key = RSA.generate(4096)
signer = PKCS1_v1_5.new(key)
bin_enc_msg = signer.private_encrypt(plain_message.encode())
The decryption after the base64 encoded transfer in nodejs with URSA publicDecrypt works fine.
It should be clear from the imports but I want to mention this nonetheless:
This actually encrypts with PKCS1.5 padded rsa.
Another solution would be to combine symmetric encryption with asymmetric signing to be able to verify it but that would require additional effort and complexity I don't want or need.
Upvotes: 3
Reputation: 129
If your goal is to connect a python environment and Node.js with encryption and don't require the use of third party verification, are you required to use RSA Public key encryption? It really sounds like what you're trying to accomplish is Symmetric-key Encryption and you could use AES. The pyCrypto Library already supports this, and some googling provided this library for Node.js on git hub.
Upvotes: 1