Java 使用rsa密钥解密字符串

Java 使用rsa密钥解密字符串,java,android,security,encryption,bouncycastle,Java,Android,Security,Encryption,Bouncycastle,我已经使用RSA公钥对一个简单的json数据进行了编码,现在我正在尝试对其进行解码。编码部分通过终端完成,解码以编程方式执行。为了验证加密文件的完整性,我通过终端对其进行了解密,效果很好。现在我正试图以编程方式解密文件,我遇到了解密问题。我可以完美地读取private_key.pem文件,并将其传递给Cipher对编码文件进行解密,但是在执行此操作后,我得到以下异常 java.lang.ArrayIndexOutOfBoundsException: too much data for RSA b

我已经使用RSA公钥对一个简单的json数据进行了编码,现在我正在尝试对其进行解码。编码部分通过终端完成,解码以编程方式执行。为了验证加密文件的完整性,我通过终端对其进行了解密,效果很好。现在我正试图以编程方式解密文件,我遇到了解密问题。我可以完美地读取private_key.pem文件,并将其传递给Cipher对编码文件进行解密,但是在执行此操作后,我得到以下异常

java.lang.ArrayIndexOutOfBoundsException: too much data for RSA block
 at com.android.org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.engineDoFinal(CipherSpi.java:457)
 at javax.crypto.Cipher.doFinal(Cipher.java:1204)
 at com.benchmark.openssl.RSADecryption.decipherString(RSADecryption.java:295)
 at com.benchmark.openssl.RSADecryption.main(RSADecryption.java:263)
 at com.benchmark.MainActivity$1.onComplete(MainActivity.java:157)
 at io.reactivex.internal.operators.completable.CompletableObserveOn$ObserveOnCompletableObserver.run(CompletableObserveOn.java:90)
 at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:463)
 at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
 at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
 at java.util.concurrent.FutureTask.run(FutureTask.java:237)
 at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
 at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
 at java.lang.Thread.run(Thread.java:841)
使用的OpenSSL命令:

