gpt4 book ai didi

java - 在java中使用cipher,如何使加密文件的长度为16的倍数?

转载 作者:行者123 更新时间:2023-12-01 06:03:46 26 4
gpt4 key购买 nike

Error : javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher

尝试过的解决方案:我尝试将 padding 更改为 "AES/ECB/NoPadding", "AES/ECB/PKCS5", "AES/CBC/NoPadding”、“AES/CBC/PKCS5Padding”,但仍然收到相同的错误或仅需要 AESRijndael 的错误。然后我尝试使 key 使用“AES”参数并将 ALGO 设置为“AES/CBC/PKCS5Padding”,但我收到了一个缺少参数的错误,我尝试修复添加 new IvParameterSpec(新字节[16])cipher.init。它仍然导致 16 位问题。所以我现在被困住了。

import java.util.Scanner;
import java.io.File;
import java.io.IOException;

import java.io.BufferedReader;
import java.io.FileReader;

import java.security.Key;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.*;

import java.io.PrintWriter;
import java.io.FileWriter;

import java.util.*;
import java.io.*;

// Don't forget to import any supporting classes you plan to use.

public class Crypto
{
private Scanner fileText;
private PrintWriter fileEncrypt;
private Scanner inputFile;
private PrintWriter outputFile;

private static final String ALGO = "AES/CBC/PKCS5Padding";
private byte[] keyValue;

public Crypto(String key)
{
keyValue = key.getBytes();
}

public String encrypt(String Data) throws Exception
{
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encVal = c.doFinal(Data.getBytes());
String encryptedValue = new BASE64Encoder().encode(encVal);
return encryptedValue;
}

public String decrypt(String encryptedData) throws Exception
{
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.DECRYPT_MODE, key);
byte[] decodedValue = new BASE64Decoder().decodeBuffer(encryptedData);
byte[] decValue = c.doFinal(decodedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}

public Key generateKey() throws Exception
{
Key key = new SecretKeySpec(keyValue, "AES");
return key;
}

// encrypt_decrypt("ENCRYPT", "CryptoPlaintext.txt", "CryptoCiphertext.txt" )
// encrypt_decrypt("DECRYPT", "CryptoCiphertext.txt", "CryptoDeciphered.txt")

public void encrypt_decrypt(String function_type , String source_file , String
target_file)
{
String lineValue = "";
String convertedValue = "";
try
{
inputFile = new Scanner(new File(source_file));
}
catch(Exception e)
{
System.out.println("( " + source_file + ") - File Opening Error");
}
try
{
outputFile = new PrintWriter(new FileWriter(target_file));
}
catch(Exception e)
{
System.out.println("( " + target_file + ") - File Opening Error");
}

while(inputFile.hasNext())
{
lineValue = inputFile.nextLine();
System.out.println("Source Line: " + lineValue);

try
{
if (function_type == "ENCRYPT")
{
convertedValue = encrypt(lineValue);
}
else if (function_type == "DECRYPT")
{
convertedValue = decrypt(lineValue);
}
}
catch(Exception e)
{
System.out.println(e);
}
System.out.println("Converted Line : " + convertedValue);

outputFile.write(convertedValue);
}

inputFile.close();
outputFile.close();
}

public static void main( String args[] ) throws IOException
{

// Write your code here...
// You will read from CryptoPlaintext.txt and write to
CryptoCiphertext.txt.
Crypto c = new Crypto("dk201anckse29sns");
c.encrypt_decrypt("ENCRYPT", "CryptoPlaintext.txt", "CryptoCiphertext.txt"
);
c.encrypt_decrypt("DECRYPT", "CryptoCiphertext.txt",
"CryptoDeciphered.txt");
//
// And then read from CryptoCiphertext.txt and write to
CryptoDeciphered.txt.
//
// DON'T forget your comments!
// =============================== DO NOT MODIFY ANY CODE BELOW HERE
==============================

// Compare the files

System.out.println(compareFiles() ? "The files are identical!" : "The
files are NOT identical.");
}

/**
* Compares the Plaintext file with the Deciphered file.
*
* @return true if files match, false if they do not
*/

public static boolean compareFiles() throws IOException
{

Scanner pt = new Scanner(new File("CryptoPlaintext.txt")); // Open the
plaintext file
Scanner dc = new Scanner(new File("CryptoDeciphered.txt")); // Open the
deciphered file

// Read through the files and compare them record by record.
// If any of the records do not match, the files are not identical.

while(pt.hasNextLine() && dc.hasNextLine())
if(!pt.nextLine().equals(dc.nextLine())) return false;

// If we have any records left over, then the files are not identical.

if(pt.hasNextLine() || dc.hasNextLine()) return false;

// The files are identical.

return true;




}
}

最佳答案

您的代码中有两个错误:

