Java 视频文件的加密?
我使用此方法加密视频文件:Java 视频文件的加密?,java,android,file,encryption,out-of-memory,Java,Android,File,Encryption,Out Of Memory,我使用此方法加密视频文件: public static void encryptToBinaryFile(String password, byte[] bytes, File file) throws EncrypterException { try { final byte[] rawKey = getRawKey(password.getBytes()); final FileOutputStream ostream = new FileOutput
public static void encryptToBinaryFile(String password, byte[] bytes, File file) throws EncrypterException {
try {
final byte[] rawKey = getRawKey(password.getBytes());
final FileOutputStream ostream = new FileOutputStream(file, false);
ostream.write(encrypt(rawKey, bytes));
ostream.flush();
ostream.close();
} catch (IOException e) {
throw new EncrypterException(e);
}
}
private static byte[] encrypt(byte[] raw, byte[] clear) throws EncrypterException {
try {
final SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
final Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
return cipher.doFinal(clear);
} catch (Exception e) {
throw new EncrypterException(e);
}
}
但它给出了一个错误Outofmemoryerror,表示拒绝分配301023321元素
1.对于这样大的文件,我使用的方法正确吗
2.如果是,为什么会出现此错误?解决方案是什么
3.如果没有,请建议一些好的方法?
CipherInputStream
和CipherOutputStream
将帮助您轻松做到这一点。我编写了一个示例程序来加密和解密视频文件。根据您的选择修改它
FileInputStream fis = new FileInputStream(new File("D:/Shashank/inputVideo.avi"));
File outfile = new File("D:/Shashank/encVideo.avi");
int read;
if(!outfile.exists())
outfile.createNewFile();
File decfile = new File("D:/Shashank/decVideo.avi");
if(!decfile.exists())
decfile.createNewFile();
FileOutputStream fos = new FileOutputStream(outfile);
FileInputStream encfis = new FileInputStream(outfile);
FileOutputStream decfos = new FileOutputStream(decfile);
Cipher encipher = Cipher.getInstance("AES");
Cipher decipher = Cipher.getInstance("AES");
KeyGenerator kgen = KeyGenerator.getInstance("AES");
//byte key[] = {0x00,0x32,0x22,0x11,0x00,0x00,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
SecretKey skey = kgen.generateKey();
//Lgo
encipher.init(Cipher.ENCRYPT_MODE, skey);
CipherInputStream cis = new CipherInputStream(fis, encipher);
decipher.init(Cipher.DECRYPT_MODE, skey);
CipherOutputStream cos = new CipherOutputStream(decfos,decipher);
while((read = cis.read())!=-1)
{
fos.write((char)read);
fos.flush();
}
fos.close();
while((read=encfis.read())!=-1)
{
cos.write(read);
cos.flush();
}
cos.close();
我正在使用generateKey()
生成一个新密钥。您也可以使用字节数组来生成自己的密钥……
使用JavaSecureRandom
随机IV生成快速加密/解密
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Encrypter {
private final static int IV_LENGTH = 16; // Default length with Default 128
// key AES encryption
private final static int DEFAULT_READ_WRITE_BLOCK_BUFFER_SIZE = 1024;
private final static String ALGO_RANDOM_NUM_GENERATOR = "SHA1PRNG";
private final static String ALGO_SECRET_KEY_GENERATOR = "AES";
private final static String ALGO_VIDEO_ENCRYPTOR = "AES/CBC/PKCS5Padding";
@SuppressWarnings("resource")
public static void encrypt(SecretKey key, /*AlgorithmParameterSpec paramSpec,*/ InputStream in, OutputStream out)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
InvalidAlgorithmParameterException, IOException {
try {
// byte[] iv = new byte[] { (byte) 0x8E, 0x12, 0x39, (byte) 0x9C,
// 0x07, 0x72, 0x6F, 0x5A, (byte) 0x8E, 0x12, 0x39, (byte) 0x9C,
// 0x07, 0x72, 0x6F, 0x5A };
//generate new AlgorithmParameterSpec
// AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
Cipher c = Cipher.getInstance(ALGO_VIDEO_ENCRYPTOR);
c.init(Cipher.ENCRYPT_MODE, key, paramSpec);
out = new CipherOutputStream(out, c);
int count = 0;
byte[] buffer = new byte[DEFAULT_READ_WRITE_BLOCK_BUFFER_SIZE];
while ((count = in.read(buffer)) >= 0) {
out.write(buffer, 0, count);
}
} finally {
out.close();
}
}
@SuppressWarnings("resource")
public static void decrypt(SecretKey key, /*AlgorithmParameterSpec paramSpec,*/ InputStream in, OutputStream out)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
InvalidAlgorithmParameterException, IOException {
try {
// byte[] iv = new byte[] { (byte) 0x8E, 0x12, 0x39, (byte) 0x9C,
// 0x07, 0x72, 0x6F, 0x5A, (byte) 0x8E, 0x12, 0x39, (byte) 0x9C,
// 0x07, 0x72, 0x6F, 0x5A };
// read from input stream AlgorithmParameterSpec
// AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
Cipher c = Cipher.getInstance(ALGO_VIDEO_ENCRYPTOR);
c.init(Cipher.DECRYPT_MODE, key, paramSpec);
out = new CipherOutputStream(out, c);
int count = 0;
byte[] buffer = new byte[DEFAULT_READ_WRITE_BLOCK_BUFFER_SIZE];
while ((count = in.read(buffer)) >= 0) {
out.write(buffer, 0, count);
}
} finally {
out.close();
}
}
public static void main(String[] args) {
File inFile = new File("C:/enc_test/video.swf");
File outFile = new File("C:/enc_test/enc_video.swf");
File outFile_dec = new File("C:/enc_test/dec_video.swf");
try {
SecretKey key = KeyGenerator.getInstance(ALGO_SECRET_KEY_GENERATOR).generateKey();
byte[] keyData = key.getEncoded();
SecretKey key2 = new SecretKeySpec(keyData, 0, keyData.length, ALGO_SECRET_KEY_GENERATOR); //if you want to store key bytes to db so its just how to //recreate back key from bytes array
byte[] iv = new byte[IV_LENGTH];
SecureRandom.getInstance(ALGO_RANDOM_NUM_GENERATOR).nextBytes(iv); // If
// storing
// separately
AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
Encrypter.encrypt(key, paramSpec, new FileInputStream(inFile), new FileOutputStream(outFile));
Encrypter.decrypt(key2, paramSpec, new FileInputStream(outFile), new FileOutputStream(outFile_dec));
} catch (Exception e) {
e.printStackTrace();
}
}
}
感谢您的建议而不是dofinal,我将使用update和我的初始字节[](每次几Kb)的块,并将它们写入文件。或者使用dofinal方法和2个ByteBuffers itemsHow。您要解密这个吗?你把视频分块加密,这让事情变得复杂了……我是新手,你能帮我编一些代码吗?不需要那么多的tym……我猜你的文件很大……有多长?你打算如何再次播放加密视频,而不以未加密的形式公开它?@ShashankKadne-当然,但真正有趣的问题是,您计划如何解密和播放它们,而不将解密后的版本暴露给复制。您在读取和加密时使用字符流,速度非常慢,相反,您可以使用缓冲区和逐行读取来提高速度,如字节[]缓冲区=新字节[1024];while((count=in.read(buffer))>=0){out.write(buffer,0,count);}@anish:看起来密钥大小是128位(16字节)。如果需要,可以使用KeyGenerator
的init
方法更改它,例如:kgen.init(256)代码>很棒的工作。非常感谢。出于某种原因,AES/CBC/pkcs5p添加
对我不起作用,将其更改为AES
起作用……有时最好显示固执己见的代码,因为大多数读者不会正确理解它。IV不是秘密,所以你可以把它和密文一起发送。通常,它只是在密文前面加上前缀,然后在解密之前切掉。@ArtjomB。我已经在类变量中声明了IV_长度,IV_长度=16。我希望我已经正确理解了你的问题,如果我不清楚的话,很抱歉。最好从encrypt
和decrypt
的方法签名中删除AlgorithmParameterSpec
(IV)参数,而是:在encrypt
中生成一个新的IV,将其写入输出流并用于加密,然后在decrypt
中从输入流读取IV并用于解密。这样,未来的读者就不需要自己关心IV,也不会弄错,而且很容易弄错。@AZ_uu感谢您的回复,现在我正在使用这个库播放解密的视频