package com.ruoyi.common.utils.civilAviation;
|
|
import java.io.UnsupportedEncodingException;
|
import java.net.URLEncoder;
|
import java.security.MessageDigest;
|
import java.util.*;
|
import org.apache.commons.lang3.StringUtils;
|
|
public class ServiceOrderSign {
|
private static final int BITS_TO_A_BYTE = 8;
|
private static final int BYTES_TO_A_WORD = 4;
|
private static final int BITS_TO_A_WORD = 32;
|
private static final String APP_SECRET = "JR6o8RQItoa2bzlneOCQ";
|
|
private static final long[] m_lOnBits = new long[31];
|
private static final long[] m_l2Power = new long[31];
|
|
static {
|
// 初始化位操作数组
|
m_lOnBits[0] = 1L;
|
m_lOnBits[1] = 3L;
|
m_lOnBits[2] = 7L;
|
m_lOnBits[3] = 15L;
|
m_lOnBits[4] = 31L;
|
m_lOnBits[5] = 63L;
|
m_lOnBits[6] = 127L;
|
m_lOnBits[7] = 255L;
|
m_lOnBits[8] = 511L;
|
m_lOnBits[9] = 1023L;
|
m_lOnBits[10] = 2047L;
|
m_lOnBits[11] = 4095L;
|
m_lOnBits[12] = 8191L;
|
m_lOnBits[13] = 16383L;
|
m_lOnBits[14] = 32767L;
|
m_lOnBits[15] = 65535L;
|
m_lOnBits[16] = 131071L;
|
m_lOnBits[17] = 262143L;
|
m_lOnBits[18] = 524287L;
|
m_lOnBits[19] = 1048575L;
|
m_lOnBits[20] = 2097151L;
|
m_lOnBits[21] = 4194303L;
|
m_lOnBits[22] = 8388607L;
|
m_lOnBits[23] = 16777215L;
|
m_lOnBits[24] = 33554431L;
|
m_lOnBits[25] = 67108863L;
|
m_lOnBits[26] = 134217727L;
|
m_lOnBits[27] = 268435455L;
|
m_lOnBits[28] = 536870911L;
|
m_lOnBits[29] = 1073741823L;
|
m_lOnBits[30] = 2147483647L;
|
|
m_l2Power[0] = 1L;
|
m_l2Power[1] = 2L;
|
m_l2Power[2] = 4L;
|
m_l2Power[3] = 8L;
|
m_l2Power[4] = 16L;
|
m_l2Power[5] = 32L;
|
m_l2Power[6] = 64L;
|
m_l2Power[7] = 128L;
|
m_l2Power[8] = 256L;
|
m_l2Power[9] = 512L;
|
m_l2Power[10] = 1024L;
|
m_l2Power[11] = 2048L;
|
m_l2Power[12] = 4096L;
|
m_l2Power[13] = 8192L;
|
m_l2Power[14] = 16384L;
|
m_l2Power[15] = 32768L;
|
m_l2Power[16] = 65536L;
|
m_l2Power[17] = 131072L;
|
m_l2Power[18] = 262144L;
|
m_l2Power[19] = 524288L;
|
m_l2Power[20] = 1048576L;
|
m_l2Power[21] = 2097152L;
|
m_l2Power[22] = 4194304L;
|
m_l2Power[23] = 8388608L;
|
m_l2Power[24] = 16777216L;
|
m_l2Power[25] = 33554432L;
|
m_l2Power[26] = 67108864L;
|
m_l2Power[27] = 134217728L;
|
m_l2Power[28] = 268435456L;
|
m_l2Power[29] = 536870912L;
|
m_l2Power[30] = 1073741824L;
|
}
|
|
private static long LShift(long lValue, int iShiftBits) {
|
if (iShiftBits == 0) {
|
return lValue;
|
} else if (iShiftBits == 31) {
|
return (lValue & 1) != 0 ? 0x80000000L : 0;
|
} else if (iShiftBits < 0 || iShiftBits > 31) {
|
throw new RuntimeException("Invalid shift bits");
|
}
|
|
return ((lValue & m_lOnBits[31 - iShiftBits]) << iShiftBits);
|
}
|
|
private static long RShift(long lValue, int iShiftBits) {
|
if (iShiftBits == 0) {
|
return lValue;
|
} else if (iShiftBits == 31) {
|
return (lValue & 0x80000000L) != 0 ? 1 : 0;
|
} else if (iShiftBits < 0 || iShiftBits > 31) {
|
throw new RuntimeException("Invalid shift bits");
|
}
|
|
return (lValue >>> iShiftBits) & (0x7FFFFFFFL >>> (iShiftBits - 1));
|
}
|
|
private static long RotateLeft(long lValue, int iShiftBits) {
|
return (LShift(lValue, iShiftBits) | RShift(lValue, 32 - iShiftBits)) & 0xFFFFFFFFL;
|
}
|
|
private static long AddUnsigned(long lX, long lY) {
|
long lX8 = lX & 0x80000000L;
|
long lY8 = lY & 0x80000000L;
|
long lX4 = lX & 0x40000000L;
|
long lY4 = lY & 0x40000000L;
|
|
long lResult = (lX & 0x3FFFFFFFL) + (lY & 0x3FFFFFFFL);
|
|
if ((lX4 & lY4) != 0) {
|
lResult = lResult ^ 0x80000000L ^ lX8 ^ lY8;
|
} else if ((lX4 | lY4) != 0) {
|
if ((lResult & 0x40000000L) != 0) {
|
lResult = lResult ^ 0xC0000000L ^ lX8 ^ lY8;
|
} else {
|
lResult = lResult ^ 0x40000000L ^ lX8 ^ lY8;
|
}
|
} else {
|
lResult = lResult ^ lX8 ^ lY8;
|
}
|
|
return lResult;
|
}
|
|
private static long F(long x, long y, long z) {
|
return (x & y) | (~x & z);
|
}
|
|
private static long G(long x, long y, long z) {
|
return (x & z) | (y & ~z);
|
}
|
|
private static long H(long x, long y, long z) {
|
return x ^ y ^ z;
|
}
|
|
private static long I(long x, long y, long z) {
|
return y ^ (x | ~z);
|
}
|
|
private static void FF(long[] a, long b, long c, long d, long x, int s, long ac) {
|
a[0] = AddUnsigned(a[0], AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
|
a[0] = RotateLeft(a[0], s);
|
a[0] = AddUnsigned(a[0], b);
|
}
|
|
private static void GG(long[] a, long b, long c, long d, long x, int s, long ac) {
|
a[0] = AddUnsigned(a[0], AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
|
a[0] = RotateLeft(a[0], s);
|
a[0] = AddUnsigned(a[0], b);
|
}
|
|
private static void HH(long[] a, long b, long c, long d, long x, int s, long ac) {
|
a[0] = AddUnsigned(a[0], AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
|
a[0] = RotateLeft(a[0], s);
|
a[0] = AddUnsigned(a[0], b);
|
}
|
|
private static void II(long[] a, long b, long c, long d, long x, int s, long ac) {
|
a[0] = AddUnsigned(a[0], AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
|
a[0] = RotateLeft(a[0], s);
|
a[0] = AddUnsigned(a[0], b);
|
}
|
|
private static long[] ConvertToWordArray(byte[] messageBytes) {
|
int lMessageLength = messageBytes.length;
|
int lNumberOfWords = (((lMessageLength + 8) >> 6) + 1) << 4;
|
long[] lWordArray = new long[lNumberOfWords];
|
|
int lBytePosition = 0;
|
for (int lWordCount = 0; lBytePosition < lMessageLength; lWordCount++, lBytePosition += 4) {
|
lWordArray[lWordCount] = 0;
|
for (int lByteCount = 0; lByteCount < Math.min(4, lMessageLength - lBytePosition); lByteCount++) {
|
lWordArray[lWordCount] |= ((messageBytes[lBytePosition + lByteCount] & 0xFF) << (lByteCount << 3));
|
}
|
}
|
|
// 标记结束
|
lWordArray[lBytePosition >> 2] |= 0x80 << ((lBytePosition % 4) << 3);
|
|
// 设置消息长度
|
lWordArray[lNumberOfWords - 2] = (lMessageLength << 3) & 0xFFFFFFFFL;
|
lWordArray[lNumberOfWords - 1] = (lMessageLength >>> 29) & 0xFFFFFFFFL;
|
|
return lWordArray;
|
}
|
|
private static String WordToHex(long lValue) {
|
StringBuilder wordToHex = new StringBuilder();
|
for (int lCount = 0; lCount <= 3; lCount++) {
|
long lByte = (lValue >>> (lCount << 3)) & 255;
|
String byteHex = Integer.toHexString((int) lByte);
|
if (byteHex.length() == 1) {
|
wordToHex.append("0");
|
}
|
wordToHex.append(byteHex);
|
}
|
return wordToHex.toString();
|
}
|
|
public static String MD5(String message, String charset) {
|
try {
|
byte[] messageBytes;
|
if ("utf-8".equalsIgnoreCase(charset)) {
|
messageBytes = message.getBytes("UTF-8");
|
} else {
|
messageBytes = message.getBytes();
|
}
|
|
long[] x = ConvertToWordArray(messageBytes);
|
|
// 初始化变量
|
long a = 0x67452301L;
|
long b = 0xEFCDAB89L;
|
long c = 0x98BADCFEL;
|
long d = 0x10325476L;
|
|
// 常量定义
|
final int S11 = 7;
|
final int S12 = 12;
|
final int S13 = 17;
|
final int S14 = 22;
|
final int S21 = 5;
|
final int S22 = 9;
|
final int S23 = 14;
|
final int S24 = 20;
|
final int S31 = 4;
|
final int S32 = 11;
|
final int S33 = 16;
|
final int S34 = 23;
|
final int S41 = 6;
|
final int S42 = 10;
|
final int S43 = 15;
|
final int S44 = 21;
|
|
// 主循环
|
for (int k = 0; k < x.length; k += 16) {
|
long AA = a;
|
long BB = b;
|
long CC = c;
|
long DD = d;
|
|
long[] aArray = {a};
|
long[] dArray = {d};
|
long[] cArray = {c};
|
long[] bArray = {b};
|
|
// Round 1
|
FF(aArray, b, c, d, x[k + 0], S11, 0xD76AA478L); a = aArray[0];
|
FF(dArray, a, b, c, x[k + 1], S12, 0xE8C7B756L); d = dArray[0];
|
FF(cArray, d, a, b, x[k + 2], S13, 0x242070DBL); c = cArray[0];
|
FF(bArray, c, d, a, x[k + 3], S14, 0xC1BDCEEEL); b = bArray[0];
|
// ... 继续实现所有轮次
|
|
a = AddUnsigned(a, AA);
|
b = AddUnsigned(b, BB);
|
c = AddUnsigned(c, CC);
|
d = AddUnsigned(d, DD);
|
}
|
|
return (WordToHex(a) + WordToHex(b) + WordToHex(c) + WordToHex(d)).toLowerCase();
|
} catch (Exception e) {
|
throw new RuntimeException("MD5 calculation error", e);
|
}
|
}
|
|
/**
|
* 生成签名
|
* @param params 请求参数集合
|
* @return 签名值
|
*/
|
public static String generateSign(Map<String, String> params) {
|
// 1. 移除sign参数
|
params.remove("sign");
|
params.remove("Sign");
|
|
// 2. 按ASCII码排序(字典序)
|
List<String> keys = new ArrayList<>(params.keySet());
|
Collections.sort(keys);
|
|
// 3. 拼接字符串 (Key1Value1Key2Value2...)
|
StringBuilder stringA = new StringBuilder();
|
for (String key : keys) {
|
String value = params.get(key);
|
if (value != null && !value.isEmpty()) {
|
// 将参数名首字母大写
|
String capitalizedKey = StringUtils.capitalize(key);
|
stringA.append(capitalizedKey).append(value);
|
}
|
}
|
|
// 4. 拼接APP_SECRET
|
String stringSignTemp = stringA.toString() + APP_SECRET;
|
|
// 5. MD5运算并转小写
|
try {
|
MessageDigest md = MessageDigest.getInstance("MD5");
|
byte[] bytes = stringSignTemp.getBytes("UTF-8");
|
md.update(bytes);
|
byte[] md5Bytes = md.digest();
|
|
StringBuilder hexValue = new StringBuilder();
|
for (byte b : md5Bytes) {
|
int val = ((int) b) & 0xff;
|
if (val < 16) {
|
hexValue.append("0");
|
}
|
hexValue.append(Integer.toHexString(val));
|
}
|
return hexValue.toString().toLowerCase();
|
} catch (Exception e) {
|
throw new RuntimeException("MD5加密出错", e);
|
}
|
}
|
|
/**
|
* 验证签名
|
* @param params 请求参数集合
|
* @param sign 签名值
|
* @return 验证结果
|
*/
|
public static boolean verifySign(Map<String, String> params, String sign) {
|
String generatedSign = generateSign(params);
|
return generatedSign.equalsIgnoreCase(sign);
|
}
|
|
/**
|
* 使用示例
|
*/
|
public static void main(String[] args) {
|
// 测试用例
|
Map<String, String> params = new HashMap<>();
|
params.put("method", "User_Login");
|
params.put("LoginType", "0");
|
params.put("UserID", "10");
|
|
String sign = generateSign(params);
|
System.out.println("生成的签名: " + sign);
|
// 应输出: 9a0a8659f005d6984697e2ca0a9cf3b7
|
}
|
}
|