Shopify oauth 中的 HMAC-SHA256 问题(输出不匹配)
HMAC-SHA256 issue in Shopify oauth (Output does not match)
我正在尝试按照 this 文档在 Shopify 市场上发布应用程序。我被困在 oauth 文档的第 3 步,其中你必须做 'HMAC Signature Validation'.
文档指出您必须使用应用的共享密钥通过 HMAC-SHA256 处理字符串(在下面指定)。
String = "shop=some-shop.myshopify.com×tamp=1337178173"
我正在尝试使用 Java 实施这些步骤。以下是我使用的代码的要点。
private static final String HMAC_ALGORITHM = "HmacSHA256";
String key = "hush";
String data = "shop=some-shop.myshopify.com×tamp=1337178173";
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(),HMAC_ALGORITHM);
Mac mac = Mac.getInstance(HMAC_ALGORITHM);
mac.init(keySpec);
byte[] rawHmac = mac.doFinal(data.getBytes());
System.out.println(Hex.encodeHexString(rawHmac));
代码生成以下字符串:
c2812f39f84c32c2edaded339a1388abc9829babf351b684ab797f04cd94d4c7
通过在 Shopify 开发者论坛上的一些随机搜索,我发现 link 到 question。
来自 @Shayne 的最后一条消息建议我们必须通过添加 protocol
字段来更改 data
变量。
但是没有成功:(
任何人都可以告诉我应该做什么吗?我是否必须修改我的代码或文档中的过程已更改。
请帮忙。
这个例子显然是错误的。您的哈希码没问题。您需要确保包含 Shopify 响应中的所有参数,例如用于验证响应的输入如下所示:
code={code}&protocol=https://&store={store}×tamp={timestamp}
这是验证 Shopify HMAC 所需的 java 代码。协议参数不是必需的,除非它是来自 shopify 的结果,而不是来自我。
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String HMAC_ALGORITHM = "HmacSHA256";
resp.setContentType("text/html;charset=UTF-8");
Map<String,String[]> parameters = req.getParameterMap();
String data = null;
SortedSet<String> keys = new TreeSet<String>(parameters.keySet());
for (String key : keys) {
if (!key.equals("hmac")&&!key.equals("signature")){
if (data == null){
data = key + "=" +req.getParameter(key);
}
else {
data = data + "&" + key + "=" + req.getParameter(key);
}
}
}
SecretKeySpec keySpec = new SecretKeySpec(SHARED_KEY.getBytes(),HMAC_ALGORITHM);
Mac mac = null;
try {
mac = Mac.getInstance(HMAC_ALGORITHM);
mac.init(keySpec);
byte[] rawHmac = mac.doFinal(data.getBytes());
if (Hex.encodeHexString(rawHmac).equals(req.getParameter("hmac"))){
//THE HMAC IS VERIFIED
} else {
//THE HMAC IS NOT VERIFIED
}
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
e.printStackTrace();
}
}
有意思的是,data中的timestamp参数变成了
×tamp=1459537704
而不是
×tamp=1459537704
这是我的产品代码:
public class HMACValidator {
public static String sha256HMAC(String key, String data) throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException, DecoderException {
Mac hmac = Mac.getInstance("HmacSHA256");
System.out.println("data "+data);
SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
hmac.init(secret_key);
return Hex.encodeHexString(hmac.doFinal(data.getBytes("UTF-8")));
}
public static boolean validateShopifyAskForPermission(String key, String hmac, String shop, String timestamp) throws Exception {
return (sha256HMAC(key, "shop="+shop+"×tamp="+timestamp).compareTo(hmac) == 0);
}
}
我正在尝试按照 this 文档在 Shopify 市场上发布应用程序。我被困在 oauth 文档的第 3 步,其中你必须做 'HMAC Signature Validation'.
文档指出您必须使用应用的共享密钥通过 HMAC-SHA256 处理字符串(在下面指定)。
String = "shop=some-shop.myshopify.com×tamp=1337178173"
我正在尝试使用 Java 实施这些步骤。以下是我使用的代码的要点。
private static final String HMAC_ALGORITHM = "HmacSHA256";
String key = "hush";
String data = "shop=some-shop.myshopify.com×tamp=1337178173";
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(),HMAC_ALGORITHM);
Mac mac = Mac.getInstance(HMAC_ALGORITHM);
mac.init(keySpec);
byte[] rawHmac = mac.doFinal(data.getBytes());
System.out.println(Hex.encodeHexString(rawHmac));
代码生成以下字符串:
c2812f39f84c32c2edaded339a1388abc9829babf351b684ab797f04cd94d4c7
通过在 Shopify 开发者论坛上的一些随机搜索,我发现 link 到 question。
来自 @Shayne 的最后一条消息建议我们必须通过添加 protocol
字段来更改 data
变量。
但是没有成功:(
任何人都可以告诉我应该做什么吗?我是否必须修改我的代码或文档中的过程已更改。 请帮忙。
这个例子显然是错误的。您的哈希码没问题。您需要确保包含 Shopify 响应中的所有参数,例如用于验证响应的输入如下所示:
code={code}&protocol=https://&store={store}×tamp={timestamp}
这是验证 Shopify HMAC 所需的 java 代码。协议参数不是必需的,除非它是来自 shopify 的结果,而不是来自我。
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String HMAC_ALGORITHM = "HmacSHA256";
resp.setContentType("text/html;charset=UTF-8");
Map<String,String[]> parameters = req.getParameterMap();
String data = null;
SortedSet<String> keys = new TreeSet<String>(parameters.keySet());
for (String key : keys) {
if (!key.equals("hmac")&&!key.equals("signature")){
if (data == null){
data = key + "=" +req.getParameter(key);
}
else {
data = data + "&" + key + "=" + req.getParameter(key);
}
}
}
SecretKeySpec keySpec = new SecretKeySpec(SHARED_KEY.getBytes(),HMAC_ALGORITHM);
Mac mac = null;
try {
mac = Mac.getInstance(HMAC_ALGORITHM);
mac.init(keySpec);
byte[] rawHmac = mac.doFinal(data.getBytes());
if (Hex.encodeHexString(rawHmac).equals(req.getParameter("hmac"))){
//THE HMAC IS VERIFIED
} else {
//THE HMAC IS NOT VERIFIED
}
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
e.printStackTrace();
}
}
有意思的是,data中的timestamp参数变成了
×tamp=1459537704
而不是
×tamp=1459537704
这是我的产品代码:
public class HMACValidator {
public static String sha256HMAC(String key, String data) throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException, DecoderException {
Mac hmac = Mac.getInstance("HmacSHA256");
System.out.println("data "+data);
SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
hmac.init(secret_key);
return Hex.encodeHexString(hmac.doFinal(data.getBytes("UTF-8")));
}
public static boolean validateShopifyAskForPermission(String key, String hmac, String shop, String timestamp) throws Exception {
return (sha256HMAC(key, "shop="+shop+"×tamp="+timestamp).compareTo(hmac) == 0);
}
}