文件加密和解密在 java 中不起作用
File encryption and decryption does not work in java
我想最有效地加密一个名为 largefile.mp4
的大型视频文件,然后再次解密,但它没有按预期工作。
实际上没有任何错误,文件生成了。但是新生成的文件比主文件小。
这里 largefile.mp4
是 100mb 但 newEncryptedFile.txt
是 107kb 而 newDecryptedFile.mp4
是 210 字节
有什么问题?
package fileenc;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import java.io.*;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
public class FileEncrypterDecrypter {
SecretKey key;
Cipher cipher;
public FileEncrypterDecrypter() {
try {
KeyGenerator keygen = KeyGenerator.getInstance("AES");
key = keygen.generateKey();
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
System.out.println(e);
}
}
public boolean fileEncrypt(String plainFile) {
try (BufferedInputStream fis = new BufferedInputStream(new FileInputStream(plainFile))){
cipher.init(Cipher.ENCRYPT_MODE, key);
FileOutputStream fs = new FileOutputStream("newEncryptedFile.txt");
CipherOutputStream out = new CipherOutputStream(fs, cipher);
byte[] byteSize = new byte[1024];
int numberOfBytedRead;
while ( (numberOfBytedRead = fis.read(byteSize)) != -1 ) {
out.write(numberOfBytedRead);
}
fis.close();
out.flush();
out.close();
System.out.println("Encryption done...");
return true;
} catch (IOException | InvalidKeyException e) {
}
return false;
}
public boolean fileDecrypt(String encryptedFile) {
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("newDecryptedFile.mp4"))){
cipher.init(Cipher.DECRYPT_MODE, key);
FileInputStream fis = new FileInputStream(encryptedFile);
CipherInputStream in = new CipherInputStream(fis, cipher);
byte[] byteSize = new byte[1024];
int numberOfBytedRead;
while ( (numberOfBytedRead = in.read(byteSize)) != -1) {
bos.write(numberOfBytedRead);
}
System.out.println("Decryption done...");
bos.flush();
bos.close();
in.close();
return true;
} catch (IOException | InvalidKeyException e) {
}
return false;
}
public static void main(String[] args) throws FileNotFoundException, IOException {
FileEncrypterDecrypter fed = new FileEncrypterDecrypter();
fed.fileEncrypt("largefile.mp4"); // about 100 mb
fed.fileDecrypt("newEncryptedFile.txt");
}
}
很抱歉,我没有检查您的代码,因为您使用的是 UNSECURE 模式 ECB,不应再在新项目中使用。
下面是一个使用AES CBC模式加密和解密文件的示例代码。程序生成一个随机密钥用于加密和解密(为了更好地存储,使用base64编码的密钥),生成一个随机初始化向量(IV)写在加密文件的开头。
对于解密,前 16 个字节作为未加密数据读取,所有其他数据通过解密流。
加密是在 CipherOutput-/InputStream.
的帮助下以 8192 字节的块完成的
安全警告:代码没有任何异常处理,仅供学习使用。请注意,为了更好的安全性,您可以更改为经过身份验证的加密(例如使用 HMAC 或使用 GCM 模式进行保护)。
输出:
AES CBC 256 file encryption with CipherOutputStream
encryption key in base64 encoding: vTsd0E8MX3arfLRFjxZ58FSjkKxKYe32+rT5zCnJPVY=
result encryption: true
result decryption: true
代码:
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
public class AesCbcEncryptionWithRandomKeyCipherOutputStreamSoExample {
public static void main(String[] args) throws NoSuchPaddingException, NoSuchAlgorithmException, IOException,
InvalidKeyException, InvalidAlgorithmParameterException {
System.out.println("AES CBC 256 file encryption with CipherOutputStream");
String uncryptedFilename = "plaintext.txt";
String encryptedFilename = "encrypted.enc";
String decryptedFilename = "decrypted.txt";
// generate random aes 256 key
byte[] encryptionKey = new byte[32];
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(encryptionKey);
System.out.println("encryption key in base64 encoding: " + base64Encoding(encryptionKey));
boolean result;
// encryption
result = encryptCbcFileBufferedCipherOutputStream(uncryptedFilename, encryptedFilename, encryptionKey);
System.out.println("result encryption: " + result);
// decryption
result = decryptCbcFileBufferedCipherInputStream(encryptedFilename, decryptedFilename, encryptionKey);
System.out.println("result decryption: " + result);
}
public static boolean encryptCbcFileBufferedCipherOutputStream(String inputFilename, String outputFilename, byte[] key)
throws IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException {
// generate random iv
SecureRandom secureRandom = new SecureRandom();
byte[] iv = new byte[16];
secureRandom.nextBytes(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
try (FileInputStream in = new FileInputStream(inputFilename);
FileOutputStream out = new FileOutputStream(outputFilename);
CipherOutputStream encryptedOutputStream = new CipherOutputStream(out, cipher);) {
out.write(iv);
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] buffer = new byte[8096];
int nread;
while ((nread = in.read(buffer)) > 0) {
encryptedOutputStream.write(buffer, 0, nread);
}
encryptedOutputStream.flush();
}
if (new File(outputFilename).exists()) {
return true;
} else {
return false;
}
}
public static boolean decryptCbcFileBufferedCipherInputStream(String inputFilename, String outputFilename, byte[] key) throws
IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException {
byte[] iv = new byte[16];
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
try (FileInputStream in = new FileInputStream(inputFilename);
CipherInputStream cipherInputStream = new CipherInputStream(in, cipher);
FileOutputStream out = new FileOutputStream(outputFilename))
{
byte[] buffer = new byte[8192];
in.read(iv);
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
int nread;
while ((nread = cipherInputStream.read(buffer)) > 0) {
out.write(buffer, 0, nread);
}
out.flush();
}
if (new File(outputFilename).exists()) {
return true;
} else {
return false;
}
}
private static String base64Encoding(byte[] input) {
return Base64.getEncoder().encodeToString(input);
}
}
我想最有效地加密一个名为 largefile.mp4
的大型视频文件,然后再次解密,但它没有按预期工作。
实际上没有任何错误,文件生成了。但是新生成的文件比主文件小。
这里 largefile.mp4
是 100mb 但 newEncryptedFile.txt
是 107kb 而 newDecryptedFile.mp4
是 210 字节
有什么问题?
package fileenc;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import java.io.*;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
public class FileEncrypterDecrypter {
SecretKey key;
Cipher cipher;
public FileEncrypterDecrypter() {
try {
KeyGenerator keygen = KeyGenerator.getInstance("AES");
key = keygen.generateKey();
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
System.out.println(e);
}
}
public boolean fileEncrypt(String plainFile) {
try (BufferedInputStream fis = new BufferedInputStream(new FileInputStream(plainFile))){
cipher.init(Cipher.ENCRYPT_MODE, key);
FileOutputStream fs = new FileOutputStream("newEncryptedFile.txt");
CipherOutputStream out = new CipherOutputStream(fs, cipher);
byte[] byteSize = new byte[1024];
int numberOfBytedRead;
while ( (numberOfBytedRead = fis.read(byteSize)) != -1 ) {
out.write(numberOfBytedRead);
}
fis.close();
out.flush();
out.close();
System.out.println("Encryption done...");
return true;
} catch (IOException | InvalidKeyException e) {
}
return false;
}
public boolean fileDecrypt(String encryptedFile) {
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("newDecryptedFile.mp4"))){
cipher.init(Cipher.DECRYPT_MODE, key);
FileInputStream fis = new FileInputStream(encryptedFile);
CipherInputStream in = new CipherInputStream(fis, cipher);
byte[] byteSize = new byte[1024];
int numberOfBytedRead;
while ( (numberOfBytedRead = in.read(byteSize)) != -1) {
bos.write(numberOfBytedRead);
}
System.out.println("Decryption done...");
bos.flush();
bos.close();
in.close();
return true;
} catch (IOException | InvalidKeyException e) {
}
return false;
}
public static void main(String[] args) throws FileNotFoundException, IOException {
FileEncrypterDecrypter fed = new FileEncrypterDecrypter();
fed.fileEncrypt("largefile.mp4"); // about 100 mb
fed.fileDecrypt("newEncryptedFile.txt");
}
}
很抱歉,我没有检查您的代码,因为您使用的是 UNSECURE 模式 ECB,不应再在新项目中使用。
下面是一个使用AES CBC模式加密和解密文件的示例代码。程序生成一个随机密钥用于加密和解密(为了更好地存储,使用base64编码的密钥),生成一个随机初始化向量(IV)写在加密文件的开头。
对于解密,前 16 个字节作为未加密数据读取,所有其他数据通过解密流。
加密是在 CipherOutput-/InputStream.
的帮助下以 8192 字节的块完成的安全警告:代码没有任何异常处理,仅供学习使用。请注意,为了更好的安全性,您可以更改为经过身份验证的加密(例如使用 HMAC 或使用 GCM 模式进行保护)。
输出:
AES CBC 256 file encryption with CipherOutputStream
encryption key in base64 encoding: vTsd0E8MX3arfLRFjxZ58FSjkKxKYe32+rT5zCnJPVY=
result encryption: true
result decryption: true
代码:
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
public class AesCbcEncryptionWithRandomKeyCipherOutputStreamSoExample {
public static void main(String[] args) throws NoSuchPaddingException, NoSuchAlgorithmException, IOException,
InvalidKeyException, InvalidAlgorithmParameterException {
System.out.println("AES CBC 256 file encryption with CipherOutputStream");
String uncryptedFilename = "plaintext.txt";
String encryptedFilename = "encrypted.enc";
String decryptedFilename = "decrypted.txt";
// generate random aes 256 key
byte[] encryptionKey = new byte[32];
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(encryptionKey);
System.out.println("encryption key in base64 encoding: " + base64Encoding(encryptionKey));
boolean result;
// encryption
result = encryptCbcFileBufferedCipherOutputStream(uncryptedFilename, encryptedFilename, encryptionKey);
System.out.println("result encryption: " + result);
// decryption
result = decryptCbcFileBufferedCipherInputStream(encryptedFilename, decryptedFilename, encryptionKey);
System.out.println("result decryption: " + result);
}
public static boolean encryptCbcFileBufferedCipherOutputStream(String inputFilename, String outputFilename, byte[] key)
throws IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException {
// generate random iv
SecureRandom secureRandom = new SecureRandom();
byte[] iv = new byte[16];
secureRandom.nextBytes(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
try (FileInputStream in = new FileInputStream(inputFilename);
FileOutputStream out = new FileOutputStream(outputFilename);
CipherOutputStream encryptedOutputStream = new CipherOutputStream(out, cipher);) {
out.write(iv);
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] buffer = new byte[8096];
int nread;
while ((nread = in.read(buffer)) > 0) {
encryptedOutputStream.write(buffer, 0, nread);
}
encryptedOutputStream.flush();
}
if (new File(outputFilename).exists()) {
return true;
} else {
return false;
}
}
public static boolean decryptCbcFileBufferedCipherInputStream(String inputFilename, String outputFilename, byte[] key) throws
IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException {
byte[] iv = new byte[16];
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
try (FileInputStream in = new FileInputStream(inputFilename);
CipherInputStream cipherInputStream = new CipherInputStream(in, cipher);
FileOutputStream out = new FileOutputStream(outputFilename))
{
byte[] buffer = new byte[8192];
in.read(iv);
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
int nread;
while ((nread = cipherInputStream.read(buffer)) > 0) {
out.write(buffer, 0, nread);
}
out.flush();
}
if (new File(outputFilename).exists()) {
return true;
} else {
return false;
}
}
private static String base64Encoding(byte[] input) {
return Base64.getEncoder().encodeToString(input);
}
}