Chromium Code Reviews
|
| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/http/http_mac_signature.h" | |
| 6 | |
| 7 #include "base/base64.h" | |
| 8 #include "base/rand_util.h" | |
| 9 #include "base/string_number_conversions.h" | |
| 10 #include "base/string_util.h" | |
| 11 #include "base/time.h" | |
| 12 #include "crypto/hmac.h" | |
| 13 | |
| 14 namespace net { | |
| 15 | |
| 16 namespace { | |
| 17 | |
| 18 const char kSHA1Name[] = "hmac-sha-1"; | |
| 19 const char kSHA256Name[] = "hmac-sha-256"; | |
| 20 const int kNonceLength = 256 / 8; | |
| 21 | |
| 22 size_t LengthForHMACAlgorithm(crypto::HMAC::HashAlgorithm algorithm) { | |
|
cbentzel
2011/04/29 14:44:49
I'm kind of surprised this isn't an HMAC method. S
abarth-chromium
2011/04/29 18:16:01
Yes. I'll add it.
| |
| 23 if (algorithm == crypto::HMAC::SHA1) | |
| 24 return 20; | |
| 25 if (algorithm == crypto::HMAC::SHA256) | |
| 26 return 32; | |
| 27 NOTREACHED(); | |
| 28 return 20; | |
| 29 } | |
| 30 | |
| 31 bool IsPlainStringCharacter(char character) { | |
| 32 return character == 0x20 || character == 0x21 || | |
| 33 (character >= 0x23 && character <= 0x5B) || | |
| 34 (character >= 0x5D && character <= 0x7E); | |
| 35 } | |
| 36 | |
| 37 bool IsPlainString(const std::string& string) { | |
| 38 for (size_t i = 0; i < string.size(); ++i) { | |
| 39 if (!IsPlainStringCharacter(string[i])) | |
| 40 return false; | |
| 41 } | |
| 42 return true; | |
| 43 } | |
| 44 | |
| 45 std::string GenerateNonce() { | |
| 46 std::string nonce; | |
| 47 bool result = base::Base64Encode(base::RandString(kNonceLength), &nonce); | |
| 48 DCHECK(result); | |
| 49 return nonce; | |
| 50 } | |
| 51 | |
| 52 } | |
| 53 | |
| 54 HttpMacSignature::HttpMacSignature() | |
| 55 : mac_algorithm_(crypto::HMAC::SHA1) | |
| 56 { | |
|
cbentzel
2011/04/29 14:44:49
Nit: { typically on same line as the last initiali
abarth-chromium
2011/04/29 18:16:01
Fixed. (WebKit style leaking in.)
| |
| 57 } | |
| 58 | |
| 59 HttpMacSignature::~HttpMacSignature() { | |
| 60 } | |
| 61 | |
| 62 bool HttpMacSignature::AddStateInfo(const std::string& id, | |
|
cbentzel
2011/04/29 14:44:49
Should this be callable multiple times?
abarth-chromium
2011/04/29 18:16:01
Not if it returns true. DCHECK added.
| |
| 63 const std::string& mac_key, | |
| 64 const std::string& mac_algorithm, | |
| 65 const std::string& issuer) { | |
| 66 if (!IsPlainString(id) || id.empty() | |
| 67 || !IsPlainString(mac_key) || mac_key.empty() | |
| 68 || !IsPlainString(issuer) || issuer.empty()) | |
| 69 return false; | |
| 70 | |
| 71 if (mac_algorithm == kSHA1Name) | |
|
cbentzel
2011/04/29 14:44:49
Very tiny issue: maybe do input validity checking
abarth-chromium
2011/04/29 18:16:01
Do you mean checking for IsPlainString ? The mac_
cbentzel
2011/04/29 18:37:56
Sorry, I just meant moving this into
if (!IsPlain
| |
| 72 mac_algorithm_ = crypto::HMAC::SHA1; | |
| 73 else if (mac_algorithm == kSHA256Name) | |
| 74 mac_algorithm_ = crypto::HMAC::SHA256; | |
| 75 else | |
| 76 return false; | |
| 77 | |
| 78 id_ = id; | |
| 79 mac_key_ = mac_key; | |
| 80 issuer_ = issuer; | |
| 81 return true; | |
| 82 } | |
| 83 | |
| 84 bool HttpMacSignature::AddHttpInfo(const std::string& method, | |
| 85 const std::string& request_uri, | |
| 86 const std::string& host, | |
| 87 int port) { | |
| 88 if (!IsPlainString(method) || method.empty() | |
| 89 || !IsPlainString(request_uri) || request_uri.empty() | |
| 90 || !IsPlainString(host) || host.empty() | |
| 91 || port <= 0) | |
|
cbentzel
2011/04/29 14:44:49
Add a port > 65535 check as well.
abarth-chromium
2011/04/29 18:16:01
Done.
| |
| 92 return false; | |
| 93 | |
| 94 method_ = StringToUpperASCII(method); | |
| 95 request_uri_ = request_uri; | |
| 96 host_ = StringToLowerASCII(host); | |
| 97 port_ = base::IntToString(port); | |
| 98 return true; | |
| 99 } | |
| 100 | |
| 101 std::string HttpMacSignature::GenerateAuthorizationHeader() { | |
| 102 DCHECK(!id_.empty()) << "Call AddStateInfo first."; | |
| 103 DCHECK(port_.empty()) << "Call AddHttpInfo first."; | |
|
cbentzel
2011/04/29 14:44:49
!port_.empty()
abarth-chromium
2011/04/29 18:16:01
I've changed this to used method_, actually, which
| |
| 104 | |
| 105 std::string timestamp = base::IntToString((base::Time::Now() - | |
| 106 base::Time::UnixEpoch()).InSeconds()); | |
| 107 std::string nonce = GenerateNonce(); | |
| 108 std::string mac = GenerateMAC(timestamp, nonce); | |
| 109 | |
| 110 DCHECK(IsPlainString(timestamp)); | |
| 111 DCHECK(IsPlainString(nonce)); | |
| 112 DCHECK(IsPlainString(mac)); | |
| 113 | |
| 114 std::string header = "MAC id=\"" + id_ + | |
| 115 "\", issuer=\"" + issuer_ + | |
| 116 "\", timestamp=\"" + timestamp + | |
| 117 "\", nonce=\"" + nonce + | |
| 118 "\", mac=\"" + mac + "\""; | |
| 119 | |
| 120 return header; | |
| 121 } | |
| 122 | |
| 123 std::string HttpMacSignature::GenerateNormalizedRequest( | |
| 124 const std::string& timestamp, | |
| 125 const std::string& nonce) { | |
| 126 static const std::string kNewLine = "\n"; | |
| 127 | |
| 128 std::string normalized_request = id_ + kNewLine; | |
| 129 normalized_request += issuer_ + kNewLine; | |
| 130 normalized_request += timestamp + kNewLine; | |
| 131 normalized_request += nonce + kNewLine; | |
| 132 normalized_request += method_ + kNewLine; | |
| 133 normalized_request += request_uri_ + kNewLine; | |
| 134 normalized_request += host_ + kNewLine; | |
| 135 normalized_request += port_ + kNewLine; | |
| 136 | |
| 137 return normalized_request; | |
| 138 } | |
| 139 | |
| 140 std::string HttpMacSignature::GenerateMAC(const std::string& timestamp, | |
|
cbentzel
2011/04/29 14:44:49
Should these be returning a bool in case hmac.Sign
abarth-chromium
2011/04/29 18:16:01
Base64Encode can't fail in these cases because the
cbentzel
2011/04/29 18:37:56
DCHECK seems fine, although I have not looked at w
| |
| 141 const std::string& nonce) { | |
| 142 std::string request = GenerateNormalizedRequest(timestamp, nonce); | |
| 143 | |
| 144 crypto::HMAC hmac(mac_algorithm_); | |
| 145 hmac.Init(mac_key_); | |
| 146 | |
| 147 std::string signature; | |
| 148 size_t length = LengthForHMACAlgorithm(mac_algorithm_); | |
| 149 char* buffer = WriteInto(&signature, length); | |
| 150 hmac.Sign(request, reinterpret_cast<unsigned char*>(buffer), length); | |
|
cbentzel
2011/04/29 14:44:49
You should check the result of hmac.Sign
abarth-chromium
2011/04/29 18:16:01
I've added a DCHECK.
| |
| 151 | |
| 152 std::string encoded_signature; | |
| 153 bool result = base::Base64Encode(signature, &encoded_signature); | |
| 154 DCHECK(result); | |
| 155 return encoded_signature; | |
| 156 } | |
| 157 | |
| 158 } // namespace net | |
| OLD | NEW |