How large of a String does Sha256 produce? - java

How large of a String does Sha256 produce?
Does the answer depend on how large of a String I am using to get a hash using Sha256?
I plan to store the Sha256-produced hash String in a mySQL table, in a column defined as a varchar(500).

SHA256 generates a 256-bit hash.
But its hexadecimal representation will be 64 characters (2^256 = 16^64)
Ex Text: stackoverflow
Hash: 126cfbe1fd5413ba4d604c50a74bfc80471cec367b1604ade4d081f31c3f4f34
Hence char(64) would be a sufficient datatype for your column.

Related

Verify Hashing.sha256() generated hash

I have this code created using Google Guava:
String sha256hex = Hashing.sha256()
.hashString(cardNum, StandardCharsets.UTF_8)
.toString();
How I can verify the generated values is a properly generated hash?
SHA-256 and, in general, the family of SHA 2 algorithms is wonderfully described in Wikipedia and different RFCs, RFC 6234 and the superseded RFC 4634.
All these sources dictate that the output provided by the SHA 256 hash function is 256 bits length, 32 bytes (the number that accompanies the SHA word is the mentioned value for every algorithm in the family, roughly speaking).
These sequence of bytes is typically encoded in hex. This is the implementation provided by Guava as well.
Then, the problem can be reduced to identify if a string in Java is a valid hex encoding.
That problem has been already answered here, in SO, for example in this question.
For its simplicity, consider the solution proposed by #laycat:
boolean isHex = mac_addr.matches("^[0-9a-fA-F]+$");
As every byte is encoded with two hex characters and, as mentioned, the SHA-256 algorithm produces and output of 32 bytes you can safely check for a string of 64 characters length, as suggested in the answer of #D.O. as well. Your validation code could be similar to this:
boolean canBeSha256Output = sha256Hex.matches("^[0-9a-fA-F]{64}$");
Please, be aware that there is no possibility for saying if a character hex string of a certain length on its own is or not the result of a hash function, whichever hash function you consider.
You only can be sure that a hash output is a hash output if and only if it matches the result of applying the corresponding hash function over the original input.
You could use a regex to verify that it looks like a sha256 hash(64 hexadecimal characters), like
\b[A-Fa-f0-9]{64}\b

How to calculate RSA MD5 signature in separate steps?

I use the following 2 steps to calculate the signature, why is it different
Use java code
1- Signature s1 = Signature.getInstance("MD5withRSA");
// some code
String b1 = base64Encode(doFinalData);
2- byte[] md5 = MD5.md5("data content");
byte[] rsa = RSA.rsa(md5);
String b2 = base64Encode(rsa);
// Why b1 and b2 are not equal
Is my understanding wrong, or the code is wrong
I'm not sure which library you are using for #2, but it looks like raw RSA encryption.
When you perform "MD5withRSA" in #1 you'll actually use PKCS#1 v1.5 padding for signature generation. This will create a structure that specifies the MD5 algorithm and the MD5 signature value. Then it will pad that, and finally it will perform the modular exponentiation with the private key. The steps are described in detail in the standard.
However, if #2 is just raw RSA then it will simply convert the MD5 to a positive integer and use that as input for modular exponentiation. So the padding and structure before the MD5 hash is missing.
Just a small additional note: the signature scheme using PKCS#1 v1.5 and raw RSA are deterministic. This is not a property that is present for all schemes: RSA-PSS or ECDSA will always generate different signature values. So to test if a signature is valid, you'll have to perform the signature verification using the public key rather than a binary compare.

Different length of hashed password using argon2 in python and java

Not sure if it is the right output but when I hash a password with argon in java, i get the output:
$argon2i$v=19$m=512,t=2,p=2$J1w6n04CBSEA8p0cCqeK7A$tb1ihqduhONYZN0+ldKkw980Y7h7ZJ2OcDTsXyIMibo
while python gives me:
argon2$argon2i$v=19$m=512,t=2,p=2$TjZiM3ZTdGFIQUlZ$CocCpAIXQc722ndqkFZWxw
the parameters seem the same: i, 512, 2, p =2
Any argon2 guru who can tell me how I can have the same length output? Prefer playing with the java since it is a simple ussd app.
After the p=2 in the string, there is a dollar sign. The string between this dollar sign and the next dollar sign is the salt of the hash. After the second dollar sign is the actual key that has been derived by Argon2. In the Java example, (after being base64 decoded), the hash length is 32. However, in Python, the hash length is 16 (which is the default in Python). So, in Python, if you did:
import argon2
argon2.hash_password(b"Password",memory_cost=512,time_cost=2,parallelism=2,hash_len=32)
Then you will have the same length hash as in the Java example. Also, if you specify the same salt for both the Python and Java implementations, then the hashes should be identical to each other (given that the parameters are the same between the two).

