簡體   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