Reading from an encrypted file into a declared string variable - java

I have an encrypted file that was done using reference from this question .I got the file encrypted.Now my issue is when trying to read the contents out, am getting an empty strings from the returned read(). Below is my call method and the method to decrypt the encrypted text to a string variable.
Calling Method:
File encryptedCFG = new File(homeDir + "/" + folder_name + "/twCGF.txt");
dc.ReadEncryptedFile(encryptedCFG);
Method:
public void ReadEncryptedFile(File deInFile) {
try {
FileInputStream fis = new FileInputStream(deInFile);
int length = (int) deInFile.length();
byte[] filebyte = new byte[length]
// Decrypt the byte contents from the file using the cipher setup
byte[] tmpTxT = mDecipher.doFinal(filebyte);
fis.read(tmpTxT);
fis.close();
// Read into a string since we got the contents
String plaintxt = new String(tmpTxt, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
}
Any pointers why am not getting the contents of the encrypted file correctly?

At the line where you're decrypting the byte array, it's still empty. You haven't read the file in, yet. You have to switch the operations.
byte[] filebyte = new byte[length]
fis.read(filebyte);
byte[] tmpTxt = mDecipher.doFinal(filebyte);
fis.close();
String plaintxt = new String(tmpTxt, "UTF-8");

Related

How to convert String variable back in byte[] in JAVA [duplicate]

This question already has answers here:
How to convert Java String into byte[]?
(9 answers)
Closed 4 years ago.
I have the following code to zip and unzip the String:
public static void main(String[] args) {
// TODO code application logic here
String Source = "hello world";
byte[] a = ZIP(Source);
System.out.format("answer:");
System.out.format(a.toString());
System.out.format("\n");
byte[] Source2 = a.toString().getBytes();
System.out.println("\nsource 2:" + Source2.toString() + "\n");
String b = unZIP(Source2);
System.out.println("\nunzip answer:");
System.out.format(b);
System.out.format("\n");
}
public static byte[] ZIP(String source) {
ByteArrayOutputStream bos= new ByteArrayOutputStream(source.length()* 4);
try {
GZIPOutputStream outZip= new GZIPOutputStream(bos);
outZip.write(source.getBytes());
outZip.flush();
outZip.close();
} catch (Exception Ex) {
}
return bos.toByteArray();
}
public static String unZIP(byte[] Source) {
ByteArrayInputStream bins= new ByteArrayInputStream(Source);
byte[] buf= new byte[2048];
StringBuffer rString= new StringBuffer("");
int len;
try {
GZIPInputStream zipit= new GZIPInputStream(bins);
while ((len = zipit.read(buf)) > 0) {
rString.append(new String(buf).substring(0, len));
}
return rString.toString();
} catch (Exception Ex) {
return "";
}
}
When "Hello World" have been zipped, it's will become [B#7bdecdec in byte[] and convert into String and display on the screen. However, if I'm trying to convert the string back into byte[] with the following code:
byte[] Source2 = a.toString().getBytes();
the value of variable a will become to [B#60a1807c instead of [B#7bdecdec . Does anyone know how can I convert the String (a value of byte but been convert into String) back in byte[] in JAVA?
Why doing byte[] Source2 = a.toString().getBytes(); ?
It seems like a double conversion; you convert a byte[] to string the to byte[].
The real conversion of a byte[] to string is new String(byte[]) hoping that you're in the same charset.
Source2 should be an exact copy of a hence you should just do byte[] Source2 = a;
Your unzip is wrong because you are converting back a string which might be in some other encoding (let's say UTF-8):
public static String unZIP(byte[] source) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream(source.length*2);
try (ByteArrayInputStream in = new ByteArrayInputStream(source);
GZIPInputStream zis = new GZIPInputStream(in)) {
byte[] buffer = new buffer[4096];
for (int n = 0; (n = zis.read(buffer) != 0; ) {
bos.write(buffer, 0, n);
}
}
return new String(bos.toByteArray(), StandardCharsets.UTF_8);
}
This one, not tested, will:
Store byte from the gzip stream into a ByteArrayOutputStream
Close the gzip/ByteArrayInputStream using try with resources
Convert the whole into a String using UTF-8 (you should always use encoding and unless rare case, UTF-8 is the way to go).
You must not use StringBuffer for two reasons:
The most important one: this will not behave well with multi bytes string such as UTF-8 or UTF-16.
And second, StringBuffer is synchronized: you should use StringBuilder whenever possible and whenever it should be used (eg: not here!). StringBuffer should be reserved for case where your share the StringBuffer with several threads, otherwise it is useless.
With those change, you will also need to change the ZIP as per David Conrad comment and because the unZIP use UTF-8:
public static byte[] ZIP(String source) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream(source.length()* 4);
try (GZIPOutputStream zip = new GZIPOutputStream(bos)) {
zip.write(source.getBytes(StandardCharsets.UTF_8));
}
return bos.toByteArray();
}
As for the main, printing a byte[] will result in the default toString.

What is the best way to calculate a checksum for a Java class?

I have an application where I am generating a "target file" based on a Java "source" class. I want to regenerate the target when the source changes. I have decided the best way to do this would be to get a byte[] of the class contents and calculate a checksum on the byte[].
I am looking for the best way to get the byte[] for a class. This byte[] would be equivalent to the contents of the compiled .class file. Using ObjectOutputStream does not work. The code below generates a byte[] that is much smaller than the byte contents of the class file.
// Incorrect function to calculate the byte[] contents of a Java class
public static final byte[] getClassContents(Class<?> myClass) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
try( ObjectOutputStream stream = new ObjectOutputStream(buffer) ) {
stream.writeObject(myClass);
}
// This byte array is much smaller than the contents of the *.class file!!!
byte[] contents = buffer.toByteArray();
return contents;
}
Is there a way to get the byte[] with the identical contents of the *.class file? Calculating the checksum is the easy part, the hard part is obtaining the byte[] contents used to calculate an MD5 or CRC32 checksum.
THis is the solution that I ended up using. I don't know if it's the most efficient implementation, but the following code uses the class loader to get the location of the *.class file and reads its contents. For simplicity, I skipped buffering of the read.
// Function to obtain the byte[] contents of a Java class
public static final byte[] getClassContents(Class<?> myClass) throws IOException {
String path = myClass.getName().replace('.', '/');
String fileName = new StringBuffer(path).append(".class").toString();
URL url = myClass.getClassLoader().getResource(fileName);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
try (InputStream stream = url.openConnection().getInputStream()) {
int datum = stream.read();
while( datum != -1) {
buffer.write(datum);
datum = stream.read();
}
}
return buffer.toByteArray();
}
I don't get what you means, but i think you are looking for this, MD5.
To check MD5 of a file, you can use this code
public String getMd5(File file)
{
DigestInputStream stream = null;
try
{
stream = new DigestInputStream(new FileInputStream(file), MessageDigest.getInstance("MD5"));
byte[] buffer = new byte[65536];
read = stream.read(buffer);
while (read >= 1) {
read = stream.read(buffer);
}
}
catch (Exception ignored)
{
int read;
return null;
}
return String.format("%1$032x", new Object[] { new BigInteger(1, stream.getMessageDigest().digest()) });
}
Then, you can store the md5 of a file in any way for exmaple XML. An exmaple of MD5 is 49e6d7e2967d1a471341335c49f46c6c so once the file name and size change, md5 will change. You can store md5 of each file in XML format and next time your run a code to check md5 and compare the md5 of each file in the xml file.
If you really want the contents of the .class file, you should read the contents of .class file, not the byte[] representation that is in memory. So something like
import java.io.*;
public class ReadSelf {
public static void main(String args[]) throws Exception {
Class classInstance = ReadSelf.class;
byte[] bytes = readClass(classInstance);
}
public static byte[] readClass(Class classInstance) throws Exception {
String name = classInstance.getName();
name = name.replaceAll("[.]", "/") + ".class";
System.out.println("Reading this: " + name);
File file = new File(name);
System.out.println("exists: " + file.exists());
return read(file);
}
public static byte[] read(File file) throws Exception {
byte[] data = new byte[(int)file.length()]; // can only read a file of size INT_MAX
DataInputStream inputStream =
new DataInputStream(
new BufferedInputStream(
new FileInputStream(file)));
int total = 0;
int nRead = 0;
try {
while((nRead = inputStream.read(data)) != -1) {
total += nRead;
}
}
finally {
inputStream.close();
}
System.out.println("Read " + total
+ " characters, which should match file length of "
+ file.length() + " characters");
return data;
}
}

When Decrypting Image, gives javax.crypto.BadPaddingException: pad block corrupted Android

Hi i'm new to android and Image encryption.
My scenario is like this,
first I'm encrypting the image file.
Then I'm uploading it to the Server
From my app I'm downloading encrypted image and saving it in SD card.
then I'm decrypting it before set it to the imageView
(See bottom for all need methods I have used..)
But I'm getting javax.crypto.BadPaddingException: pad block corrupted when decrypting. I read some articles about this exception but all are about text encryption. Can you help me to avoid this. Thank you in advance
Image Encrption using ...
private byte[] encrypt(byte[] raw, byte[] clear) throws Exception
{
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
Here I'm saving several other images as well, all saved in sd card successfully...
for (int i = 0; i < imageUrls.size(); i++)
{
File file = new File(imageUrls.get(i));
String metapath = CommonUtils.getDataFromPreferences("metaPath", "");
Log.d("metapath", metapath);
String extStorageDirectory = metapath + file.getName();
File wallpaperDirectory = new File(extStorageDirectory);
if (!wallpaperDirectory.exists() || wallpaperDirectory.length() == 0)
{
new DownloadImagesTask()
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, imageUrls.get(i));
}
}
Toast toast = Toast.makeText(ScratchDetailsActivity.this, "Lottery was purchased and saved to sdcard/E-Lottery",
Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
Image decryption...
decrypt the file here first argument is key and second is encrypted file which we get from SD card.
decrpt = simpleCrypto.decrypt(KEY, getImageFileFromSdCard());
bmpimg2 = BitmapFactory.decodeByteArray(decrpt, 0, decrpt.length);
Drawable d = new BitmapDrawable(getResources(), bmpimg2);
hiddenImage.setImageDrawable(d);
DownloadImageTask..
public class DownloadImagesTask extends AsyncTask<String, Void, InputStream>{
private String fileName;
#Override
protected InputStream doInBackground(String... urls)
{
//Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
return download_Image(urls[0]);
}
#Override
protected void onPostExecute(InputStream result)
{
storeImage(result);
}
private InputStream download_Image(String url)
{
InputStream is = null;
File file = new File(url);
fileName = file.getName();
try
{
URL aURL = new URL(url);
URLConnection conn = aURL.openConnection();
conn.connect();
is = conn.getInputStream();
}
catch (OutOfMemoryError e)
{
Log.e("Hub", "Error getting the image from server : " + e.getMessage().toString());
}
catch (IOException e)
{
Log.e("Hub", "Error getting the image from server : " + e.getMessage().toString());
}
return is;
}
public void storeImage(InputStream is)
{
String extStorageDirectory = CommonUtils.getDataFromPreferences("metaPath", "");
Log.d("extStorageDirectory", extStorageDirectory);
OutputStream outStream = null;
File wallpaperDirectory = new File(extStorageDirectory);
if (!wallpaperDirectory.exists())
{
wallpaperDirectory.mkdirs();
}
File outputFile = new File(wallpaperDirectory, fileName);
if (!outputFile.exists() || outputFile.length() == 0)
{
try
{
outStream = new FileOutputStream(outputFile);
}
catch (FileNotFoundException e1)
{
e1.printStackTrace();
}
try
{
int bytesRead = -1;
byte[] buffer = new byte[4096];
while ((bytesRead = is.read(buffer)) != -1)
{
outStream.write(buffer, 0, bytesRead);
}
outStream.close();
is.close();
Log.d("ScratchActivtiy", "Image Saved");
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}}
getImageFileFromSDCard method
/**
* This method fetch encrypted file which is save in sd card and convert it in byte array after that this file will
* be decrept.
*
* #return byte array of encrypted data for decription.
* #throws FileNotFoundException
*/
public byte[] getImageFileFromSdCard() throws FileNotFoundException
{
byte[] inarry = null;
try
{
String metapath = CommonUtils.getDataFromPreferences("metaPath", "");
File imageFolder = new File(metapath);
File urlFile = new File(selectedLottery.getImage());
for (File f : imageFolder.listFiles())
{
if (urlFile.getName().equals(f.getName()))
metapath = metapath + f.getName();
}
File imageFile = new File(metapath);
//Convert file into array of bytes.
FileInputStream fileInputStream = null;
byte[] bFile = new byte[(int) imageFile.length()];
fileInputStream = new FileInputStream(imageFile);
fileInputStream.read(bFile);
fileInputStream.close();
inarry = bFile;
}
catch (IOException e)
{
Log.d("Exception", e.getMessage());
}
return inarry;
}
There are a lot of things that might cause a Bad Padding exception. Obvious things to check are that for both encryption and decryption you are using:
the same key, that is byte-for-byte the same.
the same encryption mode (CBC, CTR or GCM usually).
the same IV/Nonce, again byte-for-byte the same.
the same padding (PKCS5 or PKCS7 are common).
Do not rely on system defaults, especially when encrypting on one system and decrypting on another, as you seem to be doing. If the system defaults are different, then your decryption will fail. Always explicitly set key, mode, IV and padding. There will be documented ways to do so in any reasonable crypto library.
If that doesn't solve it then you will need to do a bit more digging. Set the decryption method temporarily to NoPadding or whatever equivalent your library uses. That will let the decryption method ignore padding errors, and give you some output. Have a look at the output and compare it to the original input; you may have to look at hex dumps here to be sure what is happening.
Among the possibilities are:
the output is complete garbage: your key is wrong, or the IV/Nonce
is wrong for a stream cypher or GCM mode or CTR mode.
the first block is garbage with the rest matching the plaintext: you
have the wrong IV in CBC mode.
the output matches with some extra stuff at the end: the extra stuff
is padding. Set your decryption method to expect that type of
padding.
If none of these happen, then ask again here, describing the symptoms.
When you have got a solution, you must set your decryption method back to expect the correct padding. Leaving it set to NoPadding is not secure since any old garbage can be added to the decrypted plaintext.

DES encrypt/decrypt from a file

I am writting a program where I take a string, encrypt it and then write it in a file. Then later, I read from the file the string, decrypt it and then modify it. Here's my code for DES encryption/decryption:
/* class for crypting and decrypting a file */
class DESEncrypter
{
private Cipher encryptionCipher;
private Cipher decryptionCipher;
public DESEncrypter (SecretKey key) throws Exception
{
encryptionCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
encryptionCipher.init(Cipher.ENCRYPT_MODE, key);
decryptionCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
decryptionCipher.init(Cipher.DECRYPT_MODE, key);
}
/* write to 'out' the encryption of the information read from 'in' */
public String encrypt(String unencryptedString)
{
String encryptedString = "";
try {
byte[] unencryptedByteArray = unencryptedString.getBytes("UTF8");
byte[] encryptedBytes = this.encryptionCipher.doFinal(unencryptedByteArray);
encryptedString = new sun.misc.BASE64Encoder().encode(encryptedBytes);
} catch (Exception ex) {
Logger.getLogger(DESEncrypter.class.getName()).log(Level.SEVERE, null, ex);
}
return encryptedString;
}
private static String bytes2String(byte[] bytes)
{
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < bytes.length; i++)
{
stringBuffer.append((char) bytes[i]);
}
return stringBuffer.toString();
}
/* write to 'out' the information obtained by decrypting the information read from 'in' */
public String decrypt (String encryptedString) throws UnsupportedEncodingException
{
byte[] unencryptedByteArray = new byte[4096];
try {
// Encode bytes to base64 to get a string
byte[] decodedBytes = new sun.misc.BASE64Decoder().decodeBuffer(encryptedString);
// Decrypt
unencryptedByteArray = this.decryptionCipher.doFinal(decodedBytes);
} catch (Exception ex) {
Logger.getLogger(DESEncrypter.class.getName()).log(Level.SEVERE, null, ex);
}
return bytes2String(unencryptedByteArray);
}
}
And this is the function where I write a encrypted String in a file:
public void writeToFileEncrypted(String filename, String owner, String departament)
{
try
{
BufferedReader br = new BufferedReader(new FileReader(new File("files_encrypted")));
String crypt = "";
String aux;
while ((aux = br.readLine()) != null)
{
crypt += aux;
}
br.close();
String info = this.server.crypt.decrypt(crypt);
info += filename + " " + owner + " " + departament + "\n";
/* delete the old encryption */
File temp = new File("files_encrypted");
temp.delete();
String infoCrypt = this.server.crypt.encrypt(info);
File newFiles = new File("files_encrypted");
if (newFiles.createNewFile() == false)
{
log.severe("Failed to re-create the 'files_encrypted' file when trying to add a new file");
return;
}
BufferedWriter bw = new BufferedWriter(new FileWriter(newFiles));
bw.write(infoCrypt);
bw.close();
}
catch (Exception e)
{
log.warning("An exception was caught while trying to remove '" + clientName + "' from the banned list");
e.printStackTrace();
return;
}
}
While the server runs, I can make modification to that String from file(run that function many time). The problem is when I close the server and then I open it again because I get the error:
javax.crypto.BadPaddingException: Given final block not properly padded
This is how I read from file when the server opens:
BufferedReader br = new BufferedReader(new FileReader(new File("files_encrypted")));
String crypto = new String();
String aux;
while ((aux = br.readLine()) != null)
{
crypto += aux;
readBytes++;
}
br.close();
System.out.println(readBytes);
info = this.crypt.decrypt(crypto);
Why do I get that error? What I'm doing wrong? I must write the encrypted String in file some other way?
LATER EDIT:
I've changed the function that read a String from a file, decrypt it, modify it , encrypt it and then write it in file.
public void writeToFileEncrypted(String filename, String owner, String departament)
{
try
{
File f = new File("files_encrypted");
int nrRead = 0;
String info = null;
FileInputStream fis = new FileInputStream(f);
StringBuffer sb = new StringBuffer();
int ch;
while ((ch = fis.read()) != -1)
{
sb.append((char)ch);
nrRead++;
}
fis.close();
StringBuilder sba = null;
if (nrRead != 0)
{
info = this.server.crypt.decrypt(new String(sb.toString().getBytes("UTF-8"), "UTF-8"));
sba = new StringBuilder(info);
sba.append(filename + " " + owner + " " + departament + " ");
}
else
{
sba = new StringBuilder(filename + " " + owner + " " + departament + " ");
}
/* delete the old encryption */
File temp = new File("files_encrypted");
temp.delete();
//System.out.println("before: " + sba.toString());
String infoCrypt = this.server.crypt.encrypt(sba.toString());
//System.out.println("after: " + infoCrypt);
File newFiles = new File("files_encrypted");
if (newFiles.createNewFile() == false)
{
log.severe("Failed to re-create the 'files_encrypted' file when trying to add a new file");
return;
}
FileOutputStream fos = new FileOutputStream(newFiles);
fos.write(infoCrypt.getBytes("UTF-8"));
fos.flush();
fos.close();
}
catch (Exception e)
{
log.warning("An exception was caught while trying to remove '" + clientName + "' from the banned list");
e.printStackTrace();
return;
}
}
I've also modified where I read the info from file when server opens for the first time:
FileInputStream fis = new FileInputStream(f);
StringBuffer sb = new StringBuffer();
int ch;
while ((ch = fis.read()) != -1)
{
sb.append((char)ch);
readBytes++;
}
fis.close();
if (readBytes != 0)
{
System.out.println("on: " + sb.toString());
info = this.crypt.decrypt(new String(sb.toString().getBytes("UTF-8"), "UTF-8"));
System.out.println("load: " + info);
}
}
At the System.out.println with "on: " what I read from file is exactly what I've written encrypted, without any spaces or new lines. If I read with read(buffer), where buffer is byte[], it seems that adds a lot of spaces.
Although I've made all this modifications I still get the error javax.crypto.BadPaddingException: Given final block not properly padded
Has somebody any idea what's going on here?
There are a few things here.
private static String bytes2String(byte[] bytes)
Is dodgy, you are casting a byte to a char in this method so there is no character encoding specified here. To convert bytes to characters you should just use the String constructor that takes an array of bytes and an encoding. e.g.
byte[] tmp = new byte[10];
String a = new String(tmp, "UTF-8");
Be careful using BufferedReaders + .readLine() - this will strip out any newline characters from your file as you read it unless you add them back into your buffer. Although I don't think this is your problem.
But I think the best way to simplify your code is to write the encoded bytes via an OutputStream directly to the file. Unless you need to send the contents of the file over a transport that doesn't like binary data, there is no need to base64 encode. Just use Input/OutputStreams to write the encrypted bytes direct to disk.
RESPONSE TO LATER EDIT:
You are still mixing up your use of binary data (bytes) and character data (String/chars). You can't do things like:
int ch;
while ((ch = fis.read()) != -1)
{
sb.append((char)ch);
The input stream is retuning bytes, a byte is not a character and just casting it to one is going to cause problems. When using encryption the output from the encryption operation is binary data, and the input to the decryption operation is also binary data. The fact that your are encrypting text is something you deal with before the encryption occurs, and after the decryption occurs. You basic operation should go along the following lines.
Take the text you want to encrypt and convert it to bytes, specifying an encoding using the .getBytes(String charsetName) on your String.
Pass these bytes into your encryption routine
Write the resulting bytes directly to disk
To decrypt:
Read the bytes from the file
Pass the bytes to your decryption routine (as bytes! no Strings/ text involved)
Take the out put bytes and re-construct you String using new String(byte[] bytes, String charsetName) specifying the same encoding as before.
You might find the following (untested, but should work) methods useful:
public byte[] readBinaryFile(File f) throws IOException
{
byte[] contents = new byte[(int)f.length()];
BufferedInputStream bis = null;
try
{
bis = new BufferedInputStream(new FileInputStream(f));
DataInputStream dis = new DataInputStream(bis);
dis.readFully(contents);
}
finally
{
if(bis != null)
{
bis.close();
}
}
return contents;
}
public void writeBinaryFile(byte[] contents, File f) throws IOException
{
BufferedOutputStream bos = null;
try
{
bos = new BufferedOutputStream(new FileOutputStream(f));
bos.write(contents);
}
finally
{
if(bos != null)
{
bos.close();
}
}
}
So you will also need to change the interface, and internals of your encrypt and decrypt methods so they take and return byte arrays, and ditch the base64 encoding.
You have several problems. The reading and decrypting process should be symmetric with the encrypting and writing process. But
you transform your String into a byte[] using getBytes("UTF8"), which is fine, but you don't use new String(byte[], "UTF8") to do the reverse operation.
you write a whole String to a file, including potential line breaks, but you read it line by line and concatenate each line, thus losing the line breaks in the process. You must read each and every char that has been written.
Also, relying on undocumented, unsupported classes like sun.misc.Base64Encoder/Decoder shouldn't be done. Use Apache commons-codec to find a documented Base64 encoding, guaranteed to still be there when the next JDK comes out, and which can be used on every JVM, including non-Sun JVMs.
I think it is in the initialization
SecureRandom sr = new SecureRandom();
cipher.init( Cipher.DECRYPT_MODE, desKey ,sr);
Not sure this is the primary problem, but when you return the decrypted String from decrypt(), you should be using:
return new String(unencryptedByteArray, "UTF-8");

Why are my two MD5 hashing methods producing different hashes?

I'm new to java and really need some help. I created a command line tool in order to get an MD5 hash of a file. This worked so I then tailored my code to put it in GUI form. The two programs give different hashes of the same file which is confusing. I have looked into UTF-8 but as far as I can tell that would only work for strings and not a file instance. Can anyone tell me why they are providing different hash values and point me in the right direction?
First method (command line)...
public static void main(String args[]) throws IOException, NoSuchAlgorithmException {
System.out.println("Please enter file path: \n");
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
String dir = stdin.readLine();
File file = new File(dir);
FileInputStream iStream = null;
try {iStream = new FileInputStream(file);}
catch (FileNotFoundException e) {
String MD5Output = "There has been an error: " + e.toString();
}
byte[] dataBytes = new byte[1024];
MessageDigest md = MessageDigest.getInstance("MD5");
int numRead = iStream.read(dataBytes);
md.update(dataBytes, 0, numRead);
iStream.close();
dataBytes = md.digest();
md.update(dataBytes);
System.out.println("MD5: " + new BigInteger(1, md.digest()).toString(16));
}
Second method (built for gui)...
public void doMD5() throws IOException, NoSuchAlgorithmException {
File file = new File(jTxtMD51.getText());
FileInputStream iStream = null;
try {iStream = new FileInputStream(file);}
catch (FileNotFoundException e) {
String MD5Output = "There has been an error: " + e.toString();
}
byte[] dataBytes = new byte[1024];
MessageDigest md = MessageDigest.getInstance("MD5");
int numRead = iStream.read(dataBytes);
md.update(dataBytes, 0, numRead);
iStream.close();
byte[] MD5checksum = md.digest();
md.update(dataBytes);
BigInteger bigInt = new BigInteger(1, md.digest());
String MD5Hash = bigInt.toString(16);
jTextOutput.append("MD5 is : " + MD5Hash);
}
you only make one read call from the stream. you need to loop when reading an InputStream (assuming you want to read the whole thing, which you generally want). additionally, you seem to make 2 calls to digest.update() using the same bytes.
also, typically when a hash value is printed, since it is a binary value, it is printed using base64 encoding.
In addition to #jtahlborn's comment, you don't need the md.update(databytes); call in both methods, and your second method should have this at the end:
BigInteger bigInt = new BigInteger(1, MD5checksum);
You first method doesn't do this second call to digest(), whose values changes when you make the call to update()

Categories