![](/img/trans.png)
[英]JAVA RSA Decryption not working, throws InvalidKeySpecException
[英]Why is this Java RSA decryption not working?
因此,這是我根據http://www.loyalty.org/~schoen/rsa/上的挑戰進行的工作的一部分(盡管我已經不得不解決)。
總而言之,質詢提供了一個包含密碼和相關公鑰的文件列表。 利用RSA公鑰通常重復質數這一事實,我們有望從100個私鑰中找到盡可能多的私鑰並解密關聯的消息。 盡管我認為形成私鑰很簡單(並且相信我做得正確),但是卻收到錯誤消息“ javax.crypto.BadPaddingException:消息大於模數”。 有人可以告訴我我在做什么錯嗎? 我將我的代碼以及2個bin和cipher文件作為示例。
我的代碼:
package decryptrsa;
import com.sun.org.apache.xml.internal.security.utils.Base64;
import java.io.File;
import java.util.Scanner;
import java.security.spec.X509EncodedKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.KeyFactory;
import java.security.interfaces.*;
import java.math.BigInteger;
import java.util.ArrayList;
import javax.crypto.Cipher;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
*
* @author qscot
*/
public class DecryptRSA {
static ArrayList<BigInteger> publicKeys = new ArrayList<BigInteger>();
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws Exception {
// TODO code application logic here
ReadPublicKeys();
crackPrivateKeys();
}
static void ReadPublicKeys() throws Exception {
String publicKey;
for (int i = 1; i <= 100; i++) {
publicKey = "";
Scanner scanner = new Scanner(new File("C:\\Users\\qscot\\Downloads\\challenge\\" + i + ".pem"));
scanner.nextLine();
String lineString = scanner.nextLine();
do {
publicKey += lineString;
lineString = scanner.nextLine();
} while (lineString.contains("END PUBLIC KEY") == false);
scanner.close();
byte[] decoded = Base64.decode(publicKey.getBytes());
X509EncodedKeySpec spec = new X509EncodedKeySpec(decoded);
KeyFactory kf = KeyFactory.getInstance("RSA");
RSAPublicKey pk = (RSAPublicKey) kf.generatePublic(spec);
BigInteger modulus = pk.getModulus();
publicKeys.add(modulus);
}
}
static void crackPrivateKeys() throws Exception {
BigInteger gcd;
BigInteger q1;
BigInteger q2;
for (int i = 0; i < 100; i++) {
for (int z = 0; z < 100; z++) {
if (i != z) {
gcd = (gcd(publicKeys.get(i), publicKeys.get(z)));
if (!gcd.equals(BigInteger.ONE)) {
q1 = publicKeys.get(i).divide(gcd);
q2 = publicKeys.get(z).divide(gcd);
RSAPrivateKey key1 = getKey(gcd, q1);
RSAPrivateKey key2 = getKey(gcd, q2);
writeDecryptedFile(i, key1);
writeDecryptedFile(z, key2);
}
}
}
}
}
static void writeDecryptedFile(int fileNo, RSAPrivateKey privKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");
File file = new File("C:\\Users\\qscot\\Downloads\\challenge\\" + fileNo + ".bin");
FileInputStream fis = new FileInputStream(file);
byte[] fbytes = new byte[(int) file.length()];
fis.read(fbytes);
fis.close();
cipher.init(Cipher.DECRYPT_MODE, privKey);
byte[] oBytes = cipher.doFinal(fbytes);
FileOutputStream fos = new FileOutputStream("C:\\Users\\qscot\\Downloads\\challenge\\" + fileNo + "-OUTPUT.txt");
fos.write(oBytes);
fos.flush();
fos.close();
}
static BigInteger gcd(BigInteger num1, BigInteger num2) {
while (!num1.equals(BigInteger.ONE) && !num1.equals(BigInteger.ZERO) && !num2.equals(BigInteger.ONE) && !num2.equals(BigInteger.ZERO)) {
if (num1.compareTo(num2) == 1) {
num1 = num1.mod(num2);
} else {
num2 = num2.mod(num1);
}
}
if (num1.equals(BigInteger.ONE) || num2.equals(BigInteger.ONE)) {
return BigInteger.valueOf(1);
} else {
if (num1.equals(BigInteger.ZERO)) {
return num2;
} else {
return num1;
}
}
}
static RSAPrivateKey getKey(BigInteger p, BigInteger q) throws Exception {
KeyFactory kf = KeyFactory.getInstance("RSA");
BigInteger t, d, e;
e = BigInteger.valueOf(65537);
t = (p.subtract(BigInteger.ONE)).multiply((q.subtract(BigInteger.ONE)));
d = e.modInverse(t);
RSAPrivateKeySpec keyspec = new RSAPrivateKeySpec(d, e);
return (RSAPrivateKey) kf.generatePrivate(keyspec);
}
}
6.pem文件:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDn5BqEUDrlhvwXQ68MqZ001B74
fGD1w2Le++wILzEX7Ba8LeJVeuwpOxxdxDQ7280yc0SKPiChWpb3bE1/G/hV5e++
95qfhbe+SP7MRL39TxEotADaqyHY6SfloDk5A9NiIzgebWmtFriamBfhrxzx8G3K
6NWAAjDAIMx+xjLn6QIDAQAB
-----END PUBLIC KEY-----
6.bin文件:
xƒâTD§¼çÄ ØˆßPã…Ôä3x4b2Ð#•—æ¨
U«õ`Êzÿúw"Ü°™è0ÄÕ~³•—˜§FºqŠ„hÏŒÞõ&د³Ô<*pàbGÃGìMÿö¶3Ùù¸²Z•a¯®éDNïæÝjn¢¯tå!WÐ
6-OUTPUT.txt:
8.pem文件:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1fGe+mMJYZ+BDm76Ag25bXcBB
pABkGZpnQpnSTocEuCQyp5/lNNVFdF0QliNRULnxoK+pD8VEBqxR+zkYsYf9iGzU
PzOELWvbFgIJdUPixlaD3/1Y6+eSDffCOsCoJ1A/8DELMbjQdbFoxfqj9AVRU3cd
R0AauL4O9hPz0N9OVQIDAQAB
-----END PUBLIC KEY-----
8.bin文件:
¤”»BÃ."
îÂT.<(bø×]¥”£Ó¯!›==±Ñ·;ª%7¿ðU@xÀÉ5ç£
‡*h\w¸¸@¦aܳj Ù~t´õêæSü®Î ŒQU¼L-â-äK}\-žù‹ý«>DÕ£ñ”Õe6Œ"
G®lI
行RSAPrivateKeySpec keyspec = new RSAPrivateKeySpec(d, e);
包含一個錯誤。 RSAPrivateKeySpec
的參數應按順序為模數和解密指數。 根據您所提供使用的填充鏈接的文檔PKCS1PADDING。 因此,您應該使用Cipher.getInstance("RSA/ECB/PKCS1PADDING");
獲得一個Cipher實例Cipher.getInstance("RSA/ECB/PKCS1PADDING");
也有關閉的情況-1的錯誤在你writeDecryptedFile
方法。 這些文件名為1.bin
... 100.bin
,但是您的密鑰的索引是從0到99。因此,您需要訪問(fileNo + 1) + ".bin"
而不是fileNo + ".bin"
由於RSAPublicKey中提供了此信息,因此沒有理由假定加密指數始終為65537。 另外,請勿使用您正在使用的Base64編解碼器,而應使用java.util.Base64
的一種。
您從密碼中的字節讀取方法*.bin
文件是不可靠的,因為它假設一個讀總是返回請求的字節數。 它可能會在當前的實現中以這種方式解決,但是javadocs無法保證。 您應該研究非常簡單的Files.readAllBytes()
方法以及用於讀取小文件的相關方法 。 它們極大地簡化了您的代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.