input for md5 hashfunction in file checksum application - java

I understand md5 is mostly used for file checksum and we can use following code in java to generate md5 digest.
MessageDigest md = MessageDigest.getInstance("MD5");
try (InputStream is = Files.newInputStream(Paths.get("file.txt"))) {
DigestInputStream dis = new DigestInputStream(is, md);
/* Read stream to EOF as normal... */
}
byte[] digest = md.digest();
But I'd like to know what exactly is the input of the md function? the meta data of file or the text in file?

The input is the text in the file.

Related

Use of a one-way hash without a salt while fixing Download of code without Integrity check issue Checkmarx

I am trying to load some library ".so" / ".dll" files using below code
System.load("some file");
then after performing Static application security testing (SAST) using checkmarx tool
it is complaining Download of Code Without Integrity Check issue.
then I tried to fix the Download of Code Without Integrity Check SAST issue using checksum
I generated a library file checksum using a sha-512 algorithm and kept it in a String constant
public static final String TRUSTED_SHA512 = "12af30d9ffc1cdd85d21e73c8c81b7c379a9b4ab2ea5676cd9d232788e2b44fbab876796104f37d0f6a5f7bc5f97eb3663e432785b94039b5320bbfac3d19516";
now before loading the file, I am computing hash again with the same algorithm and checking it against String constant TRUSTED_SHA512
MessageDigest md = MessageDigest.getInstance("SHA-512");
String sha512ofQrcToolsWrapper = ChecksumHelper.getFileChecksum(md,temp);
if(sha512ofQrcToolsWrapper.equalsIgnoreCase(ServiceConstants.TRUSTED_SHA512_OF_QRCTOOLSWRAPPER)) {
System.load(temp.getAbsolutePath());
}else{
throw new Exception("failed to load windows dll file : Checksum mismatched");
}
Now checkmarx tool is giving one more issue Use of a one-way hash without a salt
then i updated message digest with static salt value. The
reason behind using fix salt value instead of random value is that we want to compute same hash at runtime to check with the one already there in constant
public static String getFileChecksum(MessageDigest digest, File file) throws IOException, NoSuchAlgorithmException {
//Get file input stream for reading the file content
FileInputStream fis = new FileInputStream(file);
//Create byte array to read data in chunks
byte[] byteArray = new byte[1024];
int bytesCount = 0;
//Read file data and update in message digest
while ((bytesCount = fis.read(byteArray)) != -1) {
digest.update(byteArray, 0, bytesCount);
}
//Static salt value
digest.update(getSalt());
//close the stream; We don't need it now.
fis.close();
//Get the hash's bytes
byte[] bytes = digest.digest();
//This bytes[] has bytes in decimal format;
//Convert it to hexadecimal format
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
}
//return complete hash
return sb.toString();
}
NOTE "getSalt() method is returning byte array with fixed values"
Still, checkmarx SAST is complaining both the issues
Download of code without Integrity check
Use of a one-way hash without a salt
please provide solution to fix these issues. let me know if anything else needed to clarify.
Thanks in advance

Java compare md5 with another md5 from another generator : not same value [duplicate]

