Search code examples
javapython-2.7rsapublic-key-encryptionpycrypto

Converting java crypto code to python equivalent


I have been trying to convert the below java code to its python equivalent:

Encrypt.java

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import org.apache.commons.codec.binary.Base64;
//import org.jose4j.base64url.Base64;

public class Encrypt {

    public static void main(String[] args)
            throws InvalidKeySpecException, NoSuchAlgorithmException, UnsupportedEncodingException, CertificateException, FileNotFoundException {
        PublicKey pubKey; 
        Object localObject1 = new
         String("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA76y3+1w4Ld9Q4WvHQkCkg6qjwq2wWOYMV9nAthX6ugatNlShRb2gBmy"
         +
         "qvh7tOYHhjAhkG9Z33jCVinPuhgb0ioa5/sFAgP5LDdo5SBk4b4n/wRUbdMhfFFcTT0As2OsmdBc2iONUaG4g3WjgRODxy6LLahms6YgTnG+AqeDo8LpXxsiFXe"
         +
         "iqGUyKQU1l16BPc2xyG+tDitFbKHx9pDL12e/w5b4G4Zg4yJgbNlZrGc3Udz5EbDREnAwirjAA3F6x2DF3j746vETb1g2y6+P5sS4lvG3XmaB1JBlhNh5qpqADRqmE"
         + "MWeiYhrRcK9KjS1URSUizGPo96d8R82DmXvYKQIDAQAB");

         //localObject1 = new X509EncodedKeySpec(Base64.decode(((String)localObject1).getBytes("utf-8")));
         localObject1 = new X509EncodedKeySpec(Base64.decodeBase64(((String)localObject1).getBytes("utf-8")));
         localObject1 = KeyFactory.getInstance("RSA").generatePublic((KeySpec)localObject1);
         System.out.println((PublicKey)localObject1);
         System.out.println("___________________________________________________________________________________________________________________________________________________");

//       String secret_pub_key= //"-----BEGIN RSA PUBLIC KEY-----" +
//               "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwkvq7mHuTMGeJF/qiAot"+
//               "OcLTd6hjDEcMHIk2IY35JInuypD6WieogOxSS6kHYho/U+BW/Cgz0XjziPIQSJZx"+
//               "AGOrtdZrTa6n6S6I65YB2wPB93lLi/qnBmUSetEgAgM+MOfiYT8Dift9Mut+BvbE"+
//               "iFMH163ovoiTyLDpbTYDB6InzFzu1l7G01pi/ZAc69kWrJ+yNMEUcnAerRPt30et"+
//               "XAbKD2lC696VJa/2xtWZ5T7vwMpFLIaGFAg228ZifgwDIRFsBmwPsAsngQSGVVBo"+
//               "Ijm3fb0PUDV4MTw+cNT0ldHbYCAWy6zgA0K7eL5LcUN8+ai7u6VMWYUT4FAvYNiP"+
//               "IwIDAQAB";
//               //"-----END RSA PUBLIC KEY-----";
//          X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(Base64.decode(secret_pub_key));
//          KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//          PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);

         Object secret_pub_key= new String(//"-----BEGIN RSA PUBLIC KEY-----" +
                 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApzQvzc+chU92SSh2eukY"+
                 "ycdTJArCjL4+AqW8a2lKZ2jb5g04q6FGSRJgNkuggXt7U5ys5pb+J0699vY9rzgz"+
                 "+WmH6W/ZRZ2hAf3rtWaC1YYetD1SfmD2OGItGfkFYuppjjjKXEnTDzCBQT5IL7hd"+
                 "lnlCfpDkcPmJWvKJU+5gJek9RanVQYXLWgtOIVrQ7LJhQEFDMuYSw+rz7+paBxNq"+
                 "XeHTvDk/ylGtHjb3xOvbVg3DfL2z76YYX69Ae3Cd1rlqaY0IT01k3oeqNZg3638T"+
                 "i8l+6ytwChRhtOHZh5XCaW6Cfbz2nezgYgY1qTAKK05o8Of+W/dErUt4166qnjBl"+
                 "+wIDAQAB");
                 //"-----END RSA PUBLIC KEY-----";


         secret_pub_key = new X509EncodedKeySpec(Base64.decodeBase64(((String)secret_pub_key).getBytes("utf-8")));
         secret_pub_key =  KeyFactory.getInstance("RSA").generatePublic((KeySpec)secret_pub_key);
         pubKey = (PublicKey)secret_pub_key;

        Object localObject;
        Lc lc = new Lc();
        System.out.println("\n\nlc.pub is" + lc.pub);
        System.out.println("\n\n\nokokokokok" + pubKey.getEncoded());
        //byte[] arrayOfByte = new String(Base64.encodeBase64(lc.pub.getEncoded())).getBytes();
        byte[] arrayOfByte = new String(Base64.encodeBase64(pubKey.getEncoded())).getBytes();
        StringBuilder localStringBuilder1 = new StringBuilder();
        int i = 0;
        while (i < arrayOfByte.length) {
            if (arrayOfByte.length > i + 200) {
                localObject = Arrays.copyOfRange(arrayOfByte, i, i + 200);
            } else {
                localObject = Arrays.copyOfRange(arrayOfByte, i, arrayOfByte.length + 1);
            }
            StringBuilder localStringBuilder2 = new StringBuilder();
            lc.pub = (PublicKey)localObject1;
            localObject = new String((byte[])localObject);
            localStringBuilder1.append(lc.upperDot((String)localObject) + ":::");
            i += 200;
        }
        System.out.println("The ducking key is " + localStringBuilder1.toString());
    }
}

Lc.java

import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

public class Lc {
    public static PublicKey pub;
      public static PrivateKey pri;
      public byte[] by;
      public String dot;
      public Lc() {
          Object localObject = "RSA";
          try
          {
            localObject = KeyPairGenerator.getInstance((String)localObject);
            KeyPair localKeyPair = ((KeyPairGenerator)localObject).generateKeyPair();
            localObject = localKeyPair.getPublic();
            pub = (PublicKey)localObject;
            localObject = localKeyPair.getPrivate();
            pri = (PrivateKey)localObject;
          }
          catch (NoSuchAlgorithmException localNoSuchAlgorithmException)
          {
            localNoSuchAlgorithmException.printStackTrace();
          }
    }
      public static String upperDot(String paramString)
      {
        Object localObject = "RSA/ECB/PKCS1Padding";
        try
        {
          Cipher localCipher = Cipher.getInstance((String)localObject);
          localObject = pub;
          int i = 1;
          localCipher.init(i, (Key)localObject);
          localObject = paramString.getBytes();
          byte[] arrayOfByte1 = localCipher.doFinal((byte[])localObject);
          byte[] arrayOfByte2 = Base64.encodeBase64(arrayOfByte1);
          localObject = new String(arrayOfByte2);
          return (String)localObject;
        }
        catch (Exception localException)
        {
          System.out.print(localException);
        }
        return null;
      }
}

please ignore the bad design of the above 2 java files and the debug print statements

The output that the above produces, which is of interest to me is the content of the last output statement :

The ducking key is t4z2jf9GKtKvXiXCPYU3u7Y0LwQOOeQBVi+YRATc3GqyTNb085bRLUVqiNT5v/ZcZl2FZPegeN8OTG9vPbwuY1HrQ04xv0vUf3ohJORiUXwEQtoBVMDnKHib50FPZCbAZIp/1u0KgEPBV9rEe7BmHi2UGCNnp0e50G68cBPLknUinBIIYIIrw/o3U4SAT+uBdo6wyi/x0tWR3El8gJpL34JJVWzdzi4y61cPZI31gxyY19t1EzzmtqB0wnjV5RvTsavR5s3RgtBu3EV+b43poam2K0CsRyfB2lFawkZBnvRL6GzvozBpUYe4awdPbU4Pjvuju5B3zWXloQ5kMVZAkg==:::MpcHcJWhGdYrS1VLza+ereOU1ZRZ9LyVTN0KBBdQLIjYXChX1eKtRdftrF306L5BE8Ni9ibTylbcsc6tocphVpYnCvYN2eKVcEoHLyk9Iz/Cf2ikYJCUFtHh/cPnSILhwI7txdVds0Il58uDMevMnvvRntqVR7nw6UUmUVwmtFvNWVdceP61BHc9YsDMdQs8jPOeGAHWmqA2g4ODYB2W07yQhmwNIQZEmkmrfRHUd1dqM57sIWS9HdgEbrnqhyt1pIWrCxzgYbzZCuaDS/llcFsqgLBbaPpTg2qNUFi2x3r1jJ1UeJeX+y/mOhrEvBXSLmadsCYmEROIutNgoVWigg==:::

Now I want to achieve the exact same behavior through python (2.7 if that matters). I have so far relied on pycrypto and M2Crypto but neither has been helpful.

Here's my attempt at making a python equivalent of the above :

from Crypto.PublicKey import RSA
from base64 import b64decode
from base64 import b64encode

def ecnryptorFun(key, secret):
  encrypted = key.encrypt(secret, 1)
  final_text = b64encode(encrypted[0])
  return final_text

