Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/382.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么这个Java RSA解密不起作用?_Java_Cryptography_Rsa - Fatal编程技术网

为什么这个Java RSA解密不起作用?

为什么这个Java RSA解密不起作用?,java,cryptography,rsa,Java,Cryptography,Rsa,因此,这是我正在工作的任务的一部分(尽管我已经把它交出来了,但还没有解决),基于这个挑战 总之,质询提供了包含密码和相关公钥的文件列表。利用RSA公钥经常重复素数这一事实,我们期望从100中找到尽可能多的私钥并解密相关消息。虽然我认为形成私钥很简单(并且相信我做得很正确),但我得到了错误“javax.crypto.BadPaddingException:Message大于modules”。有人能告诉我我做错了什么吗?我以我的代码和2个bin和密码文件为例 我的代码: package decryp

因此,这是我正在工作的任务的一部分(尽管我已经把它交出来了,但还没有解决),基于这个挑战

总之,质询提供了包含密码和相关公钥的文件列表。利用RSA公钥经常重复素数这一事实,我们期望从100中找到尽可能多的私钥并解密相关消息。虽然我认为形成私钥很简单(并且相信我做得很正确),但我得到了错误“javax.crypto.BadPaddingException:Message大于modules”。有人能告诉我我做错了什么吗?我以我的代码和2个bin和密码文件为例

我的代码:

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.bin文件:

xƒâTD§¼çÄ   ؈ßPã…Ôä3x4b2Ð#•—æ¨
U«õ`Êzÿúw"Ü°™è0ÄÕ~³•—˜§FºqŠ„hÏŒÞõ&د³Ô<*pàbGÃGìMÿö¶3Ùù­¸²Z•a¯®éDNïæÝjn¢¯tå!WÐ
¤”»BÃ."
îÂT.<(bø×]¥”£Ó¯!›==±Ñ·;ª%7¿ðU@xÀÉ5ç£
‡*h\w¸¸@¦aܳj Ù~t´õêæSü®Î ŒQU¼L-â-äK}\-žù‹ý«>DÕ£ñ”Õe6Œ"
G®lI
8.bin文件:

xƒâTD§¼çÄ   ؈ßPã…Ôä3x4b2Ð#•—æ¨
U«õ`Êzÿúw"Ü°™è0ÄÕ~³•—˜§FºqŠ„hÏŒÞõ&د³Ô<*pàbGÃGìMÿö¶3Ùù­¸²Z•a¯®éDNïæÝjn¢¯tå!WÐ
¤”»BÃ."
îÂT.<(bø×]¥”£Ó¯!›==±Ñ·;ª%7¿ðU@xÀÉ5ç£
‡*h\w¸¸@¦aܳj Ù~t´õêæSü®Î ŒQU¼L-â-äK}\-žù‹ý«>DÕ£ñ”Õe6Œ"
G®lI
“BÔ
îT.DÕñ“Õe6Œ”
G®锂

RSAPrivateKeySpec keyspec=新的RSAPrivateKeySpec(d,e)包含一个bug。参数应依次为模数和解密指数。根据您提供的链接中的文档,使用的填充是PKCS1PADDING。因此,您应该使用
Cipher.getInstance(“RSA/ECB/pkcs1ppadding”)

在您的
writeDecryptedFile
方法中还有一个off-by-1错误。文件名为
1.bin
100.bin
,但您的密钥索引范围从0到99。因此,您需要访问
(fileNo+1)+“.bin”
,而不是
fileNo+”.bin”

没有理由假定加密指数始终为65537,因为此信息在RSAPublicKey中可用。另外,不要使用您正在使用的Base64编解码器,而是使用来自的编解码器


从cipher
*.bin
文件中读取字节的方法不可靠,因为它假定读取总是返回请求的字节数。在当前的实现中可能会这样,但javadocs并不能保证这一点。您应该研究读取小文件的非常简单的方法和步骤。它们大大简化了代码

到底是什么问题?您是否希望使用错误密钥解密文件时输出“不,对不起,请使用其他密钥重试”?请注意,您的文件读取方法是错误的:它跳过了文件的最后一个字节,并且不能确保所有字节都已读取。对不起,我没有看到我的文件读取方法的问题,您能更具体一点吗?如果您指的是fytes数组的大小,如果我使用file.length()而不是file.length()-1,我会得到一个错误:avax.crypto.BadPaddingException:消息大于模数
新字节[(int)file.length()-1]:因此除了最后一个字节外,您只能为所有字节留出空间:读取最多b.length字节的数据。是的,如果我使用file.length(),我会得到错误:javax.crypto.BadPaddingException:消息大于modules,这时您可能应该想知道为什么会出现这样的异常,而不是随意跳过最后一个字节。