I am using the following code to hash an incoming string, in expecting that same thing applied to the method multiple times will always get the same results. The scenario will be for password hashing and later verification. But it doesn't seem to work - I got two different blobs for the same input string. Is there anything wrong or missing with my code?
public synchronized String encrypt(String token) {
try {
MessageDigest sha = MessageDigest.getInstance("SHA");
sha.reset();
sha.update(token.getBytes("UTF-8"));
byte[] raw = sha.digest();
System.out.println("raw = " + raw.toString());
String hash = Base64.encodeBase64(raw).toString();
return hash;
} catch (Exception e) {
}
return token;
}
You haven't really given enough information, but I suspect you're being distracted by this:
System.out.println("raw = " + raw.toString());
That's going to print out something like [B#30a4effe which has nothing to do with the data in the byte array. You should print out hash instead - which should be the same for all calls, if your token is genuinely the same.
(As noted by Dan, your method is inappropriately named: hashing isn't encryption. Also, please don't catch Exception or just swallow exceptions like this. It seems pretty odd to just return token on failure, too.)
EDIT: As noted, I've assumed that Base64.encode actually returns a String, which it may not. I'd recommend this base64 implementation which is public domain and has a sensible API - the encoding calls return a String, which is entirely appropriate. Of course, you then don't need the explicit toString() call as well...
I don't know what Base64 class you are using, but I will assume the one from Apache Commons. You are doing this:
String hash = Base64.encodeBase64(raw).toString();
Which is calling the toString method on whatever random byte array is returned from the Base64.encodeBase64() method. That is why your result is random every time, you are just returning an object reference as a String. Try this instead:
String hash = Base64.encodeBase64String(raw);
EDIT
As pointed out in another post, converting directly to String is probably a bad idea. I edited my answer slightly to reflect that.
Related
I'm confused about this issue. Platform is on win7 java8.
Sample code:
String encryptedData = "0019ZfGO0nefTb2kIuHO0M3hGO09ZfGF";
Base64.Decoder decoder = Base64.getDecoder();
byte[] dataByte = decoder.decode(encryptedData);
System.out.println(dataByte);
dataByte = decoder.decode(encryptedData);
System.out.println(dataByte);
The output:
[B#15db9742
[B#6d06d69c
The exact input got different result.
Don't know if there's anyway to clear the status and make the result consistent every time?
Thanks!
In Java, arrays don't override toString(), so if you try to print one directly, you get the "className + # + the hex of the hashCode of the array", as defined by Object.toString()
Note:Just printing the array by reference variable means you are calling the toString() method of that array object.
As decoder.decode(encryptedData) returns a new byte[] every-time, therefore it gives a different value when you just print the reference variable.
Ex: System.out.println(dataByte);//output:[B#15db9742
You can use the standard library functions to print the contains of the array. There are many ways to achieve this. Just some examples are below:
System.out.println(Arrays.toString(dataByte));
System.out.println(dataByte.toList());
I have a lot of urls that serve as keys in a HBase table. Since they "all" start by http://, Hbase puts them in the same node. Thus I end with a node at +100% and the other idle.
So, I need to map the url to something hash-like, but reversible. Is there any simple, standard, and fast way to do that in JAVA8.
I look for random (linear) distribution of prefixes.
Note:
reversing the url is not interesting since a lot of urls end with / ? = and risk to unbalance the distribution.
I do not need encryption, but I can accept it.
I do not look for compression, but it is welcome if possible :)
Thanks,
Costin
There's not a single, standard way.
One thing you can do is to prefix the key with its hash. Something like:
a01cc0fe http://...
That's easily reversible (just snip off the hash chars, which you can make be a fixed length) and will get you good distribution.
The hash code for a string is stable and consistent across JVMs. The algorithm for computing it is specified in String.hashCode's documentation, so you can consider it part of the contract of how a String works.
Add prefix of the hash code encoded by 36 decimal number [0-9a-z].
public static String encode(String s) {
return Integer.toString(s.hashCode() & 0xffffff, 36) + "#" + s;
}
public static String decode(String s) {
return s.replaceFirst("^[^#]*#", "");
}
sample:
http://google.com/ <-> 5o07l#http://google.com/
I would like to hash two BigIntegers in Java with the MessageDigest class.
So far I have the following code
// SHA(v concantenated with n)
public void calculateProversCertificate(BigInteger v, BigInteger n)
{
MessageDigest md;
try
{
md = MessageDigest.getInstance("SHA-1");
md.update(v.toByteArray());
md.update(n.toByteArray());
byte[] byteData = md.digest();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < byteData.length; i++)
{
sb.append(Integer.toString((byteData[i] & 0xFF) + 0x100, 16).substring(1));
}
String hash = sb.toString();
System.out.println("Certificate:" + hash);
}
catch (NoSuchAlgorithmException ex)
{
System.out.println("Could not create SHA MessageDigest class");
}
}
The code I have there is works to calculate a hash but it is not the proper length when printed as a string. I used this code to create "cookies" from user passwords and I would like to adapt it to find the hash of two BigIntegers. I am specifically not sure about the for loop and how it works. I assume it is rejoining the Byte[] into something that can be represented as a string. Though this is a little over my head on how it does this.
Could someone explain the idea behind the loop, and how it is building the string? Also how I might adapt it to produce an output like the example below?
Basically I am looking for output something like this
1tdgsp8bs0gk72dbvpu0be33tv2dobimc4mg07d209401mrhbe23qe1tdh7jcd78so46ffet20lqemlakv4mfvbk6fjp9a2th9bhb2
But I am getting something like this (Produced by the print statement in the code)
9aa1770b83257b2c7b2a6fb9684253930781c0cf
And example V and N (Produced by BigInteger.toString();)
V: 1678202601632665039275603893340186995409970283833828187403506666684692322312620073622777464636561237395218125410336245265888297965169878433803688272535099
N: 8449118772240198089422438092628650298318511756191052993769148184590886001852753186246607550316706472668220614311553576373631078947139889888957411418229019
That loop looks like it's a convoluted way of turning a byte array into a hexadecimal string. It takes each byte value, applies a hideous function to turn it into two hex characters, and appends them to a StringBuilder.
I don't know why the author didn't just use Integer.toHexString, or, even better, String.format inside the loop. Either of those would be much easier than what you have now.
Note that byteData[i] & 0xFF does nothing (except promote to int, which you don't need since byte values can auto-promote to int). byteData[i] is a byte, and executing & 0xFF on a byte value is a no-op.
Anyway, this code appears to be generating the right output. SHA-1 generates a 160-bit hash, and that looks like a 40-character hex string. Hex encodes 4 bits per character, so that seems to be a valid encoding of the hash value (40 characters * 4 bits per character = 160 bits in the hash)
Basically I am looking for output something like this
1tdgsp8bs0gk72dbvpu0be33tv2dobimc4mg07d209401mrhbe23qe1tdh7jcd78so46ffet20lqemlakv4mfvbk6fjp9a2th9bhb2
Where did you get that string from? Why do you expect your hash output to look like that?
Incidentally, I hope you are not really implementing your own certificate check. Crypto code is notoriously difficult to get right so you should be using an existing library. If you roll your own crypto you will have a vulnerability (probably many vulnerabilities).
I want to turn an MD5 Hash to a string:
public String MD5ToString(String plain) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.reset();
md.update(plain.getBytes());
byte[] digest = md.digest();
BigInteger bigInt = new BigInteger(1,digest);
String hashtext = bigInt.toString(16);
// Now we need to zero pad it if you actually want the full 32 chars.
while(hashtext.length() < 32 ){
hashtext = "0"+hashtext;
}
return plain;
} catch (Exception e) {
System.out.println("Cannot encrypt String to Hash");
e.printStackTrace();
}
return null;
}
However i just get the Md5 back? Whats ms mistake?
UPDATE:
I changed the return type to hashtext, BUT when I want to convert a hash to a string I just get another has back:
String: test
Hash: 098f6bcd4621d373cade4e832627b4f6
String: fb469d7ef430b0baf0cab6c436e70375
I didn't analyze the code carefully but you return the object plain which has not changed. You should return hashText object if you want to get MD5 string returned from the method.
To have a usable string that you can send or store easily, the usual solution is to encode it in base64 (it's about 33% shorter than in hexa).
Here's one of the numerous tutorials you can find with Google : http://www.javatips.net/blog/2011/08/how-to-encode-and-decode-in-base64-using-java
In your precise case, as you seem to want the hexa representation, maybe you simply want to change
return plain;
to
return hashtext;
I changed the return type to hashtext, BUT when I want to convert a hash to a string I just get another hash back.
You seem to be under a misapprehension of what hashes are.
In general, hashing is a non-reversible transformation. You turn the hash back into a copy of the original string / object / whatever ... because much / most of the information content of the original has been thrown away. Indeed, there are an infinite number of possible input strings that hash to a given hash value, and there is no way of knowing which one is the right one. (They are all right.)
In the case of cryptographic hash functions like MD5, it is even worse. These functions are specifically designed to be non-reversible. Or more precisely, they are designed such that for a given the hash, the problem of recovering a possible input is computationally intractable.
Now it so happens that MD5 is weak ... and that if you have a large (but technically feasible) amount computational resources and time it is possible to reverse the hash. However, that doesn't address the first bullet point.
The bottom line is that if you want to be able to recover the original string you need to encrypt it rather than hash it.
Is there an equivalent to Java's String intern function in Go?
I am parsing a lot of text input that has repeating patterns (tags). I would like to be memory efficient about it and store pointers to a single string for each tag, instead of multiple strings for each occurrence of a tag.
No such function exists that I know of. However, you can make your own very easily using maps. The string type itself is a uintptr and a length. So, a string assigned from another string takes up only two words. Therefore, all you need to do is ensure that there are no two strings with redundant content.
Here is an example of what I mean.
type Interner map[string]string
func NewInterner() Interner {
return Interner(make(map[string]string))
}
func (m Interner) Intern(s string) string {
if ret, ok := m[s]; ok {
return ret
}
m[s] = s
return s
}
This code will deduplicate redundant strings whenever you do the following:
str = interner.Intern(str)
EDIT: As jnml mentioned, my answer could pin memory depending on the string it is given. There are two ways to solve this problem. Both of these should be inserted before m[s] = s in my previous example. The first copies the string twice, the second uses unsafe. Neither are ideal.
Double copy:
b := []byte(s)
s = string(b)
Unsafe (use at your own risk. Works with current version of gc compiler):
b := []byte(s)
s = *(*string)(unsafe.Pointer(&b))
I think that for example Pool and GoPool may fulfill your needs. That code solves one thing which Stephen's solution ignores. In Go, a string value may be a slice of a bigger string. Scenarios are where it doesn't matter and scenarios are where that is a show stopper. The linked functions attempt to be on the safe side.