def sayHello(body):
    url = 'https://consumer-app-development.appspot.com/api/sayHello'
    res = requests.post(url=url, data=body)
    return res.text

key64 = b'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA76y3+1w4Ld9Q4WvHQkCkg6qjwq2wWOYMV9nAthX6ugatNlShRb2gBmyqvh7tOYHhjAhkG9Z33jCVinPuhgb0ioa5/sFAgP5LDdo5SBk4b4n/wRUbdMhfFFcTT0As2OsmdBc2iONUaG4g3WjgRODxy6LLahms6YgTnG+AqeDo8LpXxsiFXeiqGUyKQU1l16BPc2xyG+tDitFbKHx9pDL12e/w5b4G4Zg4yJgbNlZrGc3Udz5EbDREnAwirjAA3F6x2DF3j746vETb1g2y6+P5sS4lvG3XmaB1JBlhNh5qpqADRqmEMWeiYhrRcK9KjS1URSUizGPo96d8R82DmXvYKQIDAQAB'

keyDER = b64decode(key64)
keyPub = RSA.importKey(keyDER)

secret = b"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApzQvzc+chU92SSh2eukYycdTJArCjL4+AqW8a2lKZ2jb5g04q6FGSRJgNkuggXt7U5ys5pb+J0699vY9rzgz+WmH6W/ZRZ2hAf3rtWaC1YYetD1SfmD2OGItGfkFYuppjjjKXEnTDzCBQT5IL7hdlnlCfpDkcPmJWvKJU+5gJek9RanVQYXLWgtOIVrQ7LJhQEFDMuYSw+rz7+paBxNqXeHTvDk/ylGtHjb3xOvbVg3DfL2z76YYX69Ae3Cd1rlqaY0IT01k3oeqNZg3638Ti8l+6ytwChRhtOHZh5XCaW6Cfbz2nezgYgY1qTAKK05o8Of+W/dErUt4166qnjBl+wIDAQAB"

#secret1 = b64encode(secret)
arrayOfByte = bytearray(secret)

i = 0 
localStringBuilder1 = ""
while i < len(arrayOfByte):  
  if len(arrayOfByte) > (i+200):
    localObject = arrayOfByte[i:i+200]
  else:
    localObject = arrayOfByte[i:len(arrayOfByte)+1]
  localObj_byte_array = bytearray(localObject)
  localStringBuilder1 = localStringBuilder1 + ecnryptorFun(keyPub, str(localObject)) + ':::'
  #localStringBuilder1 = localStringBuilder1 + ecnryptorFun(encryption_key, localObj_byte_array) + ':::'
  i += 200;

print localStringBuilder1

Output of the above python code

vkqbraD/5HMvs9LG59VXCGCLUoJ0msU6fVvLMDCc8fQ41S3R3IC0EfxLCk9FoHUIGK5h90Rd0at2ROvcOVCtESAYZlYYCB1U99NqWCFLvyDBxS4uEAVHD5yv4U82Dmn/p/asi+D/GxnvP/xvyiI+tp39lWx77DuV4hlnRbltHu9f4o4cvqZ+Nn7wCzY1TBzIClT8f4lx2g9E/5+mhfkQIHejGIAMyJXl3xy+qhQSoy8DvudGQU95eGfDRdci4yqOwDeG2+QlUip627tMbttAroWQjM8jC419kFPetTlmV/RczE/vcwnyM3iEnrhB9KnjRLYEecJ8mEYU7L/TxBe+Tg==:::V1oZBPETF9ryap59T4zOwfW0/pASSCULWL8ZlvUrSlRLeaZmIxplNmewqyUnrhwIbnpDvwhmz7+2/Dd2EN4hJndRnGl7aoEX8/GJP0Kz9vL2qEDbIGQC/Dv6O75KPFZ/E06DYLcycLhNZYxudwVP9rJAhFEEMgefpY40v1+B6sqqogrGnZhfwITaqpU0FKTbHSlHUymlD6Cn4lb0yLMISG6MZRQrP5B67UkGexlpxPQTHsXcLy0vTEzMZkvdxbv4YtawNvmgeQEgD1jqIB45pOngrwp3jcs9D9Ib2hCwpOoqkwOV/YaA+XO+dkPo8BxOw5DH/jWRcksb3N65YEmlvQ==:::

Now although the above produces a very similar output but it is not the right one. Why? Because when the output of the java code above is sent to the backend, I receive a HTTP 200 OK and the expected response.

However, when the output of the python code above is sent similarly to the backend, I receive a 500 internal server error, meaning (as per my assumption, given that all the other params, headers etc. remain exactly the same between the java and the python HTTP requests) the input to the backend was not correct and hence it broke (again please ignore the 500, I agree it should be something more meaningful and definitely not a 500)