Is it possible to limit the hashcode into specific number of characters in Java

I have written a method to convert a plain text into it's hashcode using MD5 algorithm. Please find the code below which I used.
public static String convertToMD5Hash(final String plainText){
MessageDigest messageDigest = null;
try {
messageDigest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
LOGGER.warn("For some wierd reason the MD5 algorithm was not found.", e);
}
messageDigest.reset();
messageDigest.update(plainText.getBytes());
final byte[] digest = messageDigest.digest();
final BigInteger bigInt = new BigInteger(1, digest);
String hashtext = bigInt.toString(8);
return hashtext;
}
This method works perfectly but it returns a lengthy hash. I need to limit this hash text to 8 characters. Is there any possibilities to set the length of the hashcodes in Java?
Yes and No. You can use a substring of the original hash if you always cut the original hash-string similary (ie. 8 last/first characters). What are you going to do with that "semi-hash" is another thing.
Whatever it is you're going to do, be sure it has nothing to do with security.
Here's why: MD5 is 128-bit hash, so there's 2^128 = ~340,000,000,000,000,000,000,000,000,000,000,000,000 possible permutations. The quite astronomical amount of permutations is the thing that makes bruteforcing this kind of string virtually impossible. By cutting down to 8 characters, you'll end up with 32-bit hash. This is because a single hex-value takes 4 bits to represent (thus, also 128-bit / 4 bit = 32 hex-values). With 32-bit hash there's only 2^32 = 4,294,967,296 combinations. That's about 79,228,162,514,264,337,593,543,950,336 times less secure than original 128-bit hash and can be broken in matter of seconds with any old computer that has processing power of an 80's calculator.
No. MD5 is defined to return 128 bit values. You could use Base64 to encode them to ASCII and truncate it using String#substring(0, 8).
In Java 8 (not officially released yet), you can encode a byte[] to Base64 as follows:
String base64 = Base64.getEncoder().encodeToString(digest);
For earlier Java versions see Decode Base64 data in Java
all hash algorithms should randomly change bits in whole hash whenever any part of data has changed. so you can just choose 8 chars from your hash. just don't pick them randomly - it must be reproducible
Firstly as everyone has mentioned, the 64 bit hash is not secure enough. Ultimately it depends on what you exactly plan to do with the hash.
If you still need to convert this to 8 characters, I suggest downcasting the BigInteger to a Long value using BigIteger.longValue()
It will ensure that the long value it produces is consistent with the hash that was produced.
I am not sure if taking most significant 64 bits from the 128 bit hash is good idea. I would rather take least significant 64 bits. What this ensures is that
when hash(128, a) = hash(128, b) then hash(64, a) = hash(64, b) will always be true.
But we have to live with collision in case of 64 bits i.e. when hash(64, a) = hash(64, b) then hash(128, a) = hash(128, b) is not always true.
In a nutshell, we ensure that we do not have a case where 128 bit hashes of 2 texts are different, but their 64 bit hashes are same. It depends on what you really use the hash for, but I personally feel this approach is more correct.

Encrypt an Integer Value with DES

I want to encrypt an integer with DES, the resultant cipher text should also be an integer.
Decryption function should follow this notion as well.
I am trying to modifying the code at Encrypting a String with DES, by converting the byte array to integer, instead of using Base64 encoding. However the decryption function throws an exception of improper padding, as the conversion of integer to byte[] results in a 4 byte array.
Is there any other encryption algorithm that I can use to achieve this.
I am not concerned about the weakness of the cipher text.
If you are running an Integer value through DES to produce another Integer value, and you don't care about the cipher text weakness, then you are merely doing a very expensive hashing operation. You'd be better off generating a random integer as the key and bitwise xor-ing the exponent and the random integer. This would take nanoseconds to compute and have exactly the same security.
DES has a 64 bit blocksize, so in general the output from the encryption of a 32 bit int will be a 64 bit block. It will be easier to encrypt a 64 bit long to another 64 bit long. Use ECB mode so that padding is not an issue, or at least you are adding zero bits to the front of your int to extend it to 64 bits.
If you merely want to smush up your int then Jim's suggestion is excellent.
You want to look at Format Perserving Encryption. There are a couple of techniques for it, but in general all of them will generate a value in the same domain as your input ( i.e. integers, credit card numbers,etc)

Categories