-
Notifications
You must be signed in to change notification settings - Fork 1
/
signhelper.cpp
122 lines (96 loc) · 4.24 KB
/
signhelper.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include "signhelper.h"
QString SignHelper::generateSignature(QNetworkRequest &request, int signDurationSeconds) {
// 获取当前 Unix 时间戳
qint64 currentTime = QDateTime::currentSecsSinceEpoch();
qint64 endTime = currentTime + signDurationSeconds;
QString keyTime = QString("%1;%2").arg(currentTime).arg(endTime);
// 获取请求方法和路径
QString method = request.attribute(QNetworkRequest::CustomVerbAttribute).toString().toLower();
QString uriPath = request.url().path();
// 生成 HttpParameters 和 UrlParamList
QUrlQuery query(request.url());
QMap<QString, QString> queryParams;
for (const auto &item : query.queryItems()) {
queryParams.insert(urlEncode(item.first.toLower()), urlEncode(item.second));
}
QStringList keyList = queryParams.keys();
std::sort(keyList.begin(), keyList.end());
QString httpParameters;
QString urlParamList;
for (const auto &key : keyList) {
httpParameters += key + "=" + queryParams.value(key) + "&";
urlParamList += key + ";";
}
httpParameters.chop(1); // Remove the last '&'
urlParamList.chop(1); // Remove the last ';'
// 生成 HttpHeaders 和 HeaderList
QMap<QString, QString> headerParams;
QList<QByteArray> headerList = request.rawHeaderList();
if (headerList.isEmpty()) {
//get host from url
QString host = request.url().host();
headerParams.insert("host", urlEncode(host));
}else{
for (const auto &header : headerList) {
headerParams.insert(urlEncode(header.toLower()), urlEncode(request.rawHeader(header)));
}
}
keyList = headerParams.keys();
std::sort(keyList.begin(), keyList.end());
QString httpHeaders;
QString headerListStr;
for (const auto &key : keyList) {
httpHeaders += key + "=" + headerParams.value(key) + "&";
headerListStr += key + ";";
}
httpHeaders.chop(1); // Remove the last '&'
headerListStr.chop(1); // Remove the last ';'
// 生成 HttpString
QString httpString = QString("%1\n%2\n%3\n%4\n").arg(method, uriPath, httpParameters, httpHeaders);
//qDebug() << httpString;
// 生成 StringToSign
QString httpStringSha1 = sha1(httpString);
QString stringToSign = QString("sha1\n%1\n%2\n").arg(keyTime, httpStringSha1);
//qDebug() << stringToSign;
// 生成 SignKey
QString signKey = hmacSha1(secretKey, keyTime);
// 生成 Signature
QString signature = hmacSha1(signKey, stringToSign);
// 构造最终签名字符串
QString signatureString = QString("q-sign-algorithm=sha1&q-ak=%1&q-sign-time=%2&q-key-time=%3&q-header-list=%4&q-url-param-list=%5&q-signature=%6")
.arg(secretId, keyTime, keyTime, headerListStr, urlParamList, signature);
return signatureString;
}
QString SignHelper::hmacSha1(const QString &key, const QString &message) {
QByteArray keyBytes = key.toUtf8();
QByteArray messageBytes = message.toUtf8();
int blockSize = 64; // HMAC-SHA1 block size is 64 bytes
if (keyBytes.size() > blockSize) {
keyBytes = QCryptographicHash::hash(keyBytes, QCryptographicHash::Sha1);
}
if (keyBytes.size() < blockSize) {
keyBytes = keyBytes.leftJustified(blockSize, 0x00);
}
QByteArray oKeyPad(blockSize, 0x5c);
QByteArray iKeyPad(blockSize, 0x36);
for (int i = 0; i < blockSize; ++i) {
oKeyPad[i] = oKeyPad[i] ^ keyBytes[i];
iKeyPad[i] = iKeyPad[i] ^ keyBytes[i];
}
QByteArray innerHash = QCryptographicHash::hash(iKeyPad + messageBytes, QCryptographicHash::Sha1);
QByteArray hmac = QCryptographicHash::hash(oKeyPad + innerHash, QCryptographicHash::Sha1);
return hmac.toHex();
}
QString SignHelper::sha1(const QString &message) {
QByteArray messageBytes = message.toUtf8();
QByteArray hash = QCryptographicHash::hash(messageBytes, QCryptographicHash::Sha1);
return hash.toHex();
}
QString SignHelper::urlEncode(const QString &value) {
return QUrl::toPercentEncoding(value, "", ";/?:@&=+$,");
}
QString SignHelper::getKeyTime(int signDurationSeconds) {
qint64 currentTime = QDateTime::currentSecsSinceEpoch();
qint64 endTime = currentTime + signDurationSeconds;
return QString("%1;%2").arg(currentTime).arg(endTime);
}