20 #include "awssignaturev4.h"
21 #include "awssignaturev4_p.h"
23 #include "awsendpoint.h"
27 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) && QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
28 #include "qmessageauthenticationcode.h"
30 #include <QMessageAuthenticationCode>
61 const QNetworkAccessManager::Operation operation,
62 QNetworkRequest &request,
const QByteArray &data)
const
65 d->setAuthorizationHeader(credentials, operation, request, data, d->setDateHeader(request));
120 case QCryptographicHash::Md4:
return "AWS4-HMAC-MD4";
121 case QCryptographicHash::Md5:
return "AWS4-HMAC-MD5";
122 case QCryptographicHash::Sha1:
return "AWS4-HMAC-SHA1";
123 case QCryptographicHash::Sha224:
return "AWS4-HMAC-SHA224";
124 case QCryptographicHash::Sha256:
return "AWS4-HMAC-SHA256";
125 case QCryptographicHash::Sha384:
return "AWS4-HMAC-SHA384";
126 case QCryptographicHash::Sha512:
return "AWS4-HMAC-SHA512";
128 Q_ASSERT_X(
false, Q_FUNC_INFO,
"invalid algorithm");
129 return "invalid-algorithm";
152 const QNetworkAccessManager::Operation operation,
153 QNetworkRequest &request,
const QByteArray &payload,
154 const QDateTime ×tamp)
const
160 QByteArray signedHeaders;
163 const QByteArray
stringToSign = this->
stringToSign(algorithmDesignation, timestamp, credentialScope, canonicalRequest);
164 const QByteArray
signingKey = this->
signingKey(credentials, timestamp.date(), endpoint.regionName(), endpoint.serviceName());
165 const QByteArray signature = QMessageAuthenticationCode::hash(stringToSign, signingKey,
hashAlgorithm);
167 return algorithmDesignation +
" Credential=" + credentials.
accessKeyId().toUtf8() +
'/' + credentialScope +
168 ", SignedHeaders=" + signedHeaders +
", Signature=" + signature.toHex();
188 QByteArray header = headerName.toLower() +
':';
189 const QByteArray trimmedHeaderValue = headerValue.trimmed();
190 bool isInQuotes =
false;
191 char previousChar =
'\0';
192 for (
int index = 0; index < trimmedHeaderValue.size(); ++index) {
193 char thisChar = trimmedHeaderValue.at(index);
196 if ((thisChar ==
'"') && (previousChar !=
'\\'))
199 if ((thisChar ==
'"') && (previousChar !=
'\\')) {
201 }
else if (isspace(thisChar)) {
202 while ((index < trimmedHeaderValue.size()-1) &&
203 (isspace(trimmedHeaderValue.at(index+1))))
207 previousChar = thisChar;
235 Q_CHECK_PTR(signedHeaders);
236 signedHeaders->clear();
244 QMap<QByteArray,QByteArray> headers;
245 foreach (
const QByteArray &rawHeader, request.rawHeaderList()) {
246 headers.insert(rawHeader.toLower(), request.rawHeader(rawHeader));
249 headers.insert(
"host", request.url().host().toUtf8());
253 for (QMap<QByteArray,QByteArray>::const_iterator iter = headers.constBegin(); iter != headers.constEnd(); ++iter) {
255 if (!signedHeaders->isEmpty()) *signedHeaders +=
';';
256 *signedHeaders += iter.key();
275 const QNetworkRequest &request,
const QByteArray &payload,
276 QByteArray *
const signedHeaders)
const
278 return httpMethod(operation).toUtf8() +
'\n' +
282 *signedHeaders +
'\n' +
299 return date.toString(
DateFormat).toUtf8() +
'/' + region.toUtf8() +
'/' + service.toUtf8() +
"/aws4_request";
318 const QNetworkAccessManager::Operation operation,
319 QNetworkRequest &request,
const QByteArray &payload,
320 const QDateTime ×tamp)
const
322 Q_ASSERT(!request.hasRawHeader(
"Authorization"));
323 request.setRawHeader(
"Authorization",
authorizationHeaderValue(credentials, operation, request, payload, timestamp));
341 Q_ASSERT(!request.hasRawHeader(
"x-amz-date"));
342 request.setRawHeader(
"x-amz-date", dateTime.toString(
DateTimeFormat).toUtf8());
359 const QString ®ion,
const QString &service)
const
361 return QMessageAuthenticationCode::hash(
"aws4_request",
362 QMessageAuthenticationCode::hash(service.toUtf8(),
363 QMessageAuthenticationCode::hash(region.toUtf8(),
364 QMessageAuthenticationCode::hash(date.toString(
DateFormat).toUtf8(),
"AWS4"+credentials.
secretKey().toUtf8(),
384 const QByteArray &credentialScope,
const QByteArray &canonicalRequest)
const
386 return algorithmDesignation +
'\n' +
388 credentialScope +
'\n' +
389 QCryptographicHash::hash(canonicalRequest,
hashAlgorithm).toHex();
QDateTime setDateHeader(QNetworkRequest &request, const QDateTime &dateTime=QDateTime::currentDateTimeUtc()) const
Set the AWS custom date header.
static const QLatin1String DateFormat
Format V4 signatures use to represent dates in canonical form.
const QCryptographicHash::Algorithm hashAlgorithm
Hash algorithm to use when signing.
Private implementation for AwsSignatureV4.
QByteArray authorizationHeaderValue(const AwsAbstractCredentials &credentials, const QNetworkAccessManager::Operation operation, QNetworkRequest &request, const QByteArray &payload, const QDateTime ×tamp) const
Create an AWS V4 Signature authorization header value.
virtual void sign(const AwsAbstractCredentials &credentials, const QNetworkAccessManager::Operation operation, QNetworkRequest &request, const QByteArray &data=QByteArray()) const
Sign an AWS request.
QByteArray algorithmDesignation(const QCryptographicHash::Algorithm algorithm) const
Create an AWS V4 Signature algorithm designation.
void setAuthorizationHeader(const AwsAbstractCredentials &credentials, const QNetworkAccessManager::Operation operation, QNetworkRequest &request, const QByteArray &payload, const QDateTime ×tamp) const
Set authorization header on a network request.
Private implementation for AwsAbstractSignature.
QByteArray canonicalQuery(const QUrlQuery &query) const
Create an AWS Signature canonical query.
virtual QString secretKey() const =0
AWS secret access key for this credentials object.
virtual int version() const
AWS Signature version implemented by this class.
Interface class for providing AWS credentials.
QByteArray canonicalHeaders(const QNetworkRequest &request, QByteArray *const signedHeaders) const
Create an AWS V4 Signature canonical headers string.
Provides AWS endpoint information.
AwsSignatureV4Private(const QCryptographicHash::Algorithm hashAlgorithm, AwsSignatureV4 *const q)
Constructs a new AwsSignatureV4Private object.
Implements AWS Signature Version 4.
virtual QString accessKeyId() const =0
AWS access key ID for this credentials object.
QByteArray canonicalRequest(const QNetworkAccessManager::Operation operation, const QNetworkRequest &request, const QByteArray &payload, QByteArray *const signedHeaders) const
Create an AWS V4 Signature canonical request.
static const QLatin1String DateTimeFormat
Format V4 signatures use to represent timestamps in canonical form.
QByteArray stringToSign(const QByteArray &algorithmDesignation, const QDateTime &requestDate, const QByteArray &credentialScope, const QByteArray &canonicalRequest) const
Create an AWS V4 Signature string to sign.
QByteArray credentialScope(const QDate &date, const QString ®ion, const QString &service) const
Create an AWS V4 Signature credential scope.
AwsSignatureV4(const QCryptographicHash::Algorithm hashAlgorithm=QCryptographicHash::Sha256)
Constructs a new AwsSignatureV4 object.
QByteArray signingKey(const AwsAbstractCredentials &credentials, const QDate &date, const QString ®ion, const QString &service) const
Create an AWS V4 Signature signing key.
QByteArray canonicalHeader(const QByteArray &headerName, const QByteArray &headerValue) const
Create an AWS V4 Signature canonical header string.
QString httpMethod(const QNetworkAccessManager::Operation operation) const
Create an AWS Signature request method string.
Interface class for providing AWS signatures.
QString canonicalPath(const QUrl &url) const
Create an AWS Signature canonical path.