繁体   English   中英

解密文本文件中存储为位数组的数据时,为什么会出现“BadPaddingException:消息大于模数”?

[英]Why do I get "BadPaddingException: Message is larger than modulus" when decrypting data stored as a bit array from text file?

我使用 RSA 算法来加密一些数字,然后将这些数字存储在文本文件中的位数组中。 这些数字被加密并添加到文本文件中就好了,但是当我尝试使用下面的方法解密它们时,我在控制台中收到“BadPaddingException:消息大于模数”这个错误。 我对加密很陌生,这真的让我失望。

 Cipher cipher;
    KeyPair pair;

    public byte[] encryptData(String data) throws BadPaddingException, IllegalBlockSizeException {
        try{
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
            pair = keyPairGen.generateKeyPair();
            PublicKey publicKey = pair.getPublic();
            cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            cipher.update(data.getBytes());
            cipher.doFinal();
        }
        catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException ex){
            ex.printStackTrace();
        }
        return cipher.doFinal();
    }

将数据写入文件

 String nums = request.getParameter("numbers");
        String password = (String) session.getAttribute("password");
        String filename =  (password +".txt");



        File dir = new File("/volume");
        dir.mkdir();
        File myfile = new File(dir, filename);
        System.out.println("filename: " + filename);
        FileOutputStream output;

        try {
            if (myfile.isFile()){
                 output = new FileOutputStream(myfile, true);
            }
            else{
                 output = new FileOutputStream(myfile);
            }
            byte[] encryptednums = encryptData(nums);
            output.write(encryptednums);
            output.close();
        } catch (BadPaddingException | IllegalBlockSizeException  | IOException e) {
            e.printStackTrace();
        }

读取文件

    public byte[] bytesFileReader(File filename){
        try {
            return Files.readAllBytes(Paths.get(String.valueOf(filename)));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

解密

  HttpSession session = request.getSession();
        KeyPair pair = (KeyPair) session.getAttribute("keypair");
        Cipher cipher = (Cipher) session.getAttribute("cipher");
        String password = (String) session.getAttribute("password");

        String filename = (password +".txt");
        File dir = new File("/volume");
        dir.mkdir();
        File myfile = new File(dir, filename);

        byte[] encryptedBytes = bytesFileReader(myfile);

        try {
            cipher.init(Cipher.DECRYPT_MODE, pair.getPrivate());
            byte[] decipheredText = cipher.doFinal(encryptedBytes);
            System.out.println(new String(decipheredText, StandardCharsets.UTF_8));

        } catch (InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
            e.printStackTrace();
        }

    }

可能值得注意的是,这一切都发生在两个 java servlet 上。

您的代码中有一个主要问题和一些小问题。 让我们开始一个次要的:当将字符串转换为字节数组时,反之亦然,所有转换都必须使用固定编码(请参阅您的 encryptData 方法):

cipher.update(data.getBytes());

主要问题是进行 RSA 加密时的明文大小限制。 您可以使用此公式计算最大明文大小

1) RSA keysize divided by 8 - e.g. 2048 / 8 = 256 bytes
2) PKCS1 padding takes 11 bytes
3) maximum of plaintext bytes: 256 - 11 = 245 bytes

在我的示例代码中,我使用了大小为 ( UNSECURE ) 512 位 = 64 字节的 RSA 密钥对,减去 11 个字节用于填充,有 53 个字节可以加密。 第一轮将按预期运行,下一个 54 字节数据的加密运行到

IllegalBlockSizeException: Data must not be longer than 53 bytes

由于您的代码只有方法但没有显示写入的数据,我只能假设您尝试在一次运行中解密所有写入的数据 - 失败的可能性很高。

我的代码遇到错误的原因(而不是你的)是更新和双重(!)最终调用(注意我遗漏了你可能需要的捕获):

change:
cipher.update(data.getBytes());
cipher.doFinal();
return cipher.doFinal();
to:
return cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));

输出:

BadPaddingException: Message is larger than modulus
encrypting 12345678901234567890123456789012345678901234567890123
encryptedData length: 64
decryptedData: 12345678901234567890123456789012345678901234567890123
encrypting 123456789012345678901234567890123456789012345678901234
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Data must not be longer than 53 bytes

安全警告:此代码使用不安全的 512 位长 RSA 密钥(使用最少 2048 位)并使用易受攻击的 RSA 填充 PKCS1 进行加密 - 请使用 OEAP 填充! .

代码:

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.nio.charset.StandardCharsets;
import java.security.*;

public class Main {

    static KeyPair keyPair;

    public static void main(String[] args) throws NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException, NoSuchPaddingException {
        System.out.println("BadPaddingException: Message is larger than modulus");
        // https://stackoverflow.com/questions/64722370/why-do-i-get-badpaddingexception-message-is-larger-than-modulus-when-decrypti
        keyPair = generateKeyPair(512); // ### do not use RSA keys with 512 bits length, minimum 2048 bits
        // 512 bit = 64 byte - 11 byte for padding = maximal 53 bytes data to encrypt
        System.out.println("\nencrypting 53 chars");
        String data53Chars = "12345678901234567890123456789012345678901234567890123";
        //String data53Chars = "12345678901234567890";
        System.out.println("encrypting " + data53Chars);
        byte[] encryptedData = encryptData(data53Chars);
        System.out.println("encryptedData length: " + encryptedData.length);
        String decryptedData = decryptData(encryptedData);
        System.out.println("decryptedData: " + decryptedData);
        // now 54 bytes
        System.out.println("\nencrypting 54 chars");
        String data54Chars = "123456789012345678901234567890123456789012345678901234";
        System.out.println("encrypting " + data54Chars);
        encryptedData = encryptData(data54Chars);
        System.out.println("encryptedData length: " + encryptedData.length);
        decryptedData = decryptData(encryptedData);
        System.out.println("decryptedData: " + decryptedData);
    }

    public static byte[] encryptData(String data) throws BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException {
        PublicKey publicKey = keyPair.getPublic();
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
    }

    public static String decryptData(byte[] encryptedBytes) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, NoSuchAlgorithmException {
        byte[] decipheredText = new byte[0];
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
        decipheredText = cipher.doFinal(encryptedBytes);
        return new String(decipheredText, StandardCharsets.UTF_8);
    }

    static KeyPair generateKeyPair(int keyLength) throws NoSuchAlgorithmException {
        final String KEY_ALGORITHM = "RSA";
        KeyPairGenerator keygen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        keygen.initialize(keyLength, new SecureRandom());
        KeyPair keyPair = keygen.generateKeyPair();
        return keyPair;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM