From 9dacff4c288614377d34b19267633960354e7221 Mon Sep 17 00:00:00 2001 From: wangwei Date: Fri, 16 Sep 2022 11:00:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81HmacSHA256=E5=8A=A0=E5=AF=86?= =?UTF-8?q?=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- src/main/java/com/zto/zop/EncryptionType.java | 3 +- src/main/java/com/zto/zop/ZopClient.java | 6 +-- src/main/java/com/zto/zop/ZopDigestUtil.java | 51 +++++++++++++++++-- .../java/com/zto/zop/ZopPublicRequest.java | 13 +++++ 5 files changed, 67 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 629361b..3ffce29 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.zto.zop zopsdk - 0.8 + 0.9 jar diff --git a/src/main/java/com/zto/zop/EncryptionType.java b/src/main/java/com/zto/zop/EncryptionType.java index e0ef9c1..a4e89fc 100644 --- a/src/main/java/com/zto/zop/EncryptionType.java +++ b/src/main/java/com/zto/zop/EncryptionType.java @@ -6,6 +6,7 @@ public enum EncryptionType { MD5, - SHA256 + SHA256, + HmacSHA256 } diff --git a/src/main/java/com/zto/zop/ZopClient.java b/src/main/java/com/zto/zop/ZopClient.java index c2b358c..451c760 100644 --- a/src/main/java/com/zto/zop/ZopClient.java +++ b/src/main/java/com/zto/zop/ZopClient.java @@ -32,16 +32,16 @@ public String execute(ZopPublicRequest request) throws IOException { strToDigest = strToDigest + properties.getKey(); Map headers = new HashMap(); headers.put("x-companyid", properties.getCompanyId()); - headers.put("x-datadigest", ZopDigestUtil.digest(strToDigest, request.getBase64(), request.getEncryptionType(), request.getTimestamp())); + headers.put("x-datadigest", ZopDigestUtil.digest(strToDigest, request.getBase64(), request.getEncryptionType(), request.getTimestamp(), request.getSecretKey())); if (request.getTimestamp() != null) { headers.put("x-timestamp", String.valueOf(request.getTimestamp())); } return HttpUtil.post(request.getUrl(), headers, queryString); } else { - Map headers = new HashMap(); + Map headers = new HashMap<>(); String strToDigest = jsonBody + properties.getKey(); headers.put("x-companyid", properties.getCompanyId()); - headers.put("x-datadigest", ZopDigestUtil.digest(strToDigest, request.getBase64(), request.getEncryptionType(), request.getTimestamp())); + headers.put("x-datadigest", ZopDigestUtil.digest(strToDigest, request.getBase64(), request.getEncryptionType(), request.getTimestamp(), request.getSecretKey())); if (request.getTimestamp() != null) { headers.put("x-timestamp", String.valueOf(request.getTimestamp())); } diff --git a/src/main/java/com/zto/zop/ZopDigestUtil.java b/src/main/java/com/zto/zop/ZopDigestUtil.java index 04fc709..b86535f 100644 --- a/src/main/java/com/zto/zop/ZopDigestUtil.java +++ b/src/main/java/com/zto/zop/ZopDigestUtil.java @@ -1,16 +1,61 @@ package com.zto.zop; import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.digest.DigestUtils; +import javax.crypto.Mac; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + public class ZopDigestUtil { - public static String digest(String str, Boolean isBase64, EncryptionType encryptionType, Long timestamp) { + private static final String HMAC_SHA_256 = "HmacSHA256"; + + private static final Map MAC_MAP = new ConcurrentHashMap<>(); + + public static String digest(String str, Boolean isBase64, EncryptionType encryptionType, Long timestamp, String secretKey) { if (timestamp != null) { str = timestamp + str; } boolean base64 = isBase64 == null || isBase64; - return base64 ? EncryptionType.SHA256.equals(encryptionType) ? Base64.encodeBase64String(DigestUtils.sha256(str)) : Base64.encodeBase64String(DigestUtils.md5(str)) - : EncryptionType.SHA256.equals(encryptionType) ? DigestUtils.sha256Hex(str) : DigestUtils.md5Hex(str); + switch (encryptionType) { + case SHA256: + return base64 ? Base64.encodeBase64String(DigestUtils.sha256(str)) : DigestUtils.sha256Hex(str); + case HmacSHA256: + return base64 ? Base64.encodeBase64String(hmacSha256(secretKey, str)) : hmacSha256Str(secretKey, str); + default: + return base64 ? Base64.encodeBase64String(DigestUtils.md5(str)) : DigestUtils.md5Hex(str); + } + } + + public static String hmacSha256Str(String key, String body) { + return Hex.encodeHexString(hmacSha256(key, body)); } + + public static byte[] hmacSha256(String key, String body) { + if (Objects.isNull(key)) { + key = ""; + } + Mac mac = MAC_MAP.get(key); + if (mac == null) { + try { + mac = Mac.getInstance(HMAC_SHA_256); + SecretKey secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), HMAC_SHA_256); + mac.init(secretKey); + MAC_MAP.put(key, mac); + } catch (NoSuchAlgorithmException | InvalidKeyException e) { + throw new RuntimeException(e); + } + } + return mac.doFinal(body.getBytes(StandardCharsets.UTF_8)); + } + } diff --git a/src/main/java/com/zto/zop/ZopPublicRequest.java b/src/main/java/com/zto/zop/ZopPublicRequest.java index a20bfa9..811037c 100644 --- a/src/main/java/com/zto/zop/ZopPublicRequest.java +++ b/src/main/java/com/zto/zop/ZopPublicRequest.java @@ -25,6 +25,11 @@ public class ZopPublicRequest { */ private EncryptionType encryptionType; + /** + * HmacSHA256加密key + */ + private String secretKey; + /** * 时间戳,如果接口文档未标识使用时间戳请不要传值,否则会导致签名错误 */ @@ -99,6 +104,14 @@ public void setEncryptionType(EncryptionType encryptionType) { this.encryptionType = encryptionType; } + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } + public Long getTimestamp() { return timestamp; }