1
votes

I make encryption on python and try to decrypt it on Java, but always get decryption error

I have part of code for encrypt and decrypt message in JAVA encoded in RSA For decrypt:

import java.security.*;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import javax.crypto.Cipher;

public class Decrypter
{
    public static void main(String[] args)
    {

        try {
            String encoded_data = "PueF1RC5giqmUK9U+X80SwjAjGmgfcHybjjQvWdqHSlua1rv6xr7o6OMutHBU+NRuyCJ3etTQssYOMGiWPITbEC8xr3WG9H9oRRnvel4fYARvQCqsGmf9vO9rXcaczuRKc2zy6jbutt59pKoVKNrbonIBiGN1fx+SaStBPe9Jx+aZE2hymDsa+xdmBSCyjF30R2Ljdt6LrFOiJKaDiYeF/gaej1b7D8G6p0/HBPxiHMWZhx1ZfylSvZ6+zyP0w+MJn55txR2Cln99crGtcdGeBDyBtpm3HV+u0VlW7RhgW5b+DQwjQ/liO+Ib0/ZIPP9M+3sipIwn2DKbC45o0FZHQ==";
            byte[] decodeData = Base64.getDecoder().decode(encoded_data);

            String publicKeyString = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxzN2+mrQRXKshq3k0r06" +
                    "0/FoWafOCl6fCCyuu/7SejNU95SN2LZyopA3ipamY5MeK1G1XHOhEfkPWcYcgUbz" +
                    "TdD166nqJGi/O+rNK9VYgfhhqD+58BCmLlNidYpV2iDmUZ9B/cvVsQi96GY5XOaK" +
                    "xuVZfwrDK00xcOq+aCojQEvMh+gry05uvzfSv9xK3ki5/iCMY62ReWlmrY0B19CQ" +
                    "47FuulmJmrxi0rv2jpKdVsMq1TrOsWDGvDgZ8ieOphOrqZjK0gvN3ktsv63kc/kP" +
                    "ak78lD9opNmnVKY7zMN1SdnZmloEOcDB+/W2d56+PbfeUhAHBNjgGq2QEatmdQx3" +
                    "VwIDAQAB";
            KeyFactory kf = KeyFactory.getInstance("RSA");
            byte[] encodedPb = Base64.getDecoder().decode(publicKeyString);
            X509EncodedKeySpec keySpecPb = new X509EncodedKeySpec(encodedPb);
            PublicKey pubKey = kf.generatePublic(keySpecPb);


            Cipher cipherDecr = Cipher.getInstance("RSA");
            cipherDecr.init(Cipher.DECRYPT_MODE, pubKey);
            byte[] cipherDataDecr = cipherDecr.doFinal(decodeData);
            String result = new String(cipherDataDecr);
            System.out.println("result = "+result);
        }catch (Exception e){
            e.printStackTrace(System.out);
        }

    }
}

Unfortunately I can't make changes in this code, so all what I can is make changes in python part. This part work correctly. for check I use this code for encrypt:

import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import javax.crypto.Cipher;

public class Encrypter
{
    public static void main(String[] args)
    {
        try {   
            String data = "111111111222";
            String privateKeyString = "here is my privat key";

            byte [] encoded = Base64.getDecoder().decode(privateKeyString);
            System.out.println("encoded = "+encoded);

            java.security.Security.addProvider( new org.bouncycastle.jce.provider.BouncyCastleProvider());
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            KeySpec ks = new PKCS8EncodedKeySpec(encoded);
            RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(ks);
            System.out.println("privKey = "+privKey);

            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
            cipher.init(Cipher.ENCRYPT_MODE, privKey);

            byte[] cipherData = cipher.doFinal(data.getBytes());

            String card = Base64.getEncoder().encodeToString(cipherData);
            System.out.println("data = "+card);
        }catch (Exception e){
            e.printStackTrace(System.out);
        }

    }
}

And when I use result from Java code for encrypt and put this result to decrypt Java file - all work's great. I need same encryption part, but writing with python.

Part for encrypt with python

import base64
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5

data = '111111111222'
privat_key = 'here is my privat key'
key = RSA.importKey(privat_key)
cipher = PKCS1_v1_5.new(key)
encrypted_message = str(base64.b64encode(cipher.encrypt(base64.b64decode(data))), 'utf8')
print(encrypted_message)

So, questions is how I should encrypt message for correct decryption with on Java? I tried different libs (standard rsa, Pycrypto RSA, PKCS1_OAEP, PKCS1_v1_5) and nothing help me

P.S. I know about wrong way for use keys pair, but it is requirements of the external system

UPDATE:

Using new instance fetch me to the some result. I changed format as Maarten Bodewes said

Cipher cipherDecr = Cipher.getInstance("RSA/ECB/NoPadding");

decryption result: ����2����ٰoܬ���(�RM@�/���u*�d�{���w�b+���v�ݏ[�$�#��xJo�s��F1���X��}���1 ���������t%`�YA/��?� �ɼej�X�T�+6Y4D��!���

I can't read it, but it's not a Exception, it is good. Try to move this way

UPDATE:

I define that Java used RSA/ECB/PKCS1Padding as default. So I should use same in python

2
If you encrypt in your Python code, why do you assume that data is Base64 encoded? That's different from what you do in Java. - Artjom B.
Could you decrypt in Java using "RSA/ECB/NoPadding", and base 64 encode the result, and put that into the question? It depends on the implementation which PKCS#1 padding (for signing or encryption) is used. - Maarten Bodewes
This python script is not first. I tried different libs in different ways to make it run. You can excchange base64 encoding cipher.encrypt(base64.b64decode(data)) with cipher.encrypt(data.encode()) Unfortunately it doesn't have effect on the decryption result - Vakhrushev

2 Answers

4
votes

First of all I defined that java

Cipher cipher = Cipher.getInstance("RSA");

expanded in

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");

or

Cipher cipher = Cipher.getInstance("RSA/None/PKCS1PADDING");

For RSA no different what is defined in second argument (None or ECB). RSA doesn't use it.

So I need add padding to my encryption in python. Unfortunately PyCrypto hasn`t PKCS1PADDING, so i can't encrypt with this padding.

Next step I found M2Crypto lib https://gitlab.com/m2crypto/m2crypto This fork worked for python3. just download and build it(instruction in repo)

Than I wrote this code and it works:

import M2Crypto

# read privat key
privatKey = M2Crypto.RSA.load_key('privat.key')
# encrypt plaintext using privat key
ciphertext = privatKey.private_encrypt(data.encode('utf-8'), M2Crypto.RSA.pkcs1_padding)

encrypted_message = str(base64.b64encode(ciphertext), 'utf8')
print(encrypted_message)

That's all. It works for me, and I believe, it can help u.

0
votes

According to my code, Bouncy uses the padding for signature generation, so I presume that is what is different. You can perform a "raw" decrypt (modular exponentiation) and remove the padding yourself.