如果你的API服務安全認證協議中要求使用hmac_sha1方法對信息進行編碼,
而你的服務是由PHP實現的,客戶端是由JAVA實現的,那麼為了對簽名正確比對,就需要在兩者之間建立能匹配的編碼方式.
PHP側如下:
- define('ID','123456');
- define('KEY','k123456');
-
- $strToSign = "test_string";
-
- $utf8Str = mb_convert_encoding($strToSign, "UTF-8");
- $hmac_sha1_str = base64_encode(hash_hmac("sha1", $utf8Str, KEY));
- $signature = urlencode($hmac_sha1_str);
- print_r($signature);
JAVA側需要注意如下幾點:
1. hmac_sha1編碼結果需要轉換成hex格式
2. java中base64的實現和php不一致,其中java並不會在字符串末尾填補=號以把字節數補充為8的整數
3. hmac_sha1並非sha1, hmac_sha1是需要共享密鑰的
參考實現如下:
- import java.io.UnsupportedEncodingException;
- import javax.crypto.Mac;
- import javax.crypto.spec.SecretKeySpec;
- import org.apache.wicket.util.crypt.Base64UrlSafe;
-
- public class test {
- public static void main(String[] args) {
- String key = "f85b8b30f73eb2bf5d8063a9224b5e90";
- String toHash = "GET"+"\n"+"Thu, 09 Aug 2012 13:33:46 +0000"+"\n"+"/ApiChannel/Report.m";
- //String toHashUtf8 = URLEncoder.encode(toHash, "UTF-8");
- String res = hmac_sha1(toHash, key);
- //System.out.print(res+"\n");
-
- String signature;
- try {
- signature = new String(Base64UrlSafe.encodeBase64(res.getBytes()),"UTF-8");
- signature = appendEqualSign(signature);
- System.out.print(signature);
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- }
-
- public static String hmac_sha1(String value, String key) {
- try {
- // Get an hmac_sha1 key from the raw key bytes
- byte[] keyBytes = key.getBytes();
- SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA1");
-
- // Get an hmac_sha1 Mac instance and initialize with the signing key
- Mac mac = Mac.getInstance("HmacSHA1");
- mac.init(signingKey);
-
- // Compute the hmac on input data bytes
- byte[] rawHmac = mac.doFinal(value.getBytes());
-
- // Convert raw bytes to Hex
- String hexBytes = byte2hex(rawHmac);
- return hexBytes;
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- private static String byte2hex(final byte[] b){
- String hs="";
- String stmp="";
- for (int n=0; n<b.length; n++){
- stmp=(java.lang.Integer.toHexString(b[n] & 0xFF));
- if (stmp.length()==1) hs=hs+"0"+stmp;
- else hs=hs+stmp;
- }
- return hs;
- }
-
- private static String appendEqualSign(String s){
- int len = s.length();
- int appendNum = 8 - (int)(len/8);
- for (int n=0; n<appendNum; n++){
- s += "%3D";
- }
- return s;
- }
- }