废话不多说上代码,手写华为AKSK的签名校验工具类:
package com.sungolden.daihai.utils; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.Security; import java.text.SimpleDateFormat; import java.time.Instant; import java.time.ZoneId; import java.util.*; import java.util.stream.Collectors; public class SignUtils { private final static String AK= "3D0ED054-7B0B-8BDE-E2EA-AD6F35B8C4A9"; private final static String SK = "8E8EF629-FDF8-DCBA-1D94-6327E928C0EA"; //GET\n/share-api/ds/surface-water-hour/\nITEM_CODE=w21011&MONITOR_TIME=2023-11-06&POINT_CODE=20231018120001&WATER_LEVEL=3\n // host:192.168.165.2:19064\nx-sdk-date:20231115T090856Z\n\nhost;x-sdk-date\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" public static String stringToSign(String method,String host,String uri,Map<String, String> parameters,String postData,String singerDate) throws UnsupportedEncodingException { method = method.toUpperCase(Locale.ROOT); if (method != "POST" && method != "PATCH" && method != "PUT") { postData = ""; } if(StringUtils.isEmpty(postData)){ postData = ""; } // SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'", Locale.ENGLISH); // sdf.setTimeZone(TimeZone.getTimeZone("UTC")); // // String singerDate = sdf.format(new Date()); String hex = toHex(hash(postData)); if (uri.charAt(uri.length() - 1) != '/') { uri = uri.concat("/"); } String signString = method+"\n"+uri+"\n"+getCanonicalizedQueryString(parameters)+"\nhost:"+host+"\nx-sdk-date:"+singerDate+"\n\n"+"host;x-sdk-date"+"\n"+hex; byte[] signingKey = SK.getBytes(StandardCharsets.UTF_8); String stringToSign = createStringToSign(signString, singerDate); byte[] signature = computeSignature(stringToSign, signingKey); String signatureResult = buildAuthorizationHeader(signature); return signatureResult; } private static String createStringToSign(String canonicalRequest, String singerDate) { return "SDK-HMAC-SHA256" + "\n" + singerDate + "\n" + toHex(hash(canonicalRequest)); } private static String getCanonicalizedQueryString(Map<String, String> parameters) throws UnsupportedEncodingException { // 对map按照key进行排序 Map<String, String> sortedMap = parameters.entrySet().stream() .sorted(Map.Entry.comparingByKey()) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new)); StringJoiner joiner = new StringJoiner("&"); sortedMap.forEach((key, value) -> joiner.add(key + "=" + value)); String result = joiner.toString(); return result; } private static byte[] computeSignature(String stringToSign, byte[] signingKey) { return sign(stringToSign.getBytes(StandardCharsets.UTF_8), signingKey) ; } private static byte[] sign(byte[] data, byte[] key) { try { Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(key, "HmacSHA256")); return mac.doFinal(data); } catch (InvalidKeyException | NoSuchAlgorithmException var5) { return new byte[0]; } } private static String buildAuthorizationHeader(byte[] signature) { String credential = "Access=" + AK; String signerHeaders = "SignedHeaders=" + "host;x-sdk-date"; String signatureHeader = "Signature=" + toHex(signature); return "SDK-HMAC-SHA256" + " " + credential + ", " + signerHeaders + ", " + signatureHeader; } private static byte[] hash(String text) { try { MessageDigest md = MessageDigest.getInstance("SHA-256"); md.update(text.getBytes(StandardCharsets.UTF_8)); return md.digest(); } catch (NoSuchAlgorithmException var3) { return new byte[0]; } } private static String toHex(byte[] data) { StringBuffer sbuff = new StringBuffer(data.length * 2); byte[] var2 = data; int var3 = data.length; for(int var4 = 0; var4 < var3; ++var4) { byte bye = var2[var4]; String hexStr = Integer.toHexString(bye); if (hexStr.length() == 1) { sbuff.append("0"); } else if (hexStr.length() == 8) { hexStr = hexStr.substring(6); } sbuff.append(hexStr); } return sbuff.toString().toLowerCase(Locale.getDefault()); } }