I tried to search this but surprisingly could not find any results of converting SHA-1 generated string back to normal string. I hash a string to SHA-1 and then send it to some other device where this SHA-1 generated string should be unhashed and used but I am unable to find any such method in Java.
The whole point of SHA-1 and other hashing algorithms is that there is no such thing as unhashing. There is no such method in Java or any other language.
What you are searching for is symmetric encryption.
You are confusing hashing with encryption (this is what you would probably want to use instead). Encryption is reversible given a key, while hashing is not.
Hashes are one way, you can go from text to hash but not the other way.
Have a look at this for a nice discussion:
https://security.stackexchange.com/questions/11717/why-are-hash-functions-one-way-if-i-know-the-algorithm-why-cant-i-calculate-t
Related
public static void main(String[] args) {
String s = "text";
hash=DatatypeConverter.printHexBinary(MessageDigest.getInstance("MD5").digest(s.getBytes("UTF8")))
System.err.println(hash);
}
You can't. That's what hashing is about. This is not a API or library limitation but a mathematical one, which is there by design.
You need to understand that hashing and encryption/ decryption are two completely different things (which are often used together).
Hashing
A hash, or to be precise, a cryptographic hash, is the result of a mathematical one-way function which means it is meant to be irreversible. Once something is hashed, it is not possible to get the text that was hashed back from it. This is at least true for good hash algorithms, which are not considered broken. MD5 as well as SHA1 are considered broken, so if you need this in a security context, use SHA-256 or even SHA-512 instead. If you just need this for a checksum, MD5 should be fine.
You can just use an MD5 hash value and type it into Google and get the result back. That is not what you want from a hash function. E.g. take your the hash 1cb251ec0d568de6a929b520c4aed8d1 which is the MD5 hash of your message text and you'll get a website which shows you the original text.
Another property of a hash it that for two different inputs it should ideally never have the same output. That is of course impossible as the set of possible messages to hash is much much bigger then the set of possible hash messages as hashes have a fixed length. But it should not be possible to generate such a hash collision artificially following some algorithm or clever input.
The only way to find out what was hashed is to hash many messages (brute-force) and see if the computed hash matches the hash to be cracked. See Rainbow tables for more information on this.
Hashes are mostly used to ensure integrity i.e. no modification was done to a message sent over the network. It is often used in conjunction with encryption algorithms (that's probably where your confusion originates from) as you need more than integrity to guarantee secure communication i.e. additionally authentication (e.g. by using certificates) and confidentiality (this is provided by encryption algorithms).
Encryption
An encryption function is a function which takes a message and a key and produces a result which is not readable unless you have the key. Side note: there may be one or two keys for encryption/ decryption depending on the algorithm you use (symmetric vs. asymmetric). If you have the key, it is reversible by applying the decryption function. If it was a one-way function like a hash, encryption would make no sense, as a recipient of a message would not be able to retrieve the message.
This question already has answers here:
How to reverse MD5 to get the original string? [duplicate]
(2 answers)
Closed 2 years ago.
I am looking into md5 hashing in java with the MessageDigest Class, lets say I do that
public void givenPassword_whenHashingUsingCommons_thenVerifying() {
String hash = "35454B055CC325EA1AF2126E27707052";
String password = "ILoveJava";
String md5Hex = DigestUtils
.md5Hex(password).toUpperCase();
assertThat(md5Hex.equals(hash)).isTrue();
}
So i did convert my password String into an md5 hash, lets say my recipient now wants the String not as hash, but as an normal String ( The Hash is just for transmission ), how can i convert the md5 hash String back to an "normal" Text String?
There is no way to convert a hash (MD5 or SHA1 or SHA2....) into the original string.
The purpose of a hashing function is a one-way translation. There is no coming back.
The MD5 hash function is an outdated cryptographic function that generates fixed length hashes of an input data. The how and whys is beyond the scope of this answer. I urge you to visit detailed texts on these online.
Please also remember that if you are using the MD5 for cryptographic and sensitive reasons, please learn about more secure recommended hashing as SHA256 etc..
For more details, please refer to this introductory text.
The reason that we hash passwords in particular is because it's one way and this is good for security reasons. Imagine a bad actor got access to your database, we wouldn't want them to be able to look up the password and log in as the user. By storing the hashed password, we can perform the same hashing algorithm on the password on login and compare it with the database value in the database for a successful login.
Even this has its issues. When bad actors gain access to a compromised database, they can generate "rainbow tables" to get from the hashed value to the password. Using common hashing algorithms and software such as hashcat they build up a database of common passwords, dictionary words etc. then match the hash value to the plain text string. This is why when storing passwords, we also use salting, which can be easily researched, Google "salting and hashing".
I see another answer which states that "The purpose of the hashing function is a one way translation". I think this is an over simplification. A hashing algorithm returns a message digest. It's a fixed length alphanumeric message which, as uniquely as possibly, represents the input. One the most important properties of a hashing algorithm is the uniqueness of the message and that it differs significantly from that of similar inputs. Here's an example using MD5:
String: aaaaaaaaaa
Hash: e09c80c42fda55f9d992e59ca6b3307d
String: aaaaaaaaab
Hash: ba05a43d3b98a72379fdc90a1e28ecaf
I was currently looking for a sample AES encryption and decryption using Java and I have stumbled upon something like this as a solution:
LINK
Other solutions offered the same approach. I managed to got it to work but I just have some questions on its implementation.
Questions:
Why does the PBEKeySpec class need a password? what is it for? there
is already a key, why does it need to have an additional token or
password?
I understand that the key and salt is part of the encrypted value of
the original un-encrypted string. Why is that so? why not allow to
store the generate key and salt somewhere else?
Thanks and I appreciate any form of help. Just want to understand why it was made that way.
For easy-to-use and rock-solid java encryption library I recommend to use http://www.jasypt.org/
To your questions:
password is often used to derive the encryption key; this is needed because many algorithms require keys to meet certain properties such as length and randomness which isn't satisfied by many of the passwords normally used by people. See also https://docs.oracle.com/javase/7/docs/api/javax/crypto/spec/PBEKeySpec.html
A salt and an initialization vector are stored alongside the encrypted value (that is they are NOT encrypted) because it's convenient - you can easily retrieve them and use them to decrypt the original string. This is still safe because you typically only need these values to be unique not to be kept secret; e.g. salt helps you prevent rainbow table attacks by having a unique salt for each value.
A useful resource explaining some terminology: https://crypto.stackexchange.com/questions/3965/what-is-the-main-difference-between-a-key-an-iv-and-a-nonce
I have a string that I have hashed using
Hashing.sha256().hashString("abc", Charsets.UTF_8).toString()
Now I want to decode the encrypted string. How should I do so?
The library I am using right now is
com.google.common.hash.Hashing
If you want to extract the original string, sha256 is specifically designed to make that almost impossible. If it was possible to do that efficiently then sha256 would be useless and everyone would be sad.
If you want it to be reversible, you should use an encryption algorithm, which is different from a hashing algorithm. Reversing a hash, especially a cryptographic hash function, is supposed to be hard.
(In addition, more than one string may have the exact same hash code, meaning that you can't be sure a string with the same hash was actually the same as the original string you used.)
I am using a 3rd party platform to create a landing page, it is a business requirement that I use this particular platform.
On their page I can encrypt data and send it to my server through a request parameter when calling a resource on my site. This is done through an AES Symmetric Encryption.
I need to specify a password, salt (which must be a hex value) and an initialization vector (but be 16 characters).
Their backend is a .NET platform. I know this because if I specify an IV longer than it expects the underlying exception is:
System.Security.Cryptography.CryptographicException: Specified initialization vector (IV) does not match the block size for this algorithm.
Source: mscorlib
So for example, on their end I specify:
EncryptSymmetric("Hello World","AES","P4ssw0rD","00010203040506070809", "000102030405060708090A0B0C0D0E0F")
Where the inputs are: plain text, algorithm, pass phrase, salt, and IV respectively.
I get the value: eg/t9NIMnxmh412jTGCCeQ==
If I try and decrypt this on my end using the JCE or the BouncyCastle provider I get (same algo,pass phrase, salt & IV, with 1000 iterations): 2rrRdHwpKGRenw8HKG1dsA== which is completely different.
I have looked at many different Java examples online on how to decrypt AES. One such demo is the following: http://blogs.msdn.com/b/dotnetinterop/archive/2005/01/24/java-and-net-aes-crypto-interop.aspx
How can I decrypt a AES Symmetric Encryption that uses a pass phrase, salt and IV, which was generated by the .NET framework on a Java platform?
I don't necessarily need to be able to decrypt the contents of the encryption string if I can generate the same signature on the java side and compare (if it turns out what is really being generated here is a hash).
I'm using JDK 1.5 in production so I need to use 1.5 to do this.
As a side note, a lot of the example in Java need to specify an repetition count on the java side, but not on the .NET side. Is there a standard number of iterations I need to specify on the java side which matches the default .NET output.
It all depends on how the different parts/arguments of the encryption are used.
AES is used to encrypt bytes. So you need to convert the string to a byte array. So you need to know the encoding used to convert the string. (UTF7, UTF8, ...).
The key in AES has some fixed sizes. So you need to know, how to come from a passphrase to an AES key with the correct bitsize.
Since you provide both salt and IV, I suppose the salt is not the IV. There is no standard way to handle the Salt in .Net. As far as I remember a salt is mainly used to protect against rainbow tables and hashes. The need of a Salt in AES is unknown to me.
Maybe the passphrase is hashed (you did not provide the method for that) with the salt to get an AES key.
The IV is no secret. The easiest method is to prepend the encrypted data with the IV. Seen the length of the encrypted data, this is not the case.
I don't think your unfamiliarity of .Net is the problem here. You need to know what decisions the implementer of the encryption made, to come from your parameters to the encrypted string.
As far as I can see, it is the iteration count which is causing the issue. With all things the same (salt,IV,iterations), the .Net implementation generates the same output as the Java implementation. I think you may need to ask the 3rd party what iterations they are using