java - 解密加密文件时获得一堆额外的输出。我的代码中可能有什么问题?
问题描述
我是密码学的新手,这是我编写的填充我的分配者提供的骨架代码的代码(请不要介意结构)。我在这段代码下面描述了问题。
public class FileEncryptor {
private static final String progName = "FileEncryptor";
private static final int bufSize = 128;
public static void main(String[] args) {
BufferedInputStream in = null; // A buffered input stream to read from
BufferedOutputStream out = null; // And a buffered output stream to write to
SecretKeyFactory kf = null; // Something to create a key for us
KeySpec ks = null; // This is how we specify what kind of key we want it to generate
byte[] salt = new byte[20]; // Some salt for use with PBKDF2, only not very salty
SecretKey key = null; // The key that it generates
Cipher cipher = null; // The cipher that will do the real work
SecretKeySpec keyspec = null; // How we pass the key to the Cipher
int bytesRead = 0; // Number of bytes read into the input file buffer
// First, check the user has provided all the required arguments, and if they haven't, tell them then exit
if(args.length != 4) {
printUsageMessage(); System.exit(1);
}
// Open the input file
try {
in = new BufferedInputStream(new FileInputStream(args[1]));
} catch (FileNotFoundException e) {
printErrorMessage("Unable to open input file: " + args[1], null);
System.exit(1);
}
// And then the output file
try {
out = new BufferedOutputStream(new FileOutputStream(args[2]));
} catch (FileNotFoundException e) {
printErrorMessage("Unable to open output file: " + args[2], e);
System.exit(1);
}
// Create a PBKDF2 secret key factory
String algorithm = "PBKDF2WithHmacSHA256";
try {
kf = SecretKeyFactory.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
printErrorMessage("Specified algorithm could not be found: " + algorithm , e);
System.exit(1);
}
// Set up a KeySpec for password-based key generation of a 128-bit key
ks = new PBEKeySpec(args[3].toCharArray(),salt,4096, 128);
// Now run the passphrase through PBKDF2 to get the key
try {
key = kf.generateSecret(ks);
} catch (InvalidKeySpecException e) {
printErrorMessage("The key spec provided is invalid: " + keyspec, e);
System.exit(1);
}
// Get the byte encoded key value as a byte array
byte[] aeskey = key.getEncoded();
// Now generate a Cipher object for AES encryption in ECBC mode with PKCS #5 padding
// Use ECB for the first task, then switch to CBC for versions 2 and 3
try {
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
} catch (NoSuchAlgorithmException e) {
printErrorMessage("No Such Algorithm Exception when creating main cipher", e);
System.exit(2);
} catch (NoSuchPaddingException e) {
printErrorMessage("No Such Padding Exception when creating main cipher",e);
System.exit(2);
}
// Set a variable to indicate whether we're in encrypt or decrypt mode, based upon args[0]
int cipherMode = -1;
char mode = Character.toLowerCase(args[0].charAt(0));
switch (mode) {
case 'e' : cipherMode = Cipher.ENCRYPT_MODE; break;
case 'd' : cipherMode = Cipher.DECRYPT_MODE; break;
default: printUsageMessage(); System.exit(1);
}
// Set up a secret key specification, based on the 16-byte (128-bit) AES key array previously generated
keyspec = new SecretKeySpec(aeskey, "AES");
// Now initialize the cipher in the right mode, with the keyspec and the ivspec
try {
cipher.init(cipherMode, keyspec);
} catch (InvalidKeyException e) {
printErrorMessage("Invalid Key Spec",e); System.exit(2);
}
// Set up some input and output byte array buffers
byte[] inputBuffer = new byte[bufSize];
byte[] outputBuffer = null;
// "Prime the pump" - we've got to read something before we can encrypt it
// and not encrypt anything if we read nothing.
try {
bytesRead = in.read(inputBuffer);
} catch (IOException e1) {
printErrorMessage("Error reading input file " + args[1],e1); System.exit(1);
}
// As long as we've read something, loop around encrypting, writing and reading
// bytesRead will be zero if nothing was read, or -1 on EOF - treat them both the same
while (bytesRead > 0) {
byte[] input = inputBuffer;
// Now encrypt this block
outputBuffer = cipher.update(input);
// Write the generated block to file
try {
out.write(outputBuffer);
} catch (IOException e1) {
printErrorMessage("Error writing to output file " + args[2],e1); System.exit(1);
}
// And read in the next block of the file
try {
bytesRead = in.read(inputBuffer);
} catch (IOException e1) {
printErrorMessage("Error reading input file " + args[1],e1); System.exit(1);
}
}
// Now do the final processing
try {
outputBuffer = cipher.doFinal(outputBuffer);
} catch (IllegalBlockSizeException e2) {
printErrorMessage("Illegal block size encountered while doing final processing: " + outputBuffer.length , e2);
System.exit(1);
} catch (BadPaddingException e2) {
printErrorMessage("Bad Padding found", e2);
System.exit(1);
}
// Write the final block of output
try {
out.write(outputBuffer);
} catch (IOException e1) {
printErrorMessage("Error on final write to output file " + args[2],e1); System.exit(1);
}
// Close the output files
try {
in.close();
out.close();
} catch (IOException e1) {
printErrorMessage("Error closing file", e1);
}
}
}
为方便起见,我省略了printErrorMessage()
andprintUsageMessage()
方法。
这似乎是问题所在;我得到了一个BadPaddingException
,尽管代码捕获了该异常,但我不知道如何处理该异常或如何处理它。我尝试System.exit(1)
在最终处理中从我的代码中删除该行,但是输出文件的大小是我的加密文件的两倍,即 256 字节,而不管我的输入文件的大小(大小小于 256 字节)。所以,如果我的输入文件包含:
hello there
我使用key
密码对其进行加密,我得到的输出文件包含以下内容:
9`ÃLå7}
syXÀ¢Èì´^¾Õn¾AXëC~9‹`Èì´^¾Õn¾AXëC~9‹`Èì´^¾Õn¾AXëC~9‹`Èì´^¾Õn¾AXëC~9‹`Èì´^¾Õn¾AXëC~9‹`Èì´^¾Õn¾AXëC~9‹`Èì´^¾Õn¾AXëC~9‹`0‹ó‚±G¸Y·IñåsòQœ ÙÞç„ò;uîðpoîœ ÙÞç„ò;uîðpoîœ ÙÞç„ò;uîðpoîœ ÙÞç„ò;uîðpoîœ ÙÞç„ò;uîðpoîœ ÙÞç„ò;uîðpoîœ ÙÞç„ò;uîðpoÄQé±uTö/ژͤ
现在,当我使用相同的密码解密此文件时,key
我得到如下信息:
hello there 9`Ì巽
syXÀ¢Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`
我怎样才能摆脱这个拖在我解密文本后面的狗屎风暴?所有帮助和建议将不胜感激。谢谢。
解决方案
推荐阅读
- laravel - auth:api 中间件的作用以及为什么我使用它时会话不起作用
- android - 更新到 android 3.5.0 后 Flutter 不会构建 appbundle
- python - 查找出现在两个不同列表中的唯一数字
- c# - 如何对文本进行限制?C#
- windows - ffmpeg 提取具有零索引文件名的帧
- laravel - laravel where 条件与 % 运算符
- apache-camel - 当目的地不可用时如何停止在骆驼路线中消费消息
- acumatica - 处理屏幕网格空白处理后连接的表数据
- python - 如果 LIST 中的 x 或 y 始终为真,即使它不是
- ios - iOS 12.4.2 上的 iOS 崩溃“无法执行读取 Objective-C 的支持代码”而不是 12.0.1