I do not have access to the backend. It is more of a red team - blue team exercise we are doing

Also, I could possibly invoke the java code above from python and still manage to achieve the end result and get the work done, but that'd be more of a hack, which would although be sufficient, but I am more interested in knowing how exactly can I achieve the same with Python alone.

As per some suggestions in the comments below I tried this as well: So I tried this as well:

from Crypto.Cipher import PKCS1_v1_5

def encryptMsg(secret):
    message = secret
    key = RSA.importKey(open('myPubkey.pem').read())
    cipher = PKCS1_v1_5.new(key)
    ciphertext = b64encode(cipher.encrypt(message))
    return ciphertext

and then in the while loop, this:

localStringBuilder1 = localStringBuilder1 + encryptMsg(str(localObject)) + ':::'

Still doesn't seem to work. Same results as before.


Solution

  • Thanks to https://stackoverflow.com/users/1816580/artjom-b for pointing me in the right direction in the comments above. Ok. What works is this :

    from Crypto.PublicKey import RSA
    from base64 import b64decode
    from base64 import b64encode
    from Crypto.Cipher import PKCS1_v1_5
    
    def encryptMsg(key, secret):
        message = secret
        cipher = PKCS1_v1_5.new(key)
        ciphertext = b64encode(cipher.encrypt(message))
        return ciphertext
    
    from Crypto.PublicKey import RSA
    from base64 import b64decode
    from base64 import b64encode
    from Crypto.Cipher import PKCS1_v1_5
    import requests
    
    
    # def ecnryptorFun(key, secret):
    #   encrypted = key.encrypt(secret, 1)
    #   final_text = b64encode(encrypted[0])
    #   return final_text
    
    def encryptMsg(key, secret):
        message = secret
        cipher = PKCS1_v1_5.new(key)
        ciphertext = b64encode(cipher.encrypt(message))
        return ciphertext
    
    def sayHello(body):
        url = 'https://consumer-app-development.appspot.com/api/sayHello'
        res = requests.post(url=url, data=body)
        return res.text
    
    # this is basically the keyString value itself
    key64 = b'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA76y3+1w4Ld9Q4WvHQkCkg6qjwq2wWOYMV9nAthX6ugatNlShRb2gBmyqvh7tOYHhjAhkG9Z33jCVinPuhgb0ioa5/sFAgP5LDdo5SBk4b4n/wRUbdMhfFFcTT0As2OsmdBc2iONUaG4g3WjgRODxy6LLahms6YgTnG+AqeDo8LpXxsiFXeiqGUyKQU1l16BPc2xyG+tDitFbKHx9pDL12e/w5b4G4Zg4yJgbNlZrGc3Udz5EbDREnAwirjAA3F6x2DF3j746vETb1g2y6+P5sS4lvG3XmaB1JBlhNh5qpqADRqmEMWeiYhrRcK9KjS1URSUizGPo96d8R82DmXvYKQIDAQAB'
    
    keyDER = b64decode(key64)
    keyPub = RSA.importKey(keyDER)
    
    secret = b"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApzQvzc+chU92SSh2eukYycdTJArCjL4+AqW8a2lKZ2jb5g04q6FGSRJgNkuggXt7U5ys5pb+J0699vY9rzgz+WmH6W/ZRZ2hAf3rtWaC1YYetD1SfmD2OGItGfkFYuppjjjKXEnTDzCBQT5IL7hdlnlCfpDkcPmJWvKJU+5gJek9RanVQYXLWgtOIVrQ7LJhQEFDMuYSw+rz7+paBxNqXeHTvDk/ylGtHjb3xOvbVg3DfL2z76YYX69Ae3Cd1rlqaY0IT01k3oeqNZg3638Ti8l+6ytwChRhtOHZh5XCaW6Cfbz2nezgYgY1qTAKK05o8Of+W/dErUt4166qnjBl+wIDAQAB"    
    arrayOfByte = bytearray(secret)
    
    i = 0 
    localStringBuilder1 = ""
    while i < len(arrayOfByte):  
      if len(arrayOfByte) > (i+200):
        localObject = arrayOfByte[i:i+200]
      else:
        localObject = arrayOfByte[i:len(arrayOfByte)+1]
      localObj_byte_array = bytearray(localObject)
      localStringBuilder1 = localStringBuilder1 + encryptMsg(keyPub, str(localObject)) + ':::'
      i += 200;
    
    print localStringBuilder1
    

    And now the for the string I get the backend responds with 200 OK