  1. 您忘记生成随机 IV 并将其作为密文的前缀(在将其编码为 Base 64 之前)。您需要从密文中找到 IV,然后在解密过程中再次检索它。

请注意,CBC 代码需要一个与随机无法区分的 IV。您可以使用 new SecureRandom (当然,仅在加密期间)和 IvParameterSpec 创建它。代码可能会在没有这个的情况下运行,因为 Java 中的默认实现默认在全零 IV 上。对于本次作业来说,这可能已经足够了。

但这并不是产生错误的原因;这实在是太平庸了:

  • 您正在调用 outputFile.write 而不是 outputFile.println,这意味着不会插入换行符,并且所有 Base 64 编码都会放在一行中。
  • 请注意,您不应该使用sun.misc中的任何类。这些是 Java 实现私有(private)的,并且不是 Java API 的一部分。为了方便起见,新的 Java 版本具有 java.util.Base64。实际上,sun.misc 版本可能会在 Base 64 编码中插入行结尾,这会破坏较长行的代码。

    <小时/>

    例如:

    package nl.owlstead.stackoverflow;

    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.security.Key;
    import java.util.Base64;
    import java.util.Scanner;

    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;

    public class Crypto {
    private Scanner inputFile;
    private PrintWriter outputFile;

    private static final String ALGO = "AES/CBC/PKCS5Padding";
    private byte[] keyValue;

    public Crypto(String key) {
    keyValue = key.getBytes();
    }

    public String encrypt(String Data) throws Exception {
    Key key = generateKey();
    Cipher c = Cipher.getInstance(ALGO);
    c.init(Cipher.ENCRYPT_MODE, key,
    new IvParameterSpec(new byte[c.getBlockSize()]));
    byte[] encVal = c.doFinal(Data.getBytes());
    String encryptedValue = Base64.getEncoder().encodeToString(encVal);
    return encryptedValue;
    }

    public String decrypt(String encryptedData) throws Exception {
    Key key = generateKey();
    Cipher c = Cipher.getInstance(ALGO);
    c.init(Cipher.DECRYPT_MODE, key,
    new IvParameterSpec(new byte[c.getBlockSize()]));
    byte[] decodedValue = Base64.getDecoder().decode(encryptedData);
    byte[] decValue = c.doFinal(decodedValue);
    String decryptedValue = new String(decValue);
    return decryptedValue;
    }

    public Key generateKey() throws Exception {
    Key key = new SecretKeySpec(keyValue, "AES");
    return key;
    }

    public void encrypt_decrypt(String function_type, String source_file,
    String target_file) {
    String lineValue = "";
    String convertedValue = "";
    try {
    inputFile = new Scanner(new File(source_file));
    } catch (Exception e) {
    System.out.println("( " + source_file + ") - File Opening Error");
    }
    try {
    outputFile = new PrintWriter(new FileWriter(target_file));
    } catch (Exception e) {
    System.out.println("( " + target_file + ") - File Opening Error");
    }

    while (inputFile.hasNext()) {
    lineValue = inputFile.nextLine();
    System.out.println("Source Line: " + lineValue);

    try {
    if (function_type == "ENCRYPT") {
    convertedValue = encrypt(lineValue);
    } else if (function_type == "DECRYPT") {
    convertedValue = decrypt(lineValue);
    }
    } catch (Exception e) {
    System.out.println(e);
    }
    System.out.println("Converted Line : " + convertedValue);

    outputFile.println(convertedValue);
    }

    inputFile.close();
    outputFile.close();
    }

    public static void main(String args[]) throws IOException {

    Crypto c = new Crypto("dk201anckse29sns");
    c.encrypt_decrypt("ENCRYPT", "CryptoPlaintext.txt",
    "CryptoCiphertext.txt");
    c.encrypt_decrypt("DECRYPT", "CryptoCiphertext.txt",
    "CryptoDeciphered.txt");

    System.out.println(compareFiles() ? "The files are identical!"
    : "The files are NOT identical.");
    }

    /**
    * Compares the Plaintext file with the Deciphered file.
    *
    * @return true if files match, false if they do not
    */

    public static boolean compareFiles() throws IOException {

    Scanner pt = new Scanner(new File("CryptoPlaintext.txt")); // Open the
    Scanner dc = new Scanner(new File("CryptoDeciphered.txt")); // Open the

    // Read through the files and compare them record by record.
    // If any of the records do not match, the files are not identical.

    while (pt.hasNextLine() && dc.hasNextLine()) {
    String ptl = pt.nextLine();
    String dcl = dc.nextLine();
    if (!ptl.equals(dcl))
    {
    System.out.println(ptl);
    System.out.println(dcl);
    continue;
    // return false;

    }
    }
    // If we have any records left over, then the files are not identical.

    if (pt.hasNextLine() || dc.hasNextLine())
    return false;

    // The files are identical.

    return true;
    }
    }

    关于java - 在java中使用cipher,如何使加密文件的长度为16的倍数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50288424/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com