An input text of arbitrary length can be sent through a hash function to produce an output string that has a fixed length. The hash value is the name for the output’s fixed length. A hash function must have the following characteristics in order to be cryptographically secure and effective
This characteristic implies that reversing a hash function should be computationally hard.
If we have the hash value “h”, then it should be difficult to find the value “x” such that:
h = hash(k, x)
In other words, it should be challenging to discover any input value x that hashes to z if a hash function h produces a hash value z.
This property guards against an attacker trying to locate the input with merely a hash value.
This property states that it should be difficult to locate a different message value with the same hash if we have the given input and its hash.
In other words, if we have the hash function “h (x)", that produces a hash value for “x” :
h(x) = hash(k, x)
Then it should be difficult to find another value “y” such that
h(x) = h(y)
This characteristic of the hash function guards against an attacker who possesses a message value and its hash and wishes to replace the original input value with another one that is valid.
Due to this characteristic, it should be difficult to evaluate two distinct inputs of any length that produce the same hash. This is also known as a collision-free hash function.
If we have two input messages, “x1” and “x2”, it’ll be hard to find a hash value such that:
hash(k, x1) = hash(k, x2), where k is the key value.
It is difficult for a hash function to be collision-free because it compresses data with a set hash length. This characteristic of collision-free merely supports the idea that such collisions ought to be difficult to locate.
If the function is collision-resistant, then it is also second preimage resistant.
The hash function accepts variable-length inputs and returns fixed-length outputs. Transactions are used as inputs in cryptographic hash functions, and the hash algorithm produces a fixed-size output. The figure below illustrates how hashes work.
There are so many hash functions out there, so if we are going to calculate the hash value of the above message “Hello world, this is a hash function,” it looks like:
If we only focus on the SHA-256 hash value of the above-mentioned text value then it is 5eff5ed15fe083a69bdfa7b40a28928602cd1d622adc4fdad5305b7a29c0f199
SHA-256 is a very famous hash function, it stands for Secure Hashing Algorithm which produces 256bit of hash, which is collision, preimage, and second preimage resistant. This secured hash function is also used in Bitcoin Blockchain.
Hash is totally case sensitive so if you alter a single letter it will change the whole hash value. If we calculate the hash for “hello world, this is a hash function” then the resulting SHA-256 hash value will be –
f6fe4a652671717ac3717431ddb407a61b3a7a04c126e5c24528f0256b882b17
But for the same message value, its hash value is always the same.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
class HashFunction {
public static byte[] getSHAHash(String input) throws NoSuchAlgorithmException {
// Getting instance of SHA-256
MessageDigest msg_digest = MessageDigest.getInstance("SHA-256");
// digest function calculate message digest of an input
// and return byte array
return msg_digest.digest(input.getBytes(StandardCharsets.UTF_8));
}
public static String toHexString(byte[] hash) {
// Convert byte array into Big Integer
BigInteger number = new BigInteger(1, hash);
// Convert message digest into hex value
StringBuilder hexString = new StringBuilder(number.toString(16));
// Adding leading zeroes
while (hexString.length() < 64) {
hexString.insert(0, '0');
}
return hexString.toString();
}
public static void main(String args[]) {
try {
System.out.println("HashCode Generated by SHA-256 -");
String m_value_1 = "Hello world, this is a hash function";
System.out.println("\n" + m_value_1 + " : " + toHexString(getSHAHash(m_value_1)));
String m_value_2 = "hello world, this is a hash function";
System.out.println("\n" + m_value_2 + " : " + toHexString(getSHAHash(m_value_2)));
} catch (NoSuchAlgorithmException e) {
System.out.println(e);
}
}
}
Output
Password storage is protected using hash functions.
Rather than keeping passwords in plain text, most login processes save hash values of passwords in a file.
Even if the password was accessed, an attacker can only read the hashes of passwords. They can’t use hash to log in, and can’t deduce the password from the hash value because the hash function has the characteristic of pre-image resistance.
The most typical use of hash functions is to verify data integrity. Checksums on data files are generated with it. This application gives the user assurance that the data is correct.
The integrity check aids the user in detecting any modifications to the original file. It does not, however, guarantee that the work is unique. Instead of changing file data, the attacker can change the entire file and compute a new hash for it all before sending it to the receiver. This integrity testing tool is only useful if the user is certain of the file’s uniqueness.