summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-04 19:29:58 +0000
committerjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-04 19:29:58 +0000
commitc2ad1e38df308c29d87f949fd9117341bbd6a96f (patch)
tree406cd61303883e99f63ec44b8cf4435e37b3e353 /base
parent667d357e93f2dcc8afbbac71051dfedcc91daba3 (diff)
downloadchromium_src-c2ad1e38df308c29d87f949fd9117341bbd6a96f.zip
chromium_src-c2ad1e38df308c29d87f949fd9117341bbd6a96f.tar.gz
chromium_src-c2ad1e38df308c29d87f949fd9117341bbd6a96f.tar.bz2
Implement FormStructure and an initial method, EncodeUploadRequest. This also adds SHA1HashString, a utility method to get the SHA-1 hash of an input string, with appropriate unit tests.
BUG=18201 TEST=none Review URL: http://codereview.chromium.org/355003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@30980 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r--base/base.gyp3
-rw-r--r--base/sha1.cc202
-rw-r--r--base/sha1.h24
-rw-r--r--base/sha1_unittest.cc56
4 files changed, 285 insertions, 0 deletions
diff --git a/base/base.gyp b/base/base.gyp
index b79568d..47d2438 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -267,6 +267,8 @@
'scoped_vector.h',
'setproctitle_linux.c',
'setproctitle_linux.h',
+ 'sha1.cc',
+ 'sha1.h',
'sha2.cc',
'sha2.h',
'shared_memory.h',
@@ -606,6 +608,7 @@
'scoped_ptr_unittest.cc',
'scoped_temp_dir_unittest.cc',
'scoped_variant_win_unittest.cc',
+ 'sha1_unittest.cc',
'sha2_unittest.cc',
'shared_memory_unittest.cc',
'simple_thread_unittest.cc',
diff --git a/base/sha1.cc b/base/sha1.cc
new file mode 100644
index 0000000..620dd56
--- /dev/null
+++ b/base/sha1.cc
@@ -0,0 +1,202 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/sha1.h"
+
+#include "base/basictypes.h"
+
+namespace base {
+
+// Implementation of SHA-1. Only handles data in byte-sized blocks,
+// which simplifies the code a fair bit.
+
+// This file also contains an HMAC implementation using SHA-1
+
+// Identifier names follow notation in FIPS PUB 180-3, where you'll
+// also find a description of the algorithm:
+// http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf
+
+// Usage example:
+//
+// SecureHashAlgorithm sha;
+// while(there is data to hash)
+// sha.Update(moredata, size of data);
+// sha.Final();
+// memcpy(somewhere, sha.Digest(), 20);
+//
+// to reuse the instance of sha, call sha.Init();
+
+// TODO(jhawkins): Replace this implementation with a per-platform
+// implementation using each platform's crypto library.
+
+class SecureHashAlgorithm {
+ public:
+ SecureHashAlgorithm() { Init(); }
+
+ static const int kDigestSizeBytes;
+
+ void Init();
+ void Update(const void* data, size_t nbytes);
+ void Final();
+
+ // 20 bytes of message digest.
+ const unsigned char* Digest() const {
+ return reinterpret_cast<const unsigned char*>(H);
+ }
+
+ private:
+ void Pad();
+ void Process();
+
+ uint32 A, B, C, D, E;
+
+ uint32 H[5];
+
+ union {
+ uint32 W[80];
+ uint8 M[64];
+ };
+
+ uint32 cursor;
+ uint32 l;
+};
+
+static inline uint32 f(uint32 t, uint32 B, uint32 C, uint32 D) {
+ if (t < 20) {
+ return (B & C) | ((~B) & D);
+ } else if (t < 40) {
+ return B ^ C ^ D;
+ } else if (t < 60) {
+ return (B & C) | (B & D) | (C & D);
+ } else {
+ return B ^ C ^ D;
+ }
+}
+
+static inline uint32 S(uint32 n, uint32 X) {
+ return (X << n) | (X >> (32-n));
+}
+
+static inline uint32 K(uint32 t) {
+ if (t < 20) {
+ return 0x5a827999;
+ } else if (t < 40) {
+ return 0x6ed9eba1;
+ } else if (t < 60) {
+ return 0x8f1bbcdc;
+ } else {
+ return 0xca62c1d6;
+ }
+}
+
+static inline void swapends(uint32& t) {
+ t = ((t & 0xff000000) >> 24) |
+ ((t & 0xff0000) >> 8) |
+ ((t & 0xff00) << 8) |
+ ((t & 0xff) << 24);
+}
+
+const int SecureHashAlgorithm::kDigestSizeBytes = 20;
+
+void SecureHashAlgorithm::Init() {
+ cursor = 0;
+ l = 0;
+ H[0] = 0x67452301;
+ H[1] = 0xefcdab89;
+ H[2] = 0x98badcfe;
+ H[3] = 0x10325476;
+ H[4] = 0xc3d2e1f0;
+}
+
+void SecureHashAlgorithm::Final() {
+ Pad();
+ Process();
+
+ for (int t = 0; t < 5; ++t)
+ swapends(H[t]);
+}
+
+void SecureHashAlgorithm::Update(const void* data, size_t nbytes) {
+ const uint8* d = reinterpret_cast<const uint8*>(data);
+ while (nbytes--) {
+ M[cursor++] = *d++;
+ if (cursor >= 64)
+ Process();
+ l += 8;
+ }
+}
+
+void SecureHashAlgorithm::Pad() {
+ M[cursor++] = 0x80;
+
+ if (cursor > 64-8) {
+ // pad out to next block
+ while (cursor < 64)
+ M[cursor++] = 0;
+
+ Process();
+ }
+
+ while (cursor < 64-4)
+ M[cursor++] = 0;
+
+ M[64-4] = (l & 0xff000000) >> 24;
+ M[64-3] = (l & 0xff0000) >> 16;
+ M[64-2] = (l & 0xff00) >> 8;
+ M[64-1] = (l & 0xff);
+}
+
+void SecureHashAlgorithm::Process() {
+ uint32 t;
+
+ // Each a...e corresponds to a section in the FIPS 180-3 algorithm.
+
+ // a.
+ //
+ // W and M are in a union, so no need to memcpy.
+ // memcpy(W, M, sizeof(M));
+ for (t = 0; t < 16; ++t)
+ swapends(W[t]);
+
+ // b.
+ for (t = 16; t < 80; ++t)
+ W[t] = S(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]);
+
+ // c.
+ A = H[0];
+ B = H[1];
+ C = H[2];
+ D = H[3];
+ E = H[4];
+
+ // d.
+ for (t = 0; t < 80; ++t) {
+ uint32 TEMP = S(5, A) + f(t, B, C, D) + E + W[t] + K(t);
+ E = D;
+ D = C;
+ C = S(30, B);
+ B = A;
+ A = TEMP;
+ }
+
+ // e.
+ H[0] += A;
+ H[1] += B;
+ H[2] += C;
+ H[3] += D;
+ H[4] += E;
+
+ cursor = 0;
+}
+
+std::string SHA1HashString(const std::string& str) {
+ SecureHashAlgorithm sha;
+ sha.Update(str.c_str(), str.length());
+ sha.Final();
+ std::string out(reinterpret_cast<const char*>(sha.Digest()),
+ SecureHashAlgorithm::kDigestSizeBytes);
+ return out;
+}
+
+} // namespace base
diff --git a/base/sha1.h b/base/sha1.h
new file mode 100644
index 0000000..bcc1ced
--- /dev/null
+++ b/base/sha1.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_SHA1_H_
+#define BASE_SHA1_H_
+
+#include <string>
+
+namespace base {
+
+// This function performs SHA-1 operations.
+
+enum {
+ SHA1_LENGTH = 20 // Length in bytes of a SHA-1 hash.
+};
+
+// Computes the SHA-1 hash of the input string |str| and returns the full
+// hash.
+std::string SHA1HashString(const std::string& str);
+
+} // namespace base
+
+#endif // BASE_SHA1_H_
diff --git a/base/sha1_unittest.cc b/base/sha1_unittest.cc
new file mode 100644
index 0000000..e445e8f
--- /dev/null
+++ b/base/sha1_unittest.cc
@@ -0,0 +1,56 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/sha1.h"
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(SHA1Test, Test1) {
+ // Example A.1 from FIPS 180-2: one-block message.
+ std::string input = "abc";
+
+ int expected[] = { 0xa9, 0x99, 0x3e, 0x36,
+ 0x47, 0x06, 0x81, 0x6a,
+ 0xba, 0x3e, 0x25, 0x71,
+ 0x78, 0x50, 0xc2, 0x6c,
+ 0x9c, 0xd0, 0xd8, 0x9d };
+
+ std::string output = base::SHA1HashString(input);
+ for (size_t i = 0; i < base::SHA1_LENGTH; i++)
+ EXPECT_EQ(expected[i], output[i] & 0xFF);
+}
+
+TEST(SHA1Test, Test2) {
+ // Example A.2 from FIPS 180-2: multi-block message.
+ std::string input =
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
+
+ int expected[] = { 0x84, 0x98, 0x3e, 0x44,
+ 0x1c, 0x3b, 0xd2, 0x6e,
+ 0xba, 0xae, 0x4a, 0xa1,
+ 0xf9, 0x51, 0x29, 0xe5,
+ 0xe5, 0x46, 0x70, 0xf1 };
+
+ std::string output = base::SHA1HashString(input);
+ for (size_t i = 0; i < base::SHA1_LENGTH; i++)
+ EXPECT_EQ(expected[i], output[i] & 0xFF);
+}
+
+TEST(SHA1Test, Test3) {
+ // Example A.3 from FIPS 180-2: long message.
+ std::string input(1000000, 'a');
+
+ int expected[] = { 0x34, 0xaa, 0x97, 0x3c,
+ 0xd4, 0xc4, 0xda, 0xa4,
+ 0xf6, 0x1e, 0xeb, 0x2b,
+ 0xdb, 0xad, 0x27, 0x31,
+ 0x65, 0x34, 0x01, 0x6f };
+
+ std::string output = base::SHA1HashString(input);
+ for (size_t i = 0; i < base::SHA1_LENGTH; i++)
+ EXPECT_EQ(expected[i], output[i] & 0xFF);
+}