Reputation: 23
I'm converting code from Go to Java. The source to convert is at https://github.com/h2non/imaginary#url-signature and this is my current code converted to Java.
The problem is that I'm missing something, since the signature generated in Java is different than the one in Go.
Expected result (as in source in Go):
ruEWRoFO-ic-L38vTsjqIYE6DLZ532CTaZXOh1gwuVo
Actual result in Java:
x2clz4ynSxcFPNc6h3W832vyrIQ=
My code in Java:
@Test
public void testSomeString() throws Exception {
String signKey = "4f46feebafc4b5e988f131c4ff8b5997";
String urlPath = "/resize";
String urlQuery = "file=image.jpg&height=200&type=jpeg&width=300";
byte[] signKeyAsBytes = signKey.getBytes("UTF-8");
SecretKey SHA256_KEY = new SecretKeySpec(signKeyAsBytes, "HmacSHA256");
byte[] hashAsBytes=Hashing.hmacSha1(SHA256_KEY)
.newHasher()
.putString(urlPath, UTF_8)
.putString(urlQuery, UTF_8)
.hash().asBytes();
String hash = Base64.getUrlEncoder().encodeToString(hashAsBytes);
//correct value in GoLang is: "ruEWRoFO-ic-L38vTsjqIYE6DLZ532CTaZXOh1gwuVo"
Assert.assertEquals("ruEWRoFO-ic-L38vTsjqIYE6DLZ532CTaZXOh1gwuVo", hash);
/*
Junit test fails with:
Expected :ruEWRoFO-ic-L38vTsjqIYE6DLZ532CTaZXOh1gwuVo
Actual :x2clz4ynSxcFPNc6h3W832vyrIQ=
*/
}
And this is the original in Go:
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
)
func main() {
fmt.Println("Hello, playground")
signKey := "4f46feebafc4b5e988f131c4ff8b5997"
urlPath := "/resize"
urlQuery := "file=image.jpg&height=200&type=jpeg&width=300"
h := hmac.New(sha256.New, []byte(signKey))
h.Write([]byte(urlPath))
h.Write([]byte(urlQuery))
buf := h.Sum(nil)
fmt.Println("sign=" + base64.RawURLEncoding.EncodeToString(buf))
}
Upvotes: 2
Views: 5343
Reputation: 23
For future reference, here is the final WORKING solution
package hashingImaginary;
import org.apache.commons.codec.binary.Base64;
import org.junit.Assert;
import org.junit.Test;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class apacheHashingTest {
@Test
public void testWithJavaHmacApacheBase64() throws Exception {
String urlPath = "/resize";
String urlQuery = "file=image.jpg&height=200&type=jpeg&width=300";
String signKey = "4f46feebafc4b5e988f131c4ff8b5997";
String message = urlPath + urlQuery;
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(signKey.getBytes(), "HmacSHA256");
sha256_HMAC.init(secret_key);
String hash = Base64.encodeBase64URLSafeString(sha256_HMAC.doFinal(message.getBytes()));
System.out.println(hash);
Assert.assertEquals("ruEWRoFO-ic-L38vTsjqIYE6DLZ532CTaZXOh1gwuVo", hash);
}
}
Upvotes: 0
Reputation: 39000
I don't know what Hashing
class you are using in Java, because it isn't standard, but if I use the standard class javax.crypto.Mac
to do HmacSHA256 (NOT HmacSHA1) with that key and data -- and encode with the 'unpadded URLsafe' variant of Base64 promoted by JSON, not the traditional one Java defaults to -- I do get ruEWRoFO-ic-L38vTsjqIYE6DLZ532CTaZXOh1gwuVo
.
However, it is very poor practice to sign the path and query without some delimiting -- this may allow a signature to be 'moved' to different data. It is also weird, though not directly dangerous, to use a key that is characters but only hex digit characters. I wouldn't use a scheme designed like this for anything important without extensive investigation.
Upvotes: 1