openssl -decrypt por Java

¡todas! Estoy tratando de resolver el problema.

Tengo bat-file con comando:

openssl smime -decrypt -binary -inform DER -recip [path to certificate] -inkey  [path to private key] <[path to encoded file] >[path to decoded file]

Lo he implementado en Java.

Entonces necesito decodificar el archivo con la clave privada RSA.

Primero, intenté de esta manera:

package javatest;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.security.PrivateKey;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;

/**
 * Test decrypt
 *
 * @author a.chernyy
 */
public class JavaTest {

    /**
     * String to hold name of the encryption algorithm.
     */
    public static final String ALGORITHM = "RSA";

    /**
     * String to hold the path to the keys' dir.
     */
    public static final String KEYS_DIR = "D:" + File.separator + File.separator + "keystore" + File.separator;

    /**
     * String to hold the name of the private key file.
     */
    public static final String PRIVATE_KEY_FILE = KEYS_DIR + "priv.key";

    /**
     * String to hold name of the public key file.
     */
    public static final String CERT_FILE = KEYS_DIR + "cert.cer";

    /**
     * String to hold name of the encrypted file.
     */
    public static final String ENCRYPTED_FILE = "D:" + File.separator + "Temp" + File.separator + "encrypded.xml";

    /**
     * String to hold name of the decrypted file.
     */
    public static final String DECRYPTED_FILE = "D:" + File.separator + "Temp" + File.separator + "decrypted.xml";

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        try {
            //get private key
            File keyFl = new File(PRIVATE_KEY_FILE);
            Security.addProvider(new BouncyCastleProvider());
            PEMParser pemParser = new PEMParser(new InputStreamReader(new FileInputStream(keyFl)));
            PEMKeyPair pemKeyPair = (PEMKeyPair) pemParser.readObject();
            JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
            PrivateKey key = converter.getPrivateKey(pemKeyPair.getPrivateKeyInfo());

            //decrypt file           
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, key);
            InputStream is = new FileInputStream(ENCRYPTED_FILE);
            OutputStream out = new FileOutputStream(DECRYPTED_FILE);
            CipherInputStream cis = new CipherInputStream(is, cipher);
            byte[] buffer = new byte[1024];
            int r;
            while ((r = cis.read(buffer)) > 0) {
                out.write(buffer, 0, r);
            }
            cis.close();
            is.close();
            out.close();
        } catch (Exception e) {
            System.out.println("It's a pity...");
            System.err.println(e.getMessage());
        }

        System.out.println("THE END");
    }

}

Pero me sale un error:

javax.crypto.IllegalBlockSizeException: los datos no deben tener más de 128 bytes

También probé usaresta solución. Lo implementé de esa manera:

package javatest;

//some imports...

/**
 * Test decrypt main class
 *
 * @author a.chernyy
 */
public class JavaTest {

    /**
     * String to hold name of the encryption algorithm.
     */
    public static final String ALGORITHM = "RSA";

    /**
     * String to hold the path to the keys' dir.
     */
    public static final String KEYS_DIR = "D:" + File.separator + File.separator + "keystore" + File.separator;

    /**
     * String to hold the name of the private key file.
     */
    public static final String PRIVATE_KEY_FILE = KEYS_DIR + "priv.key";

    /**
     * String to hold name of the public key file.
     */
    public static final String CERT_FILE = KEYS_DIR + "cert.cer";

    /**
     * String to hold name of the encrypted fi,le.
     */
    public static final String ENCRYPTED_FILE = "D:" + File.separator + "Temp" + File.separator + "encrypded.xml";

    /**
     * String to hold name of the decrypted file.
     */
    public static final String DECRYPTED_FILE = "D:" + File.separator + "Temp" + File.separator + "decrypted.xml";

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        try {
            RSA rsa = RSA.getInstance(PRIVATE_KEY_FILE);
            rsa.decrypt(ENCRYPTED_FILE, DECRYPTED_FILE);
        } catch (Exception e) {
            System.out.println("It's a pity...");
            System.err.println(e.getMessage());
        }

        System.out.println("THE END");
    }

}

Y:

package javatest;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Security;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;

/**
 * Decrypt class
 *
 * @link http://coding.westreicher.org/?p=23
 * @author a.chernyy
 */
public class RSA {

    /**
     * Singleton class object RSA
     */
    private static volatile RSA instance;

    /**
     * Private key
     */
    private final PrivateKey privateKey;

