/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.amazon.rankings.web.internal.util;
import com.liferay.amazon.rankings.web.configuration.AmazonRankingsConfiguration;
import com.liferay.portal.kernel.util.Base64;
import com.liferay.portal.kernel.util.CharPool;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
/**
* @author Barrie Selack
* @author Brian Wing Shun Chan
*/
public class AmazonSignedRequestsUtil {
public static String generateUrlWithSignature(
AmazonRankingsConfiguration amazonRankingsConfiguration,
Map<String, String> parameters)
throws Exception {
String canonicalizedParameters = _canonicalizeParameters(parameters);
String signature = _generateSignature(
amazonRankingsConfiguration,
"GET\necs.amazonaws.com\n/onca/xml\n" + canonicalizedParameters);
return "http://ecs.amazonaws.com/onca/xml?" + canonicalizedParameters +
"&Signature=" + signature;
}
private static String _canonicalizeParameters(
Map<String, String> parameters)
throws Exception {
if (parameters.isEmpty()) {
return StringPool.BLANK;
}
parameters = new TreeMap<>(parameters);
Set<Map.Entry<String, String>> parametersSet = parameters.entrySet();
StringBundler sb = new StringBundler(parametersSet.size() * 4);
for (Map.Entry<String, String> parameter : parametersSet) {
sb.append(_rfc3986Encode(parameter.getKey()));
sb.append(StringPool.EQUAL);
sb.append(_rfc3986Encode(parameter.getValue()));
sb.append(StringPool.AMPERSAND);
}
sb.setIndex(sb.index() - 1);
return sb.toString();
}
private static String _generateSignature(
AmazonRankingsConfiguration amazonRankingsConfiguration,
String data)
throws Exception {
if (Validator.isNull(
amazonRankingsConfiguration.amazonSecretAccessKey())) {
return StringPool.BLANK;
}
String amazonSecretAccessKey =
amazonRankingsConfiguration.amazonSecretAccessKey();
SecretKeySpec secretKeySpec = new SecretKeySpec(
amazonSecretAccessKey.getBytes(), _HMAC_SHA256_ALGORITHM);
Mac mac = Mac.getInstance(_HMAC_SHA256_ALGORITHM);
mac.init(secretKeySpec);
byte[] bytes = mac.doFinal(data.getBytes());
String signature = Base64.encode(bytes);
return StringUtil.replace(
signature, new char[] {CharPool.EQUAL, CharPool.PLUS},
new String[] {"%3D", "%2B"});
}
private static String _rfc3986Encode(String string) throws Exception {
if (Validator.isNull(string)) {
return StringPool.BLANK;
}
string = URLEncoder.encode(string, StringPool.UTF8);
string = StringUtil.replace(
string, new String[] {StringPool.STAR, StringPool.PLUS, "%7E"},
new String[] {"%2A", "%2B", "~"});
return string;
}
private static final String _HMAC_SHA256_ALGORITHM = "HmacSHA256";
}