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.