Java AES解密的3gp文件似乎已损坏
我在使用AES算法对文件进行编码和解码时遇到问题。我正在用android录制音频并加密录制的文件,通过webservice发送到另一个应用程序和另一个应用程序,文件被解密。密钥也会正常发送和到达 问题是,要用密钥解密文件,当用android player和VLC Media player打开文件时,文件似乎已损坏 回想一下,未加密的文件到达另一方时没有问题,密钥也没有问题 密钥是为记录的每个文件随机生成的32个字符的字符串。下面是加密和解密文件的类 格式为.3 gp。我使用的android仅作为mp4和3gp使用 在这种情况下该怎么办Java AES解密的3gp文件似乎已损坏,java,android,encryption,aes,Java,Android,Encryption,Aes,我在使用AES算法对文件进行编码和解码时遇到问题。我正在用android录制音频并加密录制的文件,通过webservice发送到另一个应用程序和另一个应用程序,文件被解密。密钥也会正常发送和到达 问题是,要用密钥解密文件,当用android player和VLC Media player打开文件时,文件似乎已损坏 回想一下,未加密的文件到达另一方时没有问题,密钥也没有问题 密钥是为记录的每个文件随机生成的32个字符的字符串。下面是加密和解密文件的类 格式为.3 gp。我使用的android仅作为
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import android.content.Context;
public class AES extends Cripto {
public static void encrypt(Context c, String nomeArquivo)
throws IOException, NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException {
String key = GenerateKey(); //key 32 character randomly generated
String pathFilePure = new _Path().getPathFilePure();
String pathFileCripted = new _Path().getPathFileCripto();
FileInputStream fis = new FileInputStream(pathFilePure + "/"
+ nomeArquivo);
FileOutputStream fos = new FileOutputStream(pathFileCripted + "/"
+ nomeArquivo);
SecretKeySpec sks = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, sks);
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
int b;
byte[] d = new byte[8];
while ((b = fis.read(d)) != -1) {
cos.write(d, 0, b);
}
cos.flush();
cos.close();
fis.close();
}
public static void decrypt(Context c, String fileName, String key)
throws IOException, NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException {
FileInputStream fis = new FileInputStream(
new _Path().getPathFileDownload() + "/" + fileName);
FileOutputStream fos = new FileOutputStream(
new _Path().getPathFileDescripto() + "/" + fileName);
SecretKeySpec sks = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, sks);
CipherInputStream cis = new CipherInputStream(fis, cipher);
int b;
byte[] d = new byte[8];
while ((b = cis.read(d)) != -1) {
fos.write(d, 0, b);
}
fos.flush();
fos.close();
cis.close();
}
}
没有32个字符的AES密钥。AES密钥是256位或AES-256的32字节。如果您创建随机字节(您应该这样做),那么不是每个字节都代表一个可打印字符。因此,如果将字节“解码”为
字符串
实例(例如,使用新字符串(字节)
),则可能会丢失数据
如果您需要字符串,请查看我的答案。请注意,您不应使用ECB模式加密,如果您指定
“AES”,这是默认设置
作为密码的算法
。也不要使用默认值。我一直在研究并设法解决下面的类的问题,该类现在可以工作,即加密和解密
package com.infovale.cripto;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import android.content.Context;
public class AES extends Cripto {
public static String encrypt(Context c, String nomeArquivo) {
String caminhoArquivoPuro = new _Path().getPathFilePure() + "/"
+ nomeArquivo;
String caminhoArquivoCriptografado = new _Path().getPathFileCripto()
+ "/" + nomeArquivo;
String key = null;
;
try {
FileInputStream fis = new FileInputStream(new File(
caminhoArquivoPuro));
File outfile = new File(caminhoArquivoCriptografado);
int read;
if (!outfile.exists())
outfile.createNewFile();
FileOutputStream fos = new FileOutputStream(outfile);
FileInputStream encfis = new FileInputStream(outfile);
Cipher encipher = Cipher.getInstance("AES");
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecretKey skey = kgen.generateKey();
encipher.init(Cipher.ENCRYPT_MODE, skey);
CipherInputStream cis = new CipherInputStream(fis, encipher);
key = bytesToString(skey.getEncoded());
byte[] b = stringToBytes(key);
while ((read = cis.read()) != -1) {
fos.write((char) read);
fos.flush();
}
fos.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
entityFiles file = new entityFiles();
file.setCaminhoArquivoPuro(caminhoArquivoPuro);
file.setCaminhoArquivoCriptografado(caminhoArquivoCriptografado);
file.setKeyArquivo(key);
file.setNomeArquivo(nomeArquivo);
ArquivoDataSource datasource = new ArquivoDataSource(c);
datasource.open();
file = datasource.createRegistro(file);
datasource.close();
}
return key;
}
public static void decrypt(Context c, String nomeArquivo, String key) {
String caminhoArquivoPuro = new _Path().getPathFileCripto() + "/"
+ nomeArquivo;
String caminhoArquivoCriptografado = new _Path().getPathFileDescripto()
+ "/" + nomeArquivo;
try {
FileInputStream fis = new FileInputStream(new File(
caminhoArquivoPuro));
File outfile = new File(caminhoArquivoPuro);
int read;
if (!outfile.exists()) {
outfile.createNewFile();
}
File decfile = new File(caminhoArquivoCriptografado);
if (!decfile.exists()) {
decfile.createNewFile();
}
FileInputStream encfis = new FileInputStream(outfile);
FileOutputStream decfos = new FileOutputStream(decfile);
Cipher decipher = Cipher.getInstance("AES");
SecretKey originalKey = new SecretKeySpec(stringToBytes(key), 0,
stringToBytes(key).length, "AES");
decipher.init(Cipher.DECRYPT_MODE, originalKey);
CipherOutputStream cos = new CipherOutputStream(decfos, decipher);
while ((read = encfis.read()) != -1) {
cos.write(read);
cos.flush();
}
cos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static String bytesToString(byte[] b) {
byte[] b2 = new byte[b.length + 1];
b2[0] = 1;
System.arraycopy(b, 0, b2, 1, b.length);
return new BigInteger(b2).toString(36);
}
public static byte[] stringToBytes(String s) {
byte[] b2 = new BigInteger(s, 36).toByteArray();
return Arrays.copyOfRange(b2, 1, b2.length);
}
}
使用字符串worked=),我很难安装tie来加密文件。如果(!outfile.exists())outfile.createNewFile(),则不需要代码>。您只是在重复新建FileOutputStream()
也会做的工作,但它仍然会这样做,此外,它现在必须删除您创建的文件,因此您实际上浪费了更多的时间。