RSA cryptography between Python and Java

R

Rob Knop

I've created an RSA key in Java. I have exported the public key by
making it into a X509EncodedKeySpec and spitting out the result of
getEncoded().

I want to use this public key to encode something in python that I will
send to Java, and then decode in Java with the corresponding private
key.

Are there any python libraries that will take a public key in this
format and do RSA encoding on it?
 
R

Rob Knop

Paul Rubin said:

Thanks, but that looks like a library for setting up a secure connection
between two ends. What I need is the ability to encrypt with a public
key in Python, where that public key was generated in Java as described,
and where the cipertext can later be decrypted with the corresponding
secret key in Java.
 
P

Paul Rubin

Rob Knop said:
Thanks, but that looks like a library for setting up a secure connection
between two ends. What I need is the ability to encrypt with a public
key in Python, where that public key was generated in Java as described,
and where the cipertext can later be decrypted with the corresponding
secret key in Java.

Yes, I think that library has the function that you want. It's just
X509 DER encoding.
 
P

Piet van Oostrum


I have looked into tlslite and found no easy way to do this. Maybe I
overlooked it. On the other hand with M2Crypto it isn't that hard.

However, M2Crypto wants to load keys in PEM format rather than the DER
format that the Java getEncoded() produces. It is not hard to convert
this to PEM format: just Base64 encode it and put a header and trailer
line around it. The conversion can be done with openssl or just on the
fly in the Python code.
Please note that the text to be encrypted must be smaller than the key
size (at least 11 bytes smaller). You shouldn't encrypt large data with
RSA anyway: it is too slow. Normally you would encrypt a session key
with RSA and encrypt the data with the session key using a symmetric
algorithms like AES.

Here is an example script:
If your OS doesn't have /dev/urandom you should probably seed OpenSSL's
PRNG to be more secure.
------------------------------------------------------------------------
from M2Crypto import BIO, RSA

pubkey = open("pubkey.der", 'rb').read()

import base64
pubkey = base64.encodestring(pubkey)
pubkey = '-----BEGIN PUBLIC KEY-----\n' + pubkey + '-----END PUBLIC KEY-----'

bio = BIO.MemoryBuffer(pubkey)
rsa = RSA.load_pub_key_bio(bio)

plaintext = "This is my secret text."

codetext = rsa.public_encrypt(plaintext, RSA.pkcs1_padding)

with open("codetext", 'wb') as out:
out.write(codetext)
------------------------------------------------------------------------
The following Java program decodes this with the corresponding private
key:
------------------------------------------------------------------------
import java.security.*;
import javax.crypto.*;
import java.security.spec.*;
import java.security.interfaces.*;
import java.io.*;

class Decrypt {

public static void main(String[] args) {

byte[] key = null;
try {
File file = new File("privkey.der");
FileInputStream keyfile = new FileInputStream(file);
key = new byte[(int)file.length()];
DataInputStream dis= new DataInputStream(keyfile);
dis.readFully(key);
dis.close();
}
catch(FileNotFoundException e)
{
System.out.println("Key file not found" + e);
}
catch (IOException e) {
System.out.println("Can't read key file" + e);
}

byte[] codetext = null;
try {
File file = new File("codetext");
FileInputStream codefile = new FileInputStream(file);
codetext = new byte[(int)file.length()];

DataInputStream dis = new DataInputStream(codefile);
dis.readFully(codetext);
dis.close();
}
catch(FileNotFoundException e)
{
System.out.println("Code file not found" + e);
}
catch (IOException e) {
System.out.println("Can't read code file" + e);
}

try {

KeyFactory keyFactory = KeyFactory.getInstance("RSA");

PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(key);
RSAPrivateKey rsakey = (RSAPrivateKey) keyFactory.generatePrivate(privSpec);

Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding");

c.init(Cipher.DECRYPT_MODE, rsakey);
byte[] decrypted = c.doFinal(codetext);
System.out.println("Decrypted text:");
System.out.println(new String(decrypted));

}
catch (NoSuchAlgorithmException e) {
System.out.println("Wrong Algorithm " + e);
}
catch (InvalidKeyException e) {
System.out.println("Invalid key " + e);
}
catch (IllegalBlockSizeException e) {
System.out.println("Illegal block size" + e);
}
catch (NoSuchPaddingException e) {
System.out.println("Illegal padding " + e);
}
catch (BadPaddingException e) {
System.out.println("Bad padding " + e);
}
catch (InvalidKeySpecException e) {
System.out.println("Invalid keyspec " + e);
}
}
}
 
M

Michael Ströder

Piet said:
Please note that the text to be encrypted must be smaller than the key
size (at least 11 bytes smaller). You shouldn't encrypt large data with
RSA anyway: it is too slow. Normally you would encrypt a session key
with RSA and encrypt the data with the session key using a symmetric
algorithms like AES.

I'd use CMS (AKA PKCS#7) for encrypted/signed data with X.509 certs. One
should not invent another message format.

Ciao, Michael.
 
P

Piet van Oostrum

MS> I'd use CMS (AKA PKCS#7) for encrypted/signed data with X.509 certs. One
MS> should not invent another message format.

Yes but the original question was not about X.509 certs. Just the RSA
public key. I don't know what the OP wants to do with it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,829
Messages
2,569,737
Members
45,521
Latest member
maryb

Latest Threads

Top