I need to download mp3 files, encrypt, when necessary, to decrypt a temporary mp3 and listen.
Used as reference this answer already done in StackOverflow
Encrypting files with AES on Android
All steps works. But when I send the generated mp3 file for the MediaPlayer does not recognize and break.
These are my download and encryption method
public void executeAsyncDownload(String urlFile, String id, int position, HandlerCallback callback) {
String encryptedName = Cypher.md5(id);
if (MediaUtils.containsFile(encryptedName)) {
callback.onDownloadFinish(position);
return;
}
File dir = MediaUtils.getDestinationFolder(destination);
if (!dir.exists()) {
dir.mkdir();
}
try {
if (canceled)
return;
callback.onDownloadStart(position);
URL url = new URL(urlFile);
URLConnection connection = url.openConnection();
connection.connect();
int tamFile = connection.getContentLength();
String filePath = MediaUtils.getFilePath(MediaUtils.tempPath + encryptedName).toString();
InputStream fis = new BufferedInputStream(url.openStream());
OutputStream fos = new FileOutputStream(filePath);
File file = new File(filePath);
byte data[] = new byte[80192];
int count;
long total = 0;
while ((count = fis.read(data)) != -1) {
total += count;
if (tamFile > 0) {
int percentage = (int) (total * 100 / tamFile);
if (percentage % 20 == 0)
callback.onDownloadProgress(percentage, position);
}
fos.write(data, 0, count);
if (canceled) {
MediaUtils.deleteFile(file);
return;
}
}
if (canceled)
return;
byte[] key = (salt + cryptPassword).getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key, 8);
SecretKeySpec sks = new SecretKeySpec(key, "DES");
Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, sks);
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
int b;
byte[] d = new byte[8192];
while ((b = fis.read(d)) != -1) {
cos.write(d, 0, b);
}
OutputStream outputEncrypted = new FileOutputStream(dir + File.separator + encryptedName);
outputEncrypted.write(d);
outputEncrypted.close();
fos.flush();
fos.close();
fis.close();
MediaUtils.deleteFile(file);//delete temp file
callback.onDownloadFinish(position);
} catch (Exception e) {
e.printStackTrace();
callback.onDownloadError(position);
}
}
This are my decryption method
#SafeVarargs
#Override
protected final File doInBackground(HashMap<String, Object>... params) {
String path = (String) params[0].get(FILE_PATH);
String fileName = String.valueOf(params[0].get(FILE_NAME));
boolean encrypted = (boolean) params[0].get(ENCRYPTED);
File root = android.os.Environment.getExternalStorageDirectory();
File dir = new File(root.getAbsolutePath() + File.separator + path + File.separator);
File file;
if (!encrypted) {
file = new File(dir + File.separator + fileName);
return file;
}
file = new File(dir + File.separator + Cypher.md5(fileName));
File tempMp3 = null;
try {
tempMp3 = File.createTempFile(TEMP, MP3, context.getCacheDir());
tempMp3.deleteOnExit();
} catch (IOException e) {
e.printStackTrace();
}
try {
FileInputStream fis = new FileInputStream(file);
byte[] key = (DownloadManager.salt + DownloadManager.cryptPassword).getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key, 8);
SecretKeySpec sks = new SecretKeySpec(key, "DES");
Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, sks);
CipherInputStream cis = new CipherInputStream(fis, cipher);
FileOutputStream fos = new FileOutputStream(tempMp3);
int b;
byte[] d = new byte[80192];
while ((b = cis.read(d)) != -1) {
fos.write(d, 0, b);
}
fos.flush();
fos.close();
cis.close();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return tempMp3;
}
You seem to have a typo in either your encrypt or decrypt method.
In encryption:
int b;
byte[] d = new byte[8192];
while ((b = cis.read(d)) != -1) {
fos.write(d, 0, b);
}
In decryption:
int b;
byte[] d = new byte[80192];
while ((b = cis.read(d)) != -1) {
fos.write(d, 0, b);
}
The byte array d in decryption is about 10x larger than the byte array in encryption.
After doing this:
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
int b;
byte[] d = new byte[8192];
while ((b = fis.read(d)) != -1) {
cos.write(d, 0, b);
}
OutputStream outputEncrypted = new FileOutputStream(dir + File.separator + encryptedName);
outputEncrypted.write(d);
outputEncrypted.close();
the outputEncrypted file will just contain the last buffer full of data. Furthermore, this data will not be encrypted.
Related
I'm getting the following error when i tried to decrypt a list of ogg files but when i try to decrypt only one it works this is my code.
for (IpstoriResponse ipstori: descargas) {
Executors.newSingleThreadExecutor().execute(() -> {
ipstori.setAudioHistory(getOfflineFile(ipstori.getAudioPath(), ipstori.getAudioCle(), ipstori.getAudioIv(), requireContext(), ipstori.getAudioCle()));
prepareList.add(...);
});
}
}
private String getOfflineFile(String input, String key, String iv, Context context, String name){
String result = null;
try {
File initialFile = new File(input);
InputStream inputStream = new FileInputStream(initialFile);
File outputDir = context.getCacheDir(); // context being the Activity pointer
File outputFile = File.createTempFile(name, ".ogg", outputDir);
FileOutputStream fos = new FileOutputStream(outputFile);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKey secretKey = makeKey(key);
IvParameterSpec ivParameterSpec = makeIv(iv);
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
CipherInputStream cipherInputStream = new CipherInputStream(inputStream, cipher);
byte[] buffer = new byte[8192];
int nread;
while ((nread = cipherInputStream.read(buffer)) > 0) {
fos.write(buffer, 0, nread);
}
fos.flush();
fos.close();
cipherInputStream.close();
result = outputFile.getPath();
tempFiles.add(result);
} catch (Exception ex) {
...
}
return result;
}
that's really weird cause when you try to decrypt only one element of the list the code works fine
I have an encrypted video with the key and I want to decrypt that video file with Key but I am not able to decrypt the video file. I try 2 3 methods but Non of these works for me.
Crypto.Class
public class Crypto {
static void fileProcessor(int cipherMode,String key,File inputFile,File outputFile){
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = new SecureRandom();
secureRandom.setSeed(key.getBytes("UTF-8"));
keyGenerator.init(128, secureRandom);
SecretKey secretKey = keyGenerator.generateKey();
// Key secretKey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(cipherMode, secretKey);
FileInputStream inputStream = null;
byte[] inputBytes = new byte[0];
try {
inputStream = new FileInputStream(inputFile);
inputBytes = new byte[(int) inputFile.length()];
inputStream.read(inputBytes);
} catch (IOException e) {
e.printStackTrace();
}
byte[] outputBytes = cipher.doFinal(inputBytes);
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(outputBytes);
inputStream.close();
outputStream.close();
} catch (NoSuchPaddingException | NoSuchAlgorithmException
| InvalidKeyException | BadPaddingException
| IllegalBlockSizeException | IOException e) {
e.printStackTrace();
}
}
public static String Decrypt(String filePath) {
String key = "my_encrypted_key";
// File inputFile = new File("text.txt");
File encryptedFile = new File(filePath);
String decryptedFilePath="";
//check special guid folder if not exist create
//get the selected video file path with settings path if exist decrypt if not exist show message
File decryptedFile = new File(decryptedFilePath);
try {
//Crypto.fileProcessor(Cipher.ENCRYPT_MODE,key,inputFile,encryptedFile);
Crypto.fileProcessor(Cipher.DECRYPT_MODE,key,encryptedFile,decryptedFile);
Log.d("success", "Decrypt: success");
return decryptedFile.getAbsolutePath();
} catch (Exception ex) {
System.out.println(ex.getMessage());
ex.printStackTrace();
}
return "";
}
}
But this does not work for me and I try another one.
public static void TEST2(String orgFile) {
try {
String password = "estudies741852963#123";
File outFile_dec = new File(Environment.getExternalStorageDirectory()+"/testVideo/abc.mp4");
if(!outFile_dec.isDirectory()) {
outFile_dec.mkdir();
}
if(!outFile_dec.exists()){
outFile_dec.createNewFile();
}
// reading the salt
// user should have secure mechanism to transfer the
// salt, iv and password to the recipient
FileInputStream saltFis = new FileInputStream(orgFile);
byte[] salt = new byte[8];
saltFis.read(salt);
saltFis.close();
// reading the iv
FileInputStream ivFis = new FileInputStream(orgFile);
byte[] iv = new byte[16];
ivFis.read(iv);
ivFis.close();
SecretKeyFactory factory = SecretKeyFactory
.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 1000,
256);
SecretKey tmp = factory.generateSecret(keySpec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
// file decryption
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
InputStream fis = new FileInputStream(orgFile);
OutputStream fos = new FileOutputStream(outFile_dec);
// byte[] in = new byte[1024];
// int read;
// while ((read = fis.read(in)) != -1) {
// byte[] output = cipher.update(in, 0, read);
// if (output != null)
// fos.write(output);
// }
//
// byte[] output = cipher.doFinal();
// if (output != null)
// fos.write(output);
// fis.close();
// fos.flush();
// fos.close();
// System.out.println("File Decrypted.");
fos = new CipherOutputStream(fos, cipher);
int count = 0;
byte[] buffer = new byte[1024];
while ((count = fis.read(buffer)) >= 0) {
fos.write(buffer, 0, count);
}
fis.close();
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
In this method, its always shows on exception saying no such directory. And I try another method also But none of these works for me.
Tried this solution to decrypt my video
Java 256-bit AES Password-Based Encryption
How do i decrypt a file in Android with AES?
I am hoping to decompress a zlib file.
Below is a picture of my original:
When byte no 4 is not equal to 0, it needs to decompress after 9th bytes.
After I decompress, I receive the following error:
"java.util.zip.DataFormatException: incorrect header check"
My code is below:
private static void writeToRawInFile(byte[] bData) {
try {
int index = 4;
byteBuffer = null;
byteBuffer = ByteBuffer.allocate(bData.length);
byteBuffer.put(bData);
byteBuffer.flip();
byte[] convertByte = byteBuffer.array();
System.out.println("Byte:" + convertByte.toString());
if (byteBuffer.get(index) == 0) {
System.out.println("index 0");
byteBuffer = null;
byteBuffer = ByteBuffer.allocate(bData.length);
byteBuffer.put(bData);
byteBuffer.flip();
//factoryType.fileServer.fc.write(byteBuffer);
} else {
//bData = Arrays.copyOfRange(bData, 1,9);
bData = decompressByteArray(Arrays.copyOfRange(bData, 0,9));
byteBuffer = ByteBuffer.allocate(bData.length);
byteBuffer.put(bData);
byteBuffer.flip();
System.out.println("data ="+ byteBuffer);
//factoryType.fileServer.fc.write(byteBuffer);
}
//factoryType.fileServer.fc.write(byteBuffer);
} catch (Exception e) {
System.out.println("expMsg .writeToRawInFile()=" + e.getMessage());
e.printStackTrace();
}
if (byteBuffer != null) {
byteBuffer.clear();
}
}
public static byte[] decompressByteArray(byte[] bytes) throws IOException, DataFormatException {
Inflater inflater = new Inflater();
System.out.println("Original: " + bytes.length);
inflater.setInput(bytes);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(bytes.length);
byte[] buffer = new byte[1024];
while (!inflater.finished()) {
int count = inflater.inflate(buffer);
outputStream.write(buffer, 0, count);
}
outputStream.close();
byte[] output = outputStream.toByteArray();
System.out.println("Compressed: " + output.length);
return output;
}
First of all, if not using function decode_path , I can play .wav file with my code , and it works fine I use Jlayer and audio track to play the song.
Second, if I use function decode_path it can decode mp3 to pcm file , and pass the byte[] to function PlayAudioTrack, and let it play.
The quesion is,I don't know where my code is wrong , I use 320Kbps, 44.1Khz stereo type, Layer3 mp3, but the AudioTrack plays noise but no music~!!!!
can anyone ?
???
My code
public void PlayAudioTrack(String filePath) throws IOException{
int intSize = android.media.AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_CONFIGURATION_STEREO,
AudioFormat.ENCODING_PCM_16BIT);
AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_STEREO,
AudioFormat.ENCODING_PCM_16BIT, intSize, AudioTrack.MODE_STREAM);
//Reading the file..
int count = 512 * 1024; // 512 kb
// byte[] byteData = null;
// byteData = new byte[(int)count];
//we can decode correct byte data here
byte[] byteData = null;
byteData = decode_path(filePath, 0, 20000);
File file = null;
file = new File(filePath);
FileInputStream in = null;
try {
in = new FileInputStream( file );
} catch (FileNotFoundException e) {
e.printStackTrace();
}
int bytesread = 0, ret = 0;
int size = (int) file.length();
at.play();
while (bytesread < size) {
Log.e("devon","write byte array with sizes");
ret = in.read( byteData,0, count);
if (ret != -1) {
Log.e("devon","Write the byte array to the track");
at.write(byteData,0, ret);
bytesread += ret;
}else break;
}
at.stop();
at.release();
}
public static byte[] decode_path(String path, int startMs, int maxMs)
throws IOException{
ByteArrayOutputStream outStream = new ByteArrayOutputStream(1024);
float totalMs = 0;
boolean seeking = true;
File file = new File(path);
InputStream inputStream = new BufferedInputStream(new FileInputStream(file), 8 * 1024);
try {
Bitstream bitstream = new Bitstream(inputStream);
Decoder decoder = new Decoder();
boolean done = false;
while (! done) {
Header frameHeader = bitstream.readFrame();
if (frameHeader == null) {
done = true;
} else {
totalMs += frameHeader.ms_per_frame();
if (totalMs >= startMs) {
seeking = false;
}
if (! seeking) {
SampleBuffer output = (SampleBuffer) decoder.decodeFrame(frameHeader, bitstream);
if (output.getSampleFrequency() != 44100
|| output.getChannelCount() != 2) {
throw new IllegalArgumentException("mono or non-44100 MP3 not supported");
}
short[] pcm = output.getBuffer();
for (short s : pcm) {
outStream.write(s & 0xff);
outStream.write((s >> 8 ) & 0xff);
}
}
if (totalMs >= (startMs + maxMs)) {
done = true;
}
}
bitstream.closeFrame();
}
return outStream.toByteArray();
} catch (BitstreamException e) {
throw new IOException("Bitstream error: " + e);
} catch (DecoderException e) {
Log.w(TAG, "Decoder error", e);
throw new IOException("Decoder error: " + e);
}
}
public void PlayAudioTrack(String filePath) throws IOException{
int intSize = android.media.AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_CONFIGURATION_STEREO,
AudioFormat.ENCODING_PCM_16BIT);
AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_STEREO,
AudioFormat.ENCODING_PCM_16BIT, intSize, AudioTrack.MODE_STREAM);
//Reading the file..
int count = 512 * 1024; // 512 kb
// byte[] byteData = null;
// byteData = new byte[(int)count];
//we can decode correct byte data here
byte[] byteData = null;
byteData = decode_path(filePath, 0, 20000);
int temp =0;
at.play();
while (temp<byteData.length)
{
at.write(byteData, temp, count);
temp+= count;
}
at.stop();
at.release();
}
The functions I'm using to convert the file to a string and then to an mdf are below. I'm outputting the file paths and file names to make sure everything is cool. Is there anything I'm not considering that could change the file's (a video mp4 actually) fingerprint? I'm checking it against md5sum on ubuntu.
private static String readFileToString(String filePath)
throws java.io.IOException{
StringBuffer fileData = new StringBuffer(1000);
BufferedReader reader = new BufferedReader(
new FileReader(filePath));
char[] buf = new char[1024];
int numRead=0;
while((numRead=reader.read(buf)) != -1){
String readData = String.valueOf(buf, 0, numRead);
fileData.append(readData);
buf = new char[1024];
}
reader.close();
System.out.println(fileData.toString());
return fileData.toString();
}
public static String getMD5EncryptedString(String encTarget){
MessageDigest mdEnc = null;
try {
mdEnc = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
System.out.println("Exception while encrypting to md5");
e.printStackTrace();
} // Encryption algorithm
mdEnc.update(encTarget.getBytes(), 0, encTarget.length());
String md5 = new BigInteger(1, mdEnc.digest()).toString(16) ;
return md5;
}
String isn't a container for binary data. Lose the two conversions between byte array and String. You should be reading the file as bytes and computing the MD5 directly in the bytes. You can do that while you're reading it: you don't need to read the entire file first.
And MD5 isn't an encryption: it's a secure hash.
Found this answer here: How to generate an MD5 checksum for a file in Android?
public static String fileToMD5(String filePath) {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(filePath);
byte[] buffer = new byte[1024];
MessageDigest digest = MessageDigest.getInstance("MD5");
int numRead = 0;
while (numRead != -1) {
numRead = inputStream.read(buffer);
if (numRead > 0)
digest.update(buffer, 0, numRead);
}
byte [] md5Bytes = digest.digest();
return convertHashToString(md5Bytes);
} catch (Exception e) {
return null;
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (Exception e) { }
}
}
}
private static String convertHashToString(byte[] md5Bytes) {
String returnVal = "";
for (int i = 0; i < md5Bytes.length; i++) {
returnVal += Integer.toString(( md5Bytes[i] & 0xff ) + 0x100, 16).substring(1);
}
return returnVal;
}