Question

For over a week, I've been using this to implement a RSA secured communication with my server that is in python.

However, I can not for the life of me figure out the proper imports for all the jars.

I have included all the jars found on bouncy castles website and still no dice!

I read that they moved stuff around. If this code is old or broken, what other implementation of RSA with pkcs1 padding is put there?

EDIT:

pub key is in a file named key.pub. how do I read that file in to be used as the key

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2B0wo+QJ6tCqeyTzhZ3
AtPLgAHEQ/fRYDcR0BkQ+lXEhD277P2fPZwla5AW6szqsjR1olkZEF7IuoI27Hxm
tQHJU0ROhrzstHgK42emz5Ya3BWcm+oq5pLDZnsNDnNlrPncaCT7gHQQJn3YjH8q
aibtB1WCoy7ZJ127QxoKoLfeonBDtt7Qw6P5iXE57IbQ63oLq1EaYUfg8ZpADvJF
b2H3MASJSSDrSDgrtCcKAUYuu3cZw16XShuKCNb5QLsj3tR0QC++7qjM3VcG311K
7gHVjB6zybw+5vX2UWTgZuL6WVtCvRK+WY7nhL3cc5fmXZhkW1Jbx6wLPK3K/JcR
NQIDAQAB
-----END PUBLIC KEY-----

EDIT 2: Adding Broken Code based on an answer

package Main;


import org.bouncycastle.util.encoders.Base64;

import javax.crypto.Cipher;
import javax.xml.bind.DatatypeConverter;
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.X509EncodedKeySpec;

public class EncDecRSA {
    public static byte[] pemToDer(String pemKey) throws GeneralSecurityException {
        String[] parts = pemKey.split("-----");
        return DatatypeConverter.parseBase64Binary(parts[parts.length / 2]);
    }

    public static PublicKey derToPublicKey(byte[] asn1key) throws GeneralSecurityException {
        X509EncodedKeySpec spec = new X509EncodedKeySpec(asn1key);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");
        return keyFactory.generatePublic(spec);
    }

    public static byte[] encrypt(PublicKey publicKey, String text) throws GeneralSecurityException {
        Cipher rsa = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding", "BC");//PKCS1-OAEP
        rsa.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] cipher =  rsa.doFinal(text.getBytes());
        String s = new String(cipher);
        System.out.print(s);
//        return cipher;
//        return Base64.encode(rsa.doFinal(text.getBytes()));
        cipher = Base64.encode(cipher);
        return cipher;

    }

    static String readFile(String path)
            throws IOException
    {
        String line = null;
        BufferedReader br = new BufferedReader(new FileReader(path));
        try {
            StringBuilder sb = new StringBuilder();
            line = br.readLine();

            while (line != null) {
                sb.append(line);
                sb.append("\n");
                line = br.readLine();
            }
            return sb.toString();
        } finally {
            br.close();

        }

    }
    public static void main(String[] args) throws IOException, GeneralSecurityException {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

        System.out.println("Working Directory = " +
                System.getProperty("user.dir"));
        String publicKey = readFile("key.public");
        byte[] pem = pemToDer(publicKey);
        PublicKey myKey = derToPublicKey(pem);
        String sendMessage = "{'vid_hash': '917ef7e7be4a84e279b74a257953307f1cff4a2e3d221e363ead528c6b556edb', 'state': 'ballot_response', 'userInfo': {'ssn': '700-33-6870', 'pin': '1234', 'vid': '265jMeges'}}";
        byte[] encryptedDATA = encrypt(myKey, sendMessage);
        Socket smtpSocket = null;
        DataOutputStream os = null;
        DataInputStream is = null;
        try {
            smtpSocket = new Socket("192.168.1.124", 9999);
            os = new DataOutputStream(smtpSocket.getOutputStream());
            is = new DataInputStream(smtpSocket.getInputStream());
        } catch (UnknownHostException e) {
            System.err.println("Don't know about host: hostname");
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for the connection to: hostname");
        }

        if (smtpSocket != null && os != null && is != null) {
            try {
                System.out.println("sending message");
                os.writeBytes(encryptedDATA+"\n");
                os.close();
                is.close();
                smtpSocket.close();
            } catch (UnknownHostException e) {
                System.err.println("Trying to connect to unknown host: " + e);
            } catch (IOException e) {
                System.err.println("IOException:  " + e);
            }
        }
    }
}

Which has the following error:

enter image description here

Here is the bit of python code that does that:

def _decrypt_RSA(self, private_key_loc, package):
    '''
    param: public_key_loc Path to your private key
    param: package String to be decrypted
    return decrypted string
    '''
    from Crypto.PublicKey import RSA 
    from Crypto.Cipher import PKCS1_OAEP 
    from base64 import b64decode 
    key = open('key.private', "r").read() 
    rsakey = RSA.importKey(key) 
    rsakey = PKCS1_OAEP.new(rsakey) 

    decrypted = rsakey.decrypt(package)
    # decrypted = rsakey.decrypt(b64decode(package)) 
    return decrypted

Lastly:

Is this padding scheme with PKCS1-OAEP.

That is a major requirement for this to work.

Note that I have tried it with both base64 encode and without

Was it helpful?

Solution

This example is for SpongyCastle - Android repackage of BouncyCastle. They differ as you noticed. However, making encryption in Java is as simple as this

Convert Base64 encoded key string to ASN.1 DER encoded byte array

public static byte[] pemToDer(String pemKey) throws GeneralSecurityException {
    String[] parts = pemKey.split("-----");
    return DatatypeConverter.parseBase64Binary(parts[parts.length / 2]);
}

Convert ASN.1 DER encoded public key to PublicKey object

public static PublicKey derToPublicKey(byte[] asn1key) throws GeneralSecurityException {
    X509EncodedKeySpec spec = new X509EncodedKeySpec(asn1key);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");
    return keyFactory.generatePublic(spec);
}

Encrypt data

public static byte[] encrypt(PublicKey publicKey, String text) throws GeneralSecurityException {
    Cipher rsa = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding", "BC");
    rsa.init(Cipher.ENCRYPT_MODE, publicKey);
    return rsa.doFinal(text.getBytes());
}

bcprov-jdk15on-150.jar is the only jar needed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top