openssl genrsa -out priv_key.pem 2048  
openssl rsa -pubout -in priv_key.pem -out pub_key.pem 
openssl rsautl -encrypt -in userdata.json -out user_encrypted_with_pub_key -inkey pub_key.pem –pubin
openssl rsautl -decrypt -in user_encrypted_with_pub_key -inkey priv_key.pem --> This is what I'm trying to do programmatically.
import org.spongycastle.util.io.pem.PemObject;
import org.spongycastle.util.io.pem.PemReader;
import android.util.Base64;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
public static void main(String privateKeyPath, String encodedFilePath) throws FileNotFoundException,
            IOException, NoSuchAlgorithmException, NoSuchProviderException {
        Security.addProvider(new BouncyCastleProvider());

        String encodedString = readFileAsString(encodedStringPath);
        Timber.v("Encoded String: %s", encodedString);

        KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
        try {
            PrivateKey priv = generatePrivateKey(factory, privateKeyPath);
            Timber.i(String.format("Instantiated private key: %s", priv));
            decipherString(priv, encodedString);
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
    }

    private static PrivateKey generatePrivateKey(KeyFactory factory,
                                                 String filename) throws InvalidKeySpecException,
            FileNotFoundException, IOException {
        PemFile pemFile = new PemFile(filename, false);
        byte[] content = pemFile.getPemObject().getContent();
        PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);
        return factory.generatePrivate(privKeySpec);
    }

    private static void decipherString(PrivateKey privateKey, String encodedStringData) {
        byte[] dectyptedText = null;
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            dectyptedText = cipher.doFinal(encodedStringData.getBytes()); <---- EXCEPTION HERE
            Timber.w("Deciphered text is: %s", new String(dectyptedText));
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
    static class PemFile {

        private PemObject pemObject;

        public PemFile(String filename, boolean isBase64) throws FileNotFoundException, IOException {
            PemReader pemReader = new PemReader(new InputStreamReader(new FileInputStream(filename)));
            try {
                this.pemObject = pemReader.readPemObject();
            } 
            catch (Exception e) {
                e.printStackTrace();
            }
            finally {
                pemReader.close();
            }
        }

        public PemObject getPemObject() {
            return pemObject;
        }
    }
{
    "username":"umer",
    "password":"123456",
    "pin" : "123"
}
EncryptedBase64EncodedString -> (convert from base64 to normal string [Use Default parameters only! No Padding or other constants for decoding base64 string]) -> Pass private_key & decoded string to Cipher -> Profit.
代码:

openssl genrsa -out priv_key.pem 2048  
openssl rsa -pubout -in priv_key.pem -out pub_key.pem 
openssl rsautl -encrypt -in userdata.json -out user_encrypted_with_pub_key -inkey pub_key.pem –pubin
openssl rsautl -decrypt -in user_encrypted_with_pub_key -inkey priv_key.pem --> This is what I'm trying to do programmatically.
import org.spongycastle.util.io.pem.PemObject;
import org.spongycastle.util.io.pem.PemReader;
import android.util.Base64;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
public static void main(String privateKeyPath, String encodedFilePath) throws FileNotFoundException,
            IOException, NoSuchAlgorithmException, NoSuchProviderException {
        Security.addProvider(new BouncyCastleProvider());

        String encodedString = readFileAsString(encodedStringPath);
        Timber.v("Encoded String: %s", encodedString);

        KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
        try {
            PrivateKey priv = generatePrivateKey(factory, privateKeyPath);
            Timber.i(String.format("Instantiated private key: %s", priv));
            decipherString(priv, encodedString);
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
    }

    private static PrivateKey generatePrivateKey(KeyFactory factory,
                                                 String filename) throws InvalidKeySpecException,
            FileNotFoundException, IOException {
        PemFile pemFile = new PemFile(filename, false);
        byte[] content = pemFile.getPemObject().getContent();
        PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);
        return factory.generatePrivate(privKeySpec);
    }

    private static void decipherString(PrivateKey privateKey, String encodedStringData) {
        byte[] dectyptedText = null;
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            dectyptedText = cipher.doFinal(encodedStringData.getBytes()); <---- EXCEPTION HERE
            Timber.w("Deciphered text is: %s", new String(dectyptedText));
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
    static class PemFile {

        private PemObject pemObject;

        public PemFile(String filename, boolean isBase64) throws FileNotFoundException, IOException {
            PemReader pemReader = new PemReader(new InputStreamReader(new FileInputStream(filename)));
            try {
                this.pemObject = pemReader.readPemObject();
            } 
            catch (Exception e) {
                e.printStackTrace();
            }
            finally {
                pemReader.close();
            }
        }

        public PemObject getPemObject() {
            return pemObject;
        }
    }
{
    "username":"umer",
    "password":"123456",
    "pin" : "123"
}
EncryptedBase64EncodedString -> (convert from base64 to normal string [Use Default parameters only! No Padding or other constants for decoding base64 string]) -> Pass private_key & decoded string to Cipher -> Profit.

由于我对openssl没有太多的了解,我通过一些尝试和错误找到了答案。无论如何,解密加密文件的过程应该如下所示

终端:

String -> (Encrypt) -> Encrypted String -> (convert to base64) -> EncryptedBase64EncodedString -> (Decrypt) -> Original String
编程方式:

openssl genrsa -out priv_key.pem 2048  
openssl rsa -pubout -in priv_key.pem -out pub_key.pem 
openssl rsautl -encrypt -in userdata.json -out user_encrypted_with_pub_key -inkey pub_key.pem –pubin
openssl rsautl -decrypt -in user_encrypted_with_pub_key -inkey priv_key.pem --> This is what I'm trying to do programmatically.
import org.spongycastle.util.io.pem.PemObject;
import org.spongycastle.util.io.pem.PemReader;
import android.util.Base64;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
public static void main(String privateKeyPath, String encodedFilePath) throws FileNotFoundException,
            IOException, NoSuchAlgorithmException, NoSuchProviderException {
        Security.addProvider(new BouncyCastleProvider());

        String encodedString = readFileAsString(encodedStringPath);
        Timber.v("Encoded String: %s", encodedString);

        KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
        try {
            PrivateKey priv = generatePrivateKey(factory, privateKeyPath);
            Timber.i(String.format("Instantiated private key: %s", priv));
            decipherString(priv, encodedString);
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
    }

    private static PrivateKey generatePrivateKey(KeyFactory factory,
                                                 String filename) throws InvalidKeySpecException,
            FileNotFoundException, IOException {
        PemFile pemFile = new PemFile(filename, false);
        byte[] content = pemFile.getPemObject().getContent();
        PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);
        return factory.generatePrivate(privKeySpec);
    }

    private static void decipherString(PrivateKey privateKey, String encodedStringData) {
        byte[] dectyptedText = null;
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            dectyptedText = cipher.doFinal(encodedStringData.getBytes()); <---- EXCEPTION HERE
            Timber.w("Deciphered text is: %s", new String(dectyptedText));
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
    static class PemFile {

        private PemObject pemObject;

        public PemFile(String filename, boolean isBase64) throws FileNotFoundException, IOException {
            PemReader pemReader = new PemReader(new InputStreamReader(new FileInputStream(filename)));
            try {
                this.pemObject = pemReader.readPemObject();
            } 
            catch (Exception e) {
                e.printStackTrace();
            }
            finally {
                pemReader.close();
            }
        }

        public PemObject getPemObject() {
            return pemObject;
        }
    }
{
    "username":"umer",
    "password":"123456",
    "pin" : "123"
}
EncryptedBase64EncodedString -> (convert from base64 to normal string [Use Default parameters only! No Padding or other constants for decoding base64 string]) -> Pass private_key & decoded string to Cipher -> Profit.
结果代码为:

import org.spongycastle.util.io.pem.PemObject;
import org.spongycastle.util.io.pem.PemReader;

import android.util.Base64;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

public static void main(String privateKeyPath, String publicKeyPath, String encodedStringPath, boolean isPublicKeyAndDataBase64) throws FileNotFoundException,
            IOException, NoSuchAlgorithmException, NoSuchProviderException {
        Security.addProvider(new BouncyCastleProvider());

        String encodedString = readFileAsString(encodedStringPath);
        if(isPublicKeyAndDataBase64) {
            KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
            Timber.w("Encoded String converted from base64: %s", decodeBase64ToBytesa(encodedString));
            try {
                PrivateKey priv = generatePrivateKey(factory, privateKeyPath);
                Timber.i(String.format("Instantiated private key: %s", priv));
                decipherString(priv, decodeBase64ToBytesa(encodedString));
            } catch (InvalidKeySpecException e) {
                e.printStackTrace();
            }
            return;
        }
        else
            Timber.w("Encoded String: %s", encodedString);

        KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
        try {
            PrivateKey priv = generatePrivateKey(factory, privateKeyPath);
            Timber.i(String.format("Instantiated private key: %s", priv));
            decipherString(priv, encodedString.getBytes());
            PublicKey pub = generatePublicKey(factory, publicKeyPath);
            Timber.i(String.format("Instantiated public key: %s", pub));
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
    }

    private static PrivateKey generatePrivateKey(KeyFactory factory,
                                                 String filename) throws InvalidKeySpecException,
            FileNotFoundException, IOException {
        PemFile pemFile = new PemFile(filename, false);
        byte[] content = pemFile.getPemObject().getContent();
        PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);
        return factory.generatePrivate(privKeySpec);
    }

    private static PublicKey generatePublicKey(KeyFactory factory,
                                               String filename) throws InvalidKeySpecException,
            FileNotFoundException, IOException {
        PemFile pemFile = new PemFile(filename, false);
        byte[] content = pemFile.getPemObject().getContent();
        X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(content);
        return factory.generatePublic(pubKeySpec);
    }

    private static void decipherString(PrivateKey privateKey, byte[] encodedStringData) {
        byte[] dectyptedText = null;
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            dectyptedText = cipher.doFinal(encodedStringData);
            Timber.w("Deciphered text is: %s", new String(dectyptedText));
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
    static class PemFile {

        private PemObject pemObject;

        public PemFile(String filename, boolean isBase64) throws FileNotFoundException, IOException {
            PemReader pemReader = null;

            if(isBase64) {
                Timber.i("reading base64 encoded pem file. base64DecodedString: %s", decodeBase64(filename));
                pemReader = new PemReader(new StringReader(decodeBase64(filename)));
            }
            else
                pemReader = new PemReader(new InputStreamReader(
                        new FileInputStream(filename)));
            try {
                this.pemObject = pemReader.readPemObject();
            }
            catch (Exception e) {
                e.printStackTrace();
            }finally {
                pemReader.close();
            }
        }

        public PemObject getPemObject() {
            return pemObject;
        }
    }

encodedStringData.getBytes()
肯定是错误的。希望
encodedStringData
使用与文本编码类似的Base64或som二进制编码。然后你必须先对它进行解码,然后再将其传递给密码。否则,
字符串
是保存加密数据的错误类型。另请参阅,,@jww谢谢您的建议。已更新question@Amit-谢谢你,伙计。