libqtaws  0.1.0
UnofficialAWSlibraryforQt-InternalDocumentation
Public Member Functions | Protected Member Functions | Protected Attributes | Static Protected Attributes | Friends | List of all members
AwsSignatureV4Private Class Reference

Private implementation for AwsSignatureV4. More...

Inheritance diagram for AwsSignatureV4Private:
Inheritance graph
[legend]
Collaboration diagram for AwsSignatureV4Private:
Collaboration graph
[legend]

Public Member Functions

 AwsSignatureV4Private (const QCryptographicHash::Algorithm hashAlgorithm, AwsSignatureV4 *const q)
 Constructs a new AwsSignatureV4Private object. More...
 
void setAuthorizationHeader (const AwsAbstractCredentials &credentials, const QNetworkAccessManager::Operation operation, QNetworkRequest &request, const QByteArray &payload, const QDateTime &timestamp) const
 Set authorization header on a network request. More...
 
QDateTime setDateHeader (QNetworkRequest &request, const QDateTime &dateTime=QDateTime::currentDateTimeUtc()) const
 Set the AWS custom date header. More...
 
- Public Member Functions inherited from AwsAbstractSignaturePrivate
virtual ~AwsAbstractSignaturePrivate ()
 AwsAbstractSignaturePrivate destructor. More...
 
 AwsAbstractSignaturePrivate (AwsAbstractSignature *const q)
 Constructs a new AwsAbstractSignaturePrivate object. More...
 
QString canonicalPath (const QUrl &url) const
 Create an AWS Signature canonical path. More...
 
QByteArray canonicalQuery (const QUrlQuery &query) const
 Create an AWS Signature canonical query. More...
 
QString httpMethod (const QNetworkAccessManager::Operation operation) const
 Create an AWS Signature request method string. More...
 
bool setQueryItem (QUrlQuery &query, const QString &key, const QString &value, const bool warnOnNonIdenticalDuplicate=true) const
 Set a query item, checking for existing values first. More...
 

Protected Member Functions

QByteArray algorithmDesignation (const QCryptographicHash::Algorithm algorithm) const
 Create an AWS V4 Signature algorithm designation. More...
 
QByteArray authorizationHeaderValue (const AwsAbstractCredentials &credentials, const QNetworkAccessManager::Operation operation, QNetworkRequest &request, const QByteArray &payload, const QDateTime &timestamp) const
 Create an AWS V4 Signature authorization header value. More...
 
QByteArray canonicalHeader (const QByteArray &headerName, const QByteArray &headerValue) const
 Create an AWS V4 Signature canonical header string. More...
 
QByteArray canonicalHeaders (const QNetworkRequest &request, QByteArray *const signedHeaders) const
 Create an AWS V4 Signature canonical headers string. More...
 
QByteArray canonicalRequest (const QNetworkAccessManager::Operation operation, const QNetworkRequest &request, const QByteArray &payload, QByteArray *const signedHeaders) const
 Create an AWS V4 Signature canonical request. More...
 
QByteArray credentialScope (const QDate &date, const QString &region, const QString &service) const
 Create an AWS V4 Signature credential scope. More...
 
QByteArray signingKey (const AwsAbstractCredentials &credentials, const QDate &date, const QString &region, const QString &service) const
 Create an AWS V4 Signature signing key. More...
 
QByteArray stringToSign (const QByteArray &algorithmDesignation, const QDateTime &requestDate, const QByteArray &credentialScope, const QByteArray &canonicalRequest) const
 Create an AWS V4 Signature string to sign. More...
 

Protected Attributes

const QCryptographicHash::Algorithm hashAlgorithm
 Hash algorithm to use when signing.
 
- Protected Attributes inherited from AwsAbstractSignaturePrivate
AwsAbstractSignature *const q_ptr
 Internal q-pointer.
 

Static Protected Attributes

static const QLatin1String DateFormat
 Format V4 signatures use to represent dates in canonical form.
 
static const QLatin1String DateTimeFormat
 Format V4 signatures use to represent timestamps in canonical form.
 

Friends

class TestAwsSignatureV4
 

Detailed Description

Private implementation for AwsSignatureV4.

See also
http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html

Definition at line 36 of file awssignaturev4_p.h.

Constructor & Destructor Documentation

AwsSignatureV4Private::AwsSignatureV4Private ( const QCryptographicHash::Algorithm  hashAlgorithm,
AwsSignatureV4 *const  q 
)

Constructs a new AwsSignatureV4Private object.

Parameters
hashAlgorithmThe algorithm to use during various stages of signing.
qPointer to this object's public AwsSignatureV4 instance.

Definition at line 95 of file awssignaturev4.cpp.

