【发布时间】:2018-02-08 09:32:15
【问题描述】:
我已经使用RSA public key 编码了一个简单的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;
}
}
userdata.json:
{
"username":"umer",
"password":"123456",
"pin" : "123"
}
【问题讨论】:
-
encodedStringData.getBytes()肯定是错误的。希望encodedStringData使用 Base64 或类似的二进制到文本编码。然后你必须在将它传递给密码之前对其进行解码。否则,String是保存加密数据的错误类型。 -
@jww 感谢您的建议。更新问题
-
@Amit - 谢谢伙计。
标签: java android security encryption bouncycastle