This question already has answers here:
Getting a File's MD5 Checksum in Java
(22 answers)
Closed 2 years ago.
I can generate md5 with this function :
private void generateMd5() throws NoSuchAlgorithmException, IOException {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hash = md.digest(pathFile.getBytes());
nomGestionnaire.setText(String.valueOf(String.format("%032X", new BigInteger(1, hash))));
}
My problem is when I compare my md5 generate with another md5 generator I don't have the same value.
Is it normal ? It's like my generator doesn't generate a real md5 ?
Test with this file : aaa.txt (content : aaa)
My generator : A4FA953DB4BC7772E5AF67BD706B9110
other generator : 47bce5c74f589f4867dbd57e9ca9f808
EDIT :
FileChooser fileChooser = new FileChooser();
File selectedFile = new
File(String.valueOf(fileChooser.showOpenDialog(primaryStage)));
nameFile = selectedFile.getName();
pathFile = selectedFile.getPath();
I guess there's some error on the input. Unfortunately the and file you provided is not complete. So I did I first wrote a Java method that does a basic md5. Then I did some forensics to guess and fix the code. Both deliver correct MD5: 47BCE5C74F589F4867DBD57E9CA9F808
public static String getMD5(String filename)
throws NoSuchAlgorithmException, IOException {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(Files.readAllBytes(Paths.get(filename)));
byte[] digest = md.digest();
String myChecksum = DatatypeConverter.printHexBinary(digest).toUpperCase();
return myChecksum;
}
public static String generateMd5(String pathToFile) throws NoSuchAlgorithmException, IOException {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hash = md.digest(Files.readAllBytes(Paths.get(pathToFile)));
return String.valueOf(String.format("%032X", new BigInteger(1, hash)));
}
I faced this problem before, it is probably an encoding problem (from that file path).
I put it like this in my project, and it's working just fine since then.
I'll provide you with a sample, so probably you get an idea from this:
public String hash(String stringToHash){
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
// here you init the message digit singleton with the wanted algorithm
messageDigest.update(stringToHash.getBytes());
//now you updated it, with the bytes of your string
byte[] digest = messageDigest.digest();
String result = DatatypeConverter.printHexBinary(digest);
// finally you converted the result (hex) to String (you hashed string)
// you may want to use toLowerCase() so you make it case insensitive
return result;
}
NOTE: you have many way to hash using md5, I really prefer using the Apache Commons as an easy way, you may want to check this out MD5 Hashing using Apache Commons.
You also can do that using Google Guava : MD5 Hashing using Google Guava.

Writing CipherInputStream to a text file

I'm trying to decrypt an encrypted data which is stored in a text file. I use the same key and IV to encrypt and decrypt, and transfer it via configuration file.
When I print CipherInputStream to the console I do get some content, but when I try to write it to a text file I don't get any content in it.
This is the piece of code refferes to my problem:
File encryptedData = new File("C:\\Users\\Victoria\\Desktop\\encryptedData.txt");
File decryptedData = new File("C:\\Users\\Victoria\\Desktop\\decryptedData.txt");
FileInputStream inputStream = new FileInputStream(encryptedData);
byte[] inputBytes = new byte[(int) decryptedData.length()];
inputStream.read(inputBytes);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, newkey, newiv, SecureRandom.getInstance("SHA1PRNG"));
CipherInputStream cipherInputStream = new CipherInputStream(inputStream, cipher);
FileOutputStream outputStream = new FileOutputStream(decryptedData);
System.out.println("cipherInputStream: " + cipherInputStream);
// Writing the decrypted content to an output file
byte[] buff = new byte[1024 * 10];
int length;
while ((length = cipherInputStream.read(buff)) > 0) {
outputStream.write(buff, 0, length);
}
bufin.close();
outputStream.close();
cipherInputStream.close();
Any solutions?
Thank you!
Encrypted data which is stored in a text file
This is already a contradiction in terms. Encrypted data is binary, not text, and should not be stored in files with the .txt extension.
byte[] inputBytes = new byte[(int) decryptedData.length()];
This line of code is meaningless. You don't yet know how long the decrypted data will be. The decrypted file may not even exist, in which case this will produce a zero length array; or it may be different from what is about to be produced, in which case it is the wrong length.
inputStream.read(inputBytes);
Remove this line and the one before it.
It reads into an array which is at best sized to the size of the decrypted data, which is the wrong size for encrypted data, and at worst is just the wrong size, or even zero length, as shown above.
It reads the input probably until that wrongly sized buffer is full, and you then (a) completely ignore the data read and (b) attempt to read the same stream further, which will fail in the decryption loop, or at best produce incorrect output, as you may not be decrypting all the data.
When I print CipherInputStream to the console I do get some content
No you don't. You get a piece of data of the general form CipherInputStream#0011223344, which is just the result of calling CipherInputStream.toString(), which does not contain any 'content'.