98 {
99 
100 }
const QCryptographicHash::Algorithm hashAlgorithm
Hash algorithm to use when signing.
AwsAbstractSignaturePrivate(AwsAbstractSignature *const q)
Constructs a new AwsAbstractSignaturePrivate object.

Member Function Documentation

QByteArray AwsSignatureV4Private::algorithmDesignation ( const QCryptographicHash::Algorithm  algorithm) const
protected

Create an AWS V4 Signature algorithm designation.

This function returns an algorithm designation, as defined by Amazon, for use with V4 signatures.

For example, if the algorith is QCryptographicHash::Sha256, this function will return AWS4-HMAC-SHA256.

Parameters
algorithmThe hash algorithm to get the canonical designation for.
Returns
An AWS V4 Signature algorithm designation.
See also
http://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html

Definition at line 117 of file awssignaturev4.cpp.

Referenced by authorizationHeaderValue().

118 {
119  switch (algorithm) {
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";
127  default:
128  Q_ASSERT_X(false, Q_FUNC_INFO, "invalid algorithm");
129  return "invalid-algorithm";
130  }
131 }
QByteArray AwsSignatureV4Private::authorizationHeaderValue ( const AwsAbstractCredentials credentials,
const QNetworkAccessManager::Operation  operation,
QNetworkRequest &  request,
const QByteArray &  payload,
const QDateTime &  timestamp 
) const
protected

Create an AWS V4 Signature authorization header value.

This function builds an V4 signature, and returns it to the caller. The returned header value is then suitable for adding as a Authorization header in the HTTP request, to be accepted by Amazon.

Parameters
credentialsThe AWS credentials to use to sign the request.
operationThe HTTP method being used for the request.
requestThe network request to generate a signature for.
payloadOptional data being submitted in the request (eg for PUT and POST operations).
timestampThe timestamp to use when signing the request.
Returns
An AWS V4 Signature authorization header value.
See also
http://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
setAuthorizationHeader

Definition at line 151 of file awssignaturev4.cpp.

References AwsAbstractCredentials::accessKeyId(), algorithmDesignation(), canonicalRequest(), credentialScope(), hashAlgorithm, signingKey(), and stringToSign().

Referenced by setAuthorizationHeader().

155 {
156  const QByteArray algorithmDesignation = this->algorithmDesignation(hashAlgorithm);
157  const AwsEndpoint endpoint(request.url().host());
158 
159  const QByteArray credentialScope = this->credentialScope(timestamp.date(), endpoint.regionName(), endpoint.serviceName());
160  QByteArray signedHeaders;
161  const QByteArray canonicalRequest = this->canonicalRequest(operation, request, payload, &signedHeaders);
162 
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);
166 
167  return algorithmDesignation + " Credential=" + credentials.accessKeyId().toUtf8() + '/' + credentialScope +
168  ", SignedHeaders=" + signedHeaders + ", Signature=" + signature.toHex();
169 }
const QCryptographicHash::Algorithm hashAlgorithm
Hash algorithm to use when signing.
QByteArray algorithmDesignation(const QCryptographicHash::Algorithm algorithm) const
Create an AWS V4 Signature algorithm designation.
Provides AWS endpoint information.
Definition: awsendpoint.h:33
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.
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 &region, const QString &service) const
Create an AWS V4 Signature credential scope.
QByteArray signingKey(const AwsAbstractCredentials &credentials, const QDate &date, const QString &region, const QString &service) const
Create an AWS V4 Signature signing key.
QByteArray AwsSignatureV4Private::canonicalHeader ( const QByteArray &  headerName,
const QByteArray &  headerValue 
) const
protected

Create an AWS V4 Signature canonical header string.

In canonical form, header name and value are combined with a single semi-colon separator, with all whitespace removed from both, except for whitespace within double-quotes.

Parameters
headerNameName of the HTTP header to convert to canonical form.
headerValueValue of the HTTP header to convert to canonical form.
Returns
An AWS V4 Signature canonical header string.
See also
http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
canonicalHeaders

Definition at line 186 of file awssignaturev4.cpp.

Referenced by canonicalHeaders().

187 {
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);
194  header += thisChar;
195  if (isInQuotes) {
196  if ((thisChar == '"') && (previousChar != '\\'))
197  isInQuotes = false;
198  } else {
199  if ((thisChar == '"') && (previousChar != '\\')) {
200  isInQuotes = true;
201  } else if (isspace(thisChar)) {
202  while ((index < trimmedHeaderValue.size()-1) &&
203  (isspace(trimmedHeaderValue.at(index+1))))
204  ++index;
205  }
206  }
207  previousChar = thisChar;
208  }
209  return header;
210 }
QByteArray AwsSignatureV4Private::canonicalHeaders ( const QNetworkRequest &  request,
QByteArray *const  signedHeaders 
) const
protected

Create an AWS V4 Signature canonical headers string.

This function constructs a canonical string containing all of the headers in the given request.

Note
request will typically not include a Host header at this stage, however Qt will add an appropriate Host header when the request is performed. So, if request does not include a Host header yet, this function will include a derived Host header in the canonical headers to allow for it.
Parameters
[in]requestThe network request to fetch the canonical headers from.
[out]signedHeadersA semi-colon separated list of the names of all headers included in the result.
Returns
An AWS V4 Signature canonical headers string.
See also
http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
canonicalHeader

Definition at line 233 of file awssignaturev4.cpp.

References canonicalHeader().

Referenced by canonicalRequest().

234 {
235  Q_CHECK_PTR(signedHeaders);
236  signedHeaders->clear();
237 
238  /* Note, Amazon says we should combine duplicate headers with comma separators...
239  * conveniently for us, QNetworkRequest requires that to have been done already.
240  * See note in QNetworkRequest::setRawHeader.
241  */
242 
243  // Convert the raw headers list to a map to sort on (lowercased) header names only.
244  QMap<QByteArray,QByteArray> headers;
245  foreach (const QByteArray &rawHeader, request.rawHeaderList()) {
246  headers.insert(rawHeader.toLower(), request.rawHeader(rawHeader));
247  }
248  // The "host" header is not included in QNetworkRequest::rawHeaderList, but will be sent by Qt.
249  headers.insert("host", request.url().host().toUtf8());
250 
251  // Convert the headers map to a canonical string, keeping track of which headers we've included too.
252  QByteArray canonicalHeaders;
253  for (QMap<QByteArray,QByteArray>::const_iterator iter = headers.constBegin(); iter != headers.constEnd(); ++iter) {
254  canonicalHeaders += canonicalHeader(iter.key(), iter.value()) + '\n';
255  if (!signedHeaders->isEmpty()) *signedHeaders += ';';
256  *signedHeaders += iter.key();
257  }
258  return canonicalHeaders;
259 }
QByteArray canonicalHeaders(const QNetworkRequest &request, QByteArray *const signedHeaders) const
Create an AWS V4 Signature canonical headers string.
QByteArray canonicalHeader(const QByteArray &headerName, const QByteArray &headerValue) const
Create an AWS V4 Signature canonical header string.
QByteArray AwsSignatureV4Private::canonicalRequest ( const QNetworkAccessManager::Operation  operation,
const QNetworkRequest &  request,
const QByteArray &  payload,
QByteArray *const  signedHeaders 
) const
protected

Create an AWS V4 Signature canonical request.

Parameters
[in]operationThe HTTP method being used for the request.
[in]requestThe network request to generate a canonical request for.
[in]payloadOptional data being submitted in the request (eg for PUT and POST operations).
[out]signedHeadersA semi-colon separated list of the names of all headers included in the result.
Returns
An AWS V4 Signature canonical request.
See also
http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html

Definition at line 274 of file awssignaturev4.cpp.

References canonicalHeaders(), AwsAbstractSignaturePrivate::canonicalPath(), AwsAbstractSignaturePrivate::canonicalQuery(), hashAlgorithm, and AwsAbstractSignaturePrivate::httpMethod().

Referenced by authorizationHeaderValue().

277 {
278  return httpMethod(operation).toUtf8() + '\n' +
279  canonicalPath(request.url()).toUtf8() + '\n' +
280  canonicalQuery(QUrlQuery(request.url())) + '\n' +
281  canonicalHeaders(request, signedHeaders) + '\n' +
282  *signedHeaders + '\n' +
283  QCryptographicHash::hash(payload, hashAlgorithm).toHex();
284 }
const QCryptographicHash::Algorithm hashAlgorithm
Hash algorithm to use when signing.
QByteArray canonicalQuery(const QUrlQuery &query) const
Create an AWS Signature canonical query.
QByteArray canonicalHeaders(const QNetworkRequest &request, QByteArray *const signedHeaders) const
Create an AWS V4 Signature canonical headers string.
QString httpMethod(const QNetworkAccessManager::Operation operation) const
Create an AWS Signature request method string.
QString canonicalPath(const QUrl &url) const
Create an AWS Signature canonical path.
QByteArray AwsSignatureV4Private::credentialScope ( const QDate &  date,
const QString &  region,
const QString &  service 
) const
protected

Create an AWS V4 Signature credential scope.

Parameters
dateDate to include in the credential scope.
regionRegion name to include in the credential scope.
serviceService name to include in the credential scope.
Returns
An AWS V4 Signature credential scope.
See also
http://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html

Definition at line 297 of file awssignaturev4.cpp.

References DateFormat.

Referenced by authorizationHeaderValue().

298 {
299  return date.toString(DateFormat).toUtf8() + '/' + region.toUtf8() + '/' + service.toUtf8() + "/aws4_request";
300 }
static const QLatin1String DateFormat
Format V4 signatures use to represent dates in canonical form.
void AwsSignatureV4Private::setAuthorizationHeader ( const AwsAbstractCredentials credentials,
const QNetworkAccessManager::Operation  operation,
QNetworkRequest &  request,
const QByteArray &  payload,
const QDateTime &  timestamp 
) const

Set authorization header on a network request.

This function will calculate the authorization header value and set it as the Authorization HTTP header on request.

Parameters
[in]credentialsThe AWS credentials to use to sign the request.
[in]operationThe HTTP method being used for the request.
[in,out]requestThe network request to add the authorization header to.
[in]payloadOptional data being submitted in the request (eg for PUT and POST operations).
[in]timestampThe timestamp to use when signing the request.
See also
http://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
authorizationHeaderValue

Definition at line 317 of file awssignaturev4.cpp.

References authorizationHeaderValue().

321 {
322  Q_ASSERT(!request.hasRawHeader("Authorization"));
323  request.setRawHeader("Authorization", authorizationHeaderValue(credentials, operation, request, payload, timestamp));
324 }
QByteArray authorizationHeaderValue(const AwsAbstractCredentials &credentials, const QNetworkAccessManager::Operation operation, QNetworkRequest &request, const QByteArray &payload, const QDateTime &timestamp) const
Create an AWS V4 Signature authorization header value.
QDateTime AwsSignatureV4Private::setDateHeader ( QNetworkRequest &  request,
const QDateTime &  dateTime = QDateTime::currentDateTimeUtc() 
) const

Set the AWS custom date header.

This function will set a custom x-amz-date header to the value of dateTime formatted to AwsSignatureV4Private::DateTimeFormat.

Note
Although Amazon labels this as a "date", it is in fact a full timestamp.
Parameters
requestThe network request to add the date header to.
dateTimeThe timestamp to set the date header's value to.
Returns
dateTime verbatim (just a convenience for some callers).

Definition at line 339 of file awssignaturev4.cpp.

References DateTimeFormat.

340 {
341  Q_ASSERT(!request.hasRawHeader("x-amz-date"));
342  request.setRawHeader("x-amz-date", dateTime.toString(DateTimeFormat).toUtf8());
343  return dateTime;
344 }
static const QLatin1String DateTimeFormat
Format V4 signatures use to represent timestamps in canonical form.
QByteArray AwsSignatureV4Private::signingKey ( const AwsAbstractCredentials credentials,
const QDate &  date,
const QString &  region,
const QString &  service 
) const
protected

Create an AWS V4 Signature signing key.

Parameters
credentialsAWS credentials to use when generating the signing key.
dateDate to include in the signing key.
regionRegion name to include in the signing key.
serviceService name to include in the signing key.
Returns
An AWS V4 Signature signing key.
See also
http://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html

Definition at line 358 of file awssignaturev4.cpp.

References DateFormat, hashAlgorithm, and AwsAbstractCredentials::secretKey().

Referenced by authorizationHeaderValue().

360 {
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(),
366 }
static const QLatin1String DateFormat
Format V4 signatures use to represent dates in canonical form.
const QCryptographicHash::Algorithm hashAlgorithm
Hash algorithm to use when signing.
virtual QString secretKey() const =0
AWS secret access key for this credentials object.
QByteArray AwsSignatureV4Private::stringToSign ( const QByteArray &  algorithmDesignation,
const QDateTime &  requestDate,
const QByteArray &  credentialScope,
const QByteArray &  canonicalRequest 
) const
protected

Create an AWS V4 Signature string to sign.

Parameters
algorithmDesignationAWS designation for the hash algorithm used to sign the request.
requestDateAWS request timestamp.
credentialScopeAws credential scope used to sign the request.
canonicalRequestAWS request in canonical form.
Returns
An AWS V4 Signature string to sign.
See also
http://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html
algorithmDesignation
canonicalRequest
credentialScope

Definition at line 383 of file awssignaturev4.cpp.

References DateTimeFormat, and hashAlgorithm.

Referenced by authorizationHeaderValue().

385 {
386  return algorithmDesignation + '\n' +
387  requestDate.toString(DateTimeFormat).toUtf8() + '\n' +
388  credentialScope + '\n' +
389  QCryptographicHash::hash(canonicalRequest, hashAlgorithm).toHex();
390 }
const QCryptographicHash::Algorithm hashAlgorithm
Hash algorithm to use when signing.
QByteArray algorithmDesignation(const QCryptographicHash::Algorithm algorithm) const
Create an AWS V4 Signature algorithm designation.
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 credentialScope(const QDate &date, const QString &region, const QString &service) const
Create an AWS V4 Signature credential scope.

The documentation for this class was generated from the following files: