我发送了包含相同内容的请求,包括像是在JUnit中将德国变音符号和哈希值转换为春季Web应用程序。但是HMAC加密的工作方式不同。 HMAC加密可以在JUnit上对与设置散列相同的散列进行加密。设置哈希值是从另一台服务器加密的,并发送到我的Spring Web应用程序。
发送请求到tomcat并启动hmac验证器
allValues [51, 54, 49, 50, 50, 50, 57, 51, 57, 52, 49, 51, 55, 52, 46, 57, 53, 50, 51, 48, 50, 77, 97, 110, 117, 101, 108, 32, 71, 110, 101, 114, 108, 105, 99, 104, 52, 50, 54, 51, 53, 52, 120, 120, 120, 120, 120, 120, 57, 52, 54, 56, 86, 72, 97, 109, 98, 117, 114, 103, 99, 99, 68, 69, 69, 85, 82, 49, 52, 50, 49, 51, 32, 77, 111, 110, 97, 116, 101, 32, 84, 101, 105, 108, 110, 97, 104, 109, 101, 118, 101, 114, 103, -61, -68, 116, 117, 110, 103, 32, 102, -61, -68, 114, 32, 68, 71, 83, 32, 40, 100, 101, 114, 122, 101, 105, 116, 32, 76, 101, 118, 101, 108, 32, 65, 49, 41, 97, 114, 103, 111, 110, 105, 115, 116, 64, 103, 109, 97, 105, 108, 46, 99, 111, 109, 49, 53, 54, 48, 48, 57, 55, 53, 55, 51, 77, 97, 110, 117, 101, 108, 57, 51, 54, 50, 53, 49, 51, 52, 101, 57, 54, 102, 53, 56, 48, 54, 100, 99, 53, 98, 99, 57, 101, 53, 98, 98, 57, 53, 57, 55, 53, 53, 51, 56, 56, 102, 71, 110, 101, 114, 108, 105, 99, 104, 116, 101, 115, 116, 49, 55, 46, 52, 97, 99, 99, 101, 115, 115, 45, 49, 52, 50, 49, 45, 48, 45, 48, 45, 51, 51, 56, 55, 57, 55, 52, 46, 57, 53, 55, 52, 46, 57, 53, 57, 51, 54, 50, 55, 52, 46, 57, 53, 49, 52, 50, 49, 45, 56, 98, 49, 99, 55, 48, 98, 101, 49, 56, 97, 57, 48, 83, 116, 114, 105, 110, 100, 98, 101, 114, 103, 119, 101, 103, 32, 49, 50, 51, 32, 77, 111, 110, 97, 116, 101, 32, 65, 98, 111, 32, 45, 32, 109, 97, 110, 105, 109, 117, 110, 100, 111, 99, 111, 109, 112, 108, 101, 116, 101, 100, 97, 112, 112, 111, 105, 110, 116, 101, 100, 51, 50, 49, 54, 55, 51, 52, 56, 55, 49, 53, 53, 50, 49, 53, 50, 51, 55, 51, 49, 53, 55, 57, 52, 57, 57, 48, 48, 49, 57, 46, 48, 48, 50, 50, 53, 56, 55]
hmac hash 5dffe6e4b92ff855411a73eea34d74909e25678b1b768dcb8081dd764200f7fefa710beacf26b5d141c362fa5a3ea9ed
hash 65e2f454df692db7ccb34c49e71349dc351f62ca47eaca2a08ddb6c5baa634d9baa691358c69361dc01d7f73681820ed
从jUnit hmac验证器开始
allValues [51, 54, 49, 50, 50, 50, 57, 51, 57, 52, 49, 51, 55, 52, 46, 57, 53, 50, 51, 48, 50, 77, 97, 110, 117, 101, 108, 32, 71, 110, 101, 114, 108, 105, 99, 104, 52, 50, 54, 51, 53, 52, 120, 120, 120, 120, 120, 120, 57, 52, 54, 56, 86, 72, 97, 109, 98, 117, 114, 103, 99, 99, 68, 69, 69, 85, 82, 49, 52, 50, 49, 51, 32, 77, 111, 110, 97, 116, 101, 32, 84, 101, 105, 108, 110, 97, 104, 109, 101, 118, 101, 114, 103, -61, -68, 116, 117, 110, 103, 32, 102, -61, -68, 114, 32, 68, 71, 83, 32, 40, 100, 101, 114, 122, 101, 105, 116, 32, 76, 101, 118, 101, 108, 32, 65, 49, 41, 97, 114, 103, 111, 110, 105, 115, 116, 64, 103, 109, 97, 105, 108, 46, 99, 111, 109, 49, 53, 54, 48, 48, 57, 55, 53, 55, 51, 77, 97, 110, 117, 101, 108, 57, 51, 54, 50, 53, 49, 51, 52, 101, 57, 54, 102, 53, 56, 48, 54, 100, 99, 53, 98, 99, 57, 101, 53, 98, 98, 57, 53, 57, 55, 53, 53, 51, 56, 56, 102, 71, 110, 101, 114, 108, 105, 99, 104, 116, 101, 115, 116, 49, 55, 46, 52, 97, 99, 99, 101, 115, 115, 45, 49, 52, 50, 49, 45, 48, 45, 48, 45, 51, 51, 56, 55, 57, 55, 52, 46, 57, 53, 55, 52, 46, 57, 53, 57, 51, 54, 50, 55, 52, 46, 57, 53, 49, 52, 50, 49, 45, 56, 98, 49, 99, 55, 48, 98, 101, 49, 56, 97, 57, 48, 83, 116, 114, 105, 110, 100, 98, 101, 114, 103, 119, 101, 103, 32, 49, 50, 51, 32, 77, 111, 110, 97, 116, 101, 32, 65, 98, 111, 32, 45, 32, 109, 97, 110, 105, 109, 117, 110, 100, 111, 99, 111, 109, 112, 108, 101, 116, 101, 100, 97, 112, 112, 111, 105, 110, 116, 101, 100, 51, 50, 49, 54, 55, 51, 52, 56, 55, 49, 53, 53, 50, 49, 53, 50, 51, 55, 51, 49, 53, 55, 57, 52, 57, 57, 48, 48, 49, 57, 46, 48, 48, 50, 50, 53, 56, 55]
hmac hash 65e2f454df692db7ccb34c49e71349dc351f62ca47eaca2a08ddb6c5baa634d9baa691358c69361dc01d7f73681820ed
hash 65e2f454df692db7ccb34c49e71349dc351f62ca47eaca2a08ddb6c5baa634d9baa691358c69361dc01d7f73681820ed
源代码:
@Component
public class HMACValidator {
private final SevDeskProperties sevDeskProperties;
public HMACValidator(SevDeskProperties sevDeskProperties) {
this.sevDeskProperties = sevDeskProperties;
}
public void validateHMAC(TransactionPayOne transactionPayOne, String hash) {
byte[] key = transactionPayOne.getPortalid()
.equals(sevDeskProperties.getAboPortalId()) ?
sevDeskProperties.getAboKey().getBytes() :
sevDeskProperties.getSingleKey().getBytes();
String allValues = getAllValues(transactionPayOne);
logger.debug("allValues " + allValues);
String hmacSha384Encode;
try {
logger.debug("allValues" + Arrays.toString(allValues.getBytes("UTF-8")));
hmacSha384Encode = HMAC_SHA384_encode(key, allValues);
} catch (Exception e) {
throw new IllegalArgumentException("Could not encode the values",e);
}
logger.debug("hmac hash " + hmacSha384Encode);
logger.debug("hash " + hash);
if (!hmacSha384Encode.equals(hash)) {
throw new IllegalArgumentException("message is not valid ");
}
}
public static String HMAC_SHA384_encode(byte[] key, String message) throws Exception {
SecretKeySpec keySpec = new SecretKeySpec(
key, HmacAlgorithms.HMAC_SHA_384.getName());
Mac mac = Mac.getInstance(HmacAlgorithms.HMAC_SHA_384.getName());
mac.init(keySpec);
byte[] rawHmac = mac.doFinal(message.getBytes("UTF-8"));
return Hex.encodeHexString(rawHmac);
}
// Getting all values without key in json of transaction data
private String getAllValues(TransactionPayOne transactionPayOne) {
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> mapJson;
try {
mapJson = objectMapper.readValue(transactionPayOne.getJson().getBytes("UTF-8"), new TypeReference<Map<String, Object>>() {
});
} catch (IOException e) {
e.printStackTrace();
throw new IllegalArgumentException("Could not parse json");
}
return mapJson.values().stream().map(value -> {
if (value instanceof Map) {
value = ((Map) value).values().stream().collect(Collectors.joining(""));
}
return (String) value;
}).collect(Collectors.joining(""));
}
}