A string encrypted (AES) after decryption prints the same value , but false on equals()

My program sends a string encrypted (AES) with received session key to Client to prove the key is correct.
Client should decrypt it, get the string and verify it with original one.
Program works fine. It encrypts and decrypts the string. It prints the string I need, but gives me false when I do String.equals(string).
I can figure out why.
There is the encryption part of my code:
// ----create a challenge for Client (to check if the session key is correct)--------
public void sessionKeyVer(String challenge, File out) throws Exception{
aesCipher.init(Cipher.ENCRYPT_MODE, aeskeySpec); // switching mode for encryption
CipherOutputStream os = new CipherOutputStream(new FileOutputStream(out), aesCipher); //output stream to another file
os.write(challenge.getBytes("UTF-8"));// function to copy String to outputstream
os.close(); //close the stream
}
There is the decryption part:
public boolean sessionKeyVer(File file) throws Exception{
aesCipher.init(Cipher.DECRYPT_MODE, aeskeySpec); // switching mode for decryption
CipherInputStream is = new CipherInputStream(new FileInputStream(file), aesCipher); //output stream to another file
ByteArrayOutputStream os = new ByteArrayOutputStream();
int i;
byte[] b = new byte[1024];
while((i=is.read(b))!=-1) {
os.write(b, 0, i);
}
is.close();
os.close();
String file_string = new String(b,"UTF-8");
System.out.print(file_string);
return file_string.equals(challenge); //return false
}
Thank you.
The first part is the encryption part. The second part is the decryption part.
The second part is wrong. You are decrypting the last part of the still-encrypted buffer, rather than the entire, decrypted ByteArrayOutputStream, and committing a size error in the process too.
String file_string = new String(b,"UTF-8");
should be
String file_string = new String(os.toByteArray(), "UTF-8");

Calculate multiple checksums from the same InputStream using DigestInputStream

I am trying to figure out how to read multiple digests (md5, sha1, gpg) based on the same InputStream using DigestInputStream. From what I've checked in the documentation, it seems to be possible by cloning the digest. Could somebody please illustrate this?
I don't want to be re-reading the stream in order to calculate the checksums.
You could wrap a DigestInputStream around a DigestInputStream and so on recursively:
DigestInputStream shaStream = new DigestInputStream(
inStream, MessageDigest.getInstance("SHA-1"));
DigestInputStream md5Stream = new DigestInputStream(
shaStream, MessageDigest.getInstance("MD5"));
// VERY IMPORTANT: read from final stream since it's FilterInputStream
byte[] shaDigest = shaStream.getMessageDigest().digest();
byte[] md5Digest = md5Stream.getMessageDigest().digest();
The Javadoc is pretty clear. You can use clone only to calculate different intermediate digests using the same algorithm. You cannot use DigestInputStream to calculate different digest algorithms without reading the stream multiple times. You must use a regular InputStream and multiple MessageDigest objects; read the data once, passing each buffer to all MessageDigest objects to get multiple digests with different algorithms.
You could easily encapsulate this in your own variant of DigestInputStream, say MultipleDigestInputStream that follows the same general approach but accepts a collection of MessageDigest objects or algorithm names.
Pseudojava (error handling omitted)
MessageDigest sha = MessageDigest.getInstance("SHA-1");
MessageDigest md5 = MessageDigest.getInstance("MD5");
InputStream input = ...;
byte[] buffer = new byte[BUFFER_SIZE];
int len;
while((len = input.read(buffer)) >= 0)
{
sha.update(buffer,0,len);
md5.update(buffer,0,len);
...
}
byte[] shaDigest = sha.digest();
byte[] md5Digest = md5.digest();

Categories