title: openssl -decrypt by Java
body: <p>all!
  I am trying to resolve the issue.</p>
  
  <p>I have bat-file with command:</p>
  
  <pre><code>openssl smime -decrypt -binary -inform DER -recip [path to certificate] -inkey  [path to private key] &lt;[path to encoded file] &gt;[path to decoded file]
  </code></pre>
  
  <p>I have implement it on Java.</p>
  
  <p>So I need decode file with RSA private key.</p>
  
  <p>First, I tried this way:</p>
  
  <pre><code>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)) &gt; 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");
      }
  
  }
  </code></pre>
  
  <p>But I get error: </p>
  
  <blockquote>
    <p>javax.crypto.IllegalBlockSizeException: Data must not be longer than
    128 bytes</p>
  </blockquote>
  
  <p>Also I tried use <a href="http://coding.westreicher.org/?p=23" rel="nofollow noreferrer">this</a> solution. I implemented it that way:</p>
  
  <pre><code>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 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 {
              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");
      }
  
  }
  </code></pre>
  
  <p>And:</p>
  
  <pre><code>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 &lt; bytes.length; i++) {
  
              // if we filled our buffer array we have our block ready for de- or encryption
              if ((i &gt; 0) &amp;&amp; (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 &gt; 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 &lt; prefix.length; i++) {
              toReturn[i] = prefix[i];
          }
          for (int i = 0; i &lt; 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
          //...
      }
  }
  </code></pre>
  
  <p>But I got the error:</p>
  
  <blockquote>
    <p>Decryption error</p>
  </blockquote>
  
  <p>Can anyone suggest a solution?</p>