package com.nuvole.hnnx.hnnxPay; import com.csii.sg.codec.Hex; import org.springframework.util.Assert; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.security.PrivateKey; import java.security.Signature; import java.util.*; /** * @author awlwen * @since 2017/11/30 */ public class SignatureSigner { /** * 将字节数组转换为16进制字符串 * 算法: * 将字节数组中每个字节取出后转换为16进制,截取低八位 * 将不足2位的字符前补0,解析时可按2位分隔 * * @param byteArray 字节数组 * @return 16进制字符 */ private String byteToHex(byte[] byteArray) { if (byteArray == null) { return ""; } StringBuffer sb = new StringBuffer(); for (int i = 0; i < byteArray.length; i++) { String hexString = Integer.toHexString(byteArray[i] & 0x00ff); if (hexString.length() != 2) { //如果字符长度不为2位,前补0占位 sb.append("0"); } sb.append(hexString); } return sb.toString(); } private static byte[] signLow(String plain, String algorithm, PrivateKey privateKey) { Assert.notNull(plain, "plain is null."); Assert.notNull(algorithm, "algorithm is null."); Assert.notNull(privateKey, "private key is null."); try { Signature sign = Signature.getInstance(algorithm); sign.initSign(privateKey); sign.update(plain.getBytes()); return sign.sign(); } catch (Exception ex) { throw new RuntimeException(ex); } } private static byte[] signLowByte(byte[] plain, String algorithm, PrivateKey privateKey) { Assert.notNull(plain, "plain is null."); Assert.notNull(algorithm, "algorithm is null."); Assert.notNull(privateKey, "private key is null."); try { Signature sign = Signature.getInstance(algorithm); sign.initSign(privateKey); sign.update(plain); return sign.sign(); } catch (Exception ex) { throw new RuntimeException(ex); } } public static String laBaSign(Map parameters, String accessKeySecret) { // Step 1: Sort the parameters by key in ascending order List> sortedParams = new ArrayList<>(parameters.entrySet()); Collections.sort(sortedParams, Comparator.comparing(Map.Entry::getKey)); // Step 2: Generate the string to sign StringBuilder stringToSign = new StringBuilder(); for (Map.Entry param : sortedParams) { if (param.getValue() != null && !param.getValue().isEmpty()) { stringToSign.append(param.getKey()).append("=").append(param.getValue()).append("&"); } } stringToSign.deleteCharAt(stringToSign.length() - 1); // Remove the last '&' // Step 3: Generate the signature try { Mac hmacSha256 = Mac.getInstance("HmacSHA256"); SecretKeySpec keySpec = new SecretKeySpec(accessKeySecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); hmacSha256.init(keySpec); byte[] signData = hmacSha256.doFinal(stringToSign.toString().getBytes(StandardCharsets.UTF_8)); // Step 4: Base64 encode the signature return Base64.getEncoder().encodeToString(signData); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 使用提供的算法与私钥对交易数据签名 * * @param plain 交易数据明文 * @param privateKey java.security.PrivateKey 私钥 * @return 签名 */ public String sign(String plain, PrivateKey privateKey) { byte[] bytes = signLow(plain, HnnxConstant.ALGORITHM, privateKey); return Hex.toHex(bytes); } /** * 快捷支付sign * * @param plain * @param privateKey * @return */ public String kjSign(String plain, PrivateKey privateKey) { byte[] bytes = new byte[0]; try { bytes = signLowByte(plain.getBytes("utf-8"), HnnxConstant.KJ_ALGORITHM, privateKey); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return Base64.getEncoder().encodeToString(bytes); } }