    /**
     * Cipher
     */
    private final Cipher cipher;

    /**
     * Constructor
     *
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     */
    private RSA(String privateKeyPath) throws NoSuchAlgorithmException, NoSuchPaddingException, FileNotFoundException, IOException {
        //create cipher
        this.cipher = Cipher.getInstance("RSA");

        //get private key
        File keyFl = new File(privateKeyPath);
        Security.addProvider(new BouncyCastleProvider());
        PEMParser pemParser = new PEMParser(new InputStreamReader(new FileInputStream(keyFl)));
        PEMKeyPair pemKeyPair = (PEMKeyPair) pemParser.readObject();
        JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
        this.privateKey = converter.getPrivateKey(pemKeyPair.getPrivateKeyInfo());
    }

    //Static methods
    /**
     * Static method getInstance return single refer on object RSA. If object
     * not exists, it will be created
     *
     * @param privateKeyPath
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws java.io.FileNotFoundException
     * @return RSA
     */
    public static RSA getInstance(String privateKeyPath) throws NoSuchAlgorithmException, NoSuchPaddingException, FileNotFoundException, IOException {
        if (instance == null) {
            synchronized (RSA.class) {
                if (instance == null) {
                    instance = new RSA(privateKeyPath);
                }
            }
        }
        return instance;
    }

    /**
     * Block chipher
     *
     * @param bytes
     * @param mode
     * @return
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     */
    private byte[] blockCipher(byte[] bytes, int mode) throws IllegalBlockSizeException, BadPaddingException {
        // string initialize 2 buffers.
        // scrambled will hold intermediate results
        byte[] scrambled = new byte[0];

        // toReturn will hold the total result
        byte[] toReturn = new byte[0];
        // if we encrypt we use 100 byte long blocks. Decryption requires 128 byte long blocks (because of RSA)
        int length = (mode == Cipher.ENCRYPT_MODE) ? 100 : 128;

        // another buffer. this one will hold the bytes that have to be modified in this step
        byte[] buffer = new byte[length];

        for (int i = 0; i < bytes.length; i++) {

            // if we filled our buffer array we have our block ready for de- or encryption
            if ((i > 0) && (i % length == 0)) {
                //execute the operation
                scrambled = cipher.doFinal(buffer);
                // add the result to our total result.
                toReturn = append(toReturn, scrambled);
                // here we calculate the length of the next buffer required
                int newlength = length;

                // if newlength would be longer than remaining bytes in the bytes array we shorten it.
                if (i + length > bytes.length) {
                    newlength = bytes.length - i;
                }
                // clean the buffer array
                buffer = new byte[newlength];
            }
            // copy byte into our buffer.
            buffer[i % length] = bytes[i];
        }

        // this step is needed if we had a trailing buffer. should only happen when encrypting.
        // example: we encrypt 110 bytes. 100 bytes per run means we "forgot" the last 10 bytes. they are in the buffer array
        scrambled = cipher.doFinal(buffer);

        // final step before we can return the modified data.
        toReturn = append(toReturn, scrambled);

        return toReturn;
    }

    /**
     * Concatinate bytes
     *
     * @param prefix
     * @param suffix
     * @return
     */
    private byte[] append(byte[] prefix, byte[] suffix) {
        byte[] toReturn = new byte[prefix.length + suffix.length];
        for (int i = 0; i < prefix.length; i++) {
            toReturn[i] = prefix[i];
        }
        for (int i = 0; i < suffix.length; i++) {
            toReturn[i + prefix.length] = suffix[i];
        }
        return toReturn;
    }

    public void decrypt(String filePath, String fileDecryptPath) throws Exception {
        //Convert file into bytes
        this.cipher.init(Cipher.DECRYPT_MODE, this.privateKey);
        File encryptedFile = new File(filePath);
        FileInputStream isEncryptedFile = new FileInputStream(encryptedFile);
        byte encryptedFileData[] = new byte[(int) encryptedFile.length()];
        isEncryptedFile.read(encryptedFileData);
        byte[] bts = encryptedFileData;

        //decrypt
        byte[] decrypted = blockCipher(bts, Cipher.DECRYPT_MODE);

        //Push decrypted data into file
        //...
    }
}

Pero recibí el error:

error de descifrado

¿Puede alguien sugerir una solución?

Respuestas a la pregunta(2)

Su respuesta a la pregunta