libqtaws  0.1.0
UnofficialAWSlibraryforQt-InternalDocumentation
awssignaturev1.cpp
1 /*
2  Copyright 2013-2015 Paul Colby
3 
4  This file is part of libqtaws.
5 
6  Libqtaws is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Lesser General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  Libqtaws is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public License
17  along with libqtaws. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "awssignaturev1.h"
21 #include "awssignaturev1_p.h"
22 
23 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) && QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
24 #include "qmessageauthenticationcode.h"
25 #else
26 #include <QMessageAuthenticationCode>
27 #endif
28 
29 #include <QCryptographicHash>
30 #include <QDebug>
31 #include <QNetworkRequest>
32 #include <QUrl>
33 
34 QTAWS_BEGIN_NAMESPACE
35 
36 /**
37  * @class AwsSignatureV1
38  *
39  * @brief Implements AWS Signature Version 1 \ref deprecated "(deprecated by Amazon)"
40  *
41  * @deprecated Amazon has officially deprecated signature Version 1 in favor of later,
42  * more secure signatures, such as AwsSignatureV2 and AwsSignatureV4.
43  *
44  * As version 1 signatures are rightly regarded as *insecure*, this class will refuse to sign
45  * requests that use insecure transports such as HTTP instead of HTTPS. However, insecure
46  * signatures can be enabled (why would you want to?) by defining `QTAWS_ALLOW_INSECURE_SIGNATURES`
47  * when compiling this library.
48  *
49  * @see http://s3.amazonaws.com/awsdocs/SQS/20070501/sqs-dg-20070501.pdf
50  * @see http://lmgtfy.com/?q=aws+signature+version+1+is+insecure
51  */
52 
53 /**
54  * @brief Constructs a new AwsSignatureV1 object.
55  *
56  * Use instances of this object to provide Version 1 signatures for AWS services.
57  */
59 {
60 
61 }
62 
64 {
65  return 1;
66 }
67 
68 /**
69  * @internal
70  *
71  * @class AwsSignatureV1Private
72  *
73  * @brief Private implementation for AwsSignatureV1.
74  *
75  * @warning This is an internal private implementation class, and as such external should
76  * code should **not** depend directly on anything contained within this class.
77  *
78  * @see http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html
79  */
80 
81 /**
82  * @internal
83  *
84  * @brief Constructs a new AwsSignatureV1Private object.
85  *
86  * @param q Pointer to this object's public AwsSignatureV1 instance.
87  */
89 {
90 
91 }
92 
93 /**
94  * @internal
95  *
96  * @brief Create an AWS Signature version 1 canonical query.
97  *
98  * This function returns a string containing all non-empty query parameters in
99  * sorted order (case-insensitive), with no separators at all.
100  *
101  * For example, for the following SQS query string:
102  *
103  * ?Action=CreateQueue&QueueName=queue2&AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&SignatureVersion=1&Expires=2007-01-12T12:00:00Z&Version=2006-04-01
104  *
105  * this function will return the following canonical form:
106  *
107  * ActionCreateQueueAWSAccessKeyIdAKIAIOSFODNN7EXAMPLEExpires2007-01-12T12:00:00ZQueueNamequeue2SignatureVersion1Version2006-04-01
108  *
109  * This function is very similar to AwsAbstractSignature::canonicalQuery(), except
110  * that:
111  * 1. this function sorts case-insensitively, whereas AwsAbstractSignature::canonicalQuery()
112  * use a byte sort (ie is case sensitive); and
113  * 2. this function excludes parameters with empty values, where
114  * AwsAbstractSignature::canonicalQuery() includes all query parameters, regardless
115  * of content; and
116  * 3. this function does not use any separators in the generated string, whereas
117  * AwsAbstractSignature::canonicalQuery() uses `&` and `=` separators just as
118  * you would expect to see them in a typical query string; and
119  * 4. this function does not perform any URL encoding of the query parameters,
120  * whereas AwsAbstractSignature::canonicalQuery() URL encodes both parameter
121  * keys and values.
122  *
123  * The AwsAbstractSignature::canonicalQuery() function is used by the later signature
124  * algorithms, such as AwsSignatureV2 and AwsSignatureV4, as required by Amazon. Instead
125  * this function is specific to version 1 signatures.
126  *
127  * @param query Query to encode the HTTP query string from.
128  *
129  * @return An AWS Signature canonical query string.
130  *
131  * @see http://docs.aws.amazon.com/AmazonDevPay/latest/DevPayDeveloperGuide/LSAPI_Auth_REST.html#CalculatingHMACSignature
132  */
133 QByteArray AwsSignatureV1Private::canonicalQuery(const QUrlQuery &query) const
134 {
135  QList<QStringPair> list = query.queryItems(QUrl::FullyDecoded);
136  qSort(list.begin(), list.end(), AwsSignatureV1Private::caseInsensitiveLessThan);
137  QString result;
138  foreach (const QStringPair &pair, list) {
139  if (!pair.second.isEmpty()) {
140  result += pair.first + pair.second;
141  }
142  }
143  return result.toUtf8();
144 }
145 
146 /**
147  * @internal
148  *
149  * @brief Is a key-value pair less than another key-value pair?
150  *
151  * This static function is used by the canonicalQuery function to sort query string
152  * parameters in case-insensitive order, via Qt's qSort function.
153  *
154  * @param pair1 The first key-value (query string parameter) pair.
155  * @param pair2 The second key-value (query string parameter) pair.
156  *
157  * @returns `true` if \a pair1 is less than \a pair2.
158  */
160 {
161  if (pair1.first.toLower() < pair2.first.toLower())
162  return true;
163  if (pair1.first.toLower() > pair2.first.toLower())
164  return false;
165  return (pair1.second.toLower() < pair2.second.toLower());
166 }
167 
168 QTAWS_END_NAMESPACE
virtual int version() const
AWS Signature version implemented by this class.
static bool caseInsensitiveLessThan(const QStringPair &pair1, const QStringPair &pair2)
Is a key-value pair less than another key-value pair?
QPair< QString, QString > QStringPair
A key-value pair of strings for working with QUrlQuery::queryItems() results.
Implements AWS Signature Version 1 (deprecated by Amazon).
Private implementation for AwsSignatureV0.
QByteArray canonicalQuery(const QUrlQuery &query) const
Create an AWS Signature version 1 canonical query.
Implements AWS Signature Version 0 (deprecated by Amazon).
AwsSignatureV1()
Constructs a new AwsSignatureV1 object.
AwsSignatureV1Private(AwsSignatureV1 *const q)
Constructs a new AwsSignatureV1Private object.
Private implementation for AwsSignatureV1.