blob: b79ac38bf4a8f1490a9919f89e07d57bbeac1d8d [file] [log] [blame]
[email protected]94d557e2010-06-23 21:41:401// Copyright (c) 2010 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 "base/sha1.h"
6
7#include <windows.h>
8#include <wincrypt.h>
9
10#include "base/logging.h"
11#include "base/string_util.h"
12
13namespace base {
14
15// Implementation of SHA-1 using Windows CryptoAPI.
16
17// Usage example:
18//
19// SecureHashAlgorithm sha;
20// while(there is data to hash)
21// sha.Update(moredata, size of data);
22// sha.Final();
23// memcpy(somewhere, sha.Digest(), 20);
24//
25// to reuse the instance of sha, call sha.Init();
26
27class SecureHashAlgorithm {
28 public:
29 SecureHashAlgorithm() : prov_(NULL), hash_(NULL) { Init(); }
30
31 void Init();
32 void Update(const void* data, size_t nbytes);
33 void Final();
34
35 // 20 bytes of message digest.
36 const unsigned char* Digest() const {
37 return reinterpret_cast<const unsigned char*>(result_.data());
38 }
39
40 private:
41 // Cleans up prov_, hash_, and result_.
42 void Cleanup();
43
44 HCRYPTPROV prov_;
45 HCRYPTHASH hash_;
46 std::string result_;
47};
48
49void SecureHashAlgorithm::Init() {
50 Cleanup();
51
52 if (!CryptAcquireContext(&prov_, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
53 LOG(ERROR) << "CryptAcquireContext failed: " << GetLastError();
54 return;
55 }
56
57 // Initialize the hash.
58 if (!CryptCreateHash(prov_, CALG_SHA1, 0, 0, &hash_)) {
59 LOG(ERROR) << "CryptCreateHash failed: " << GetLastError();
60 return;
61 }
62}
63
64void SecureHashAlgorithm::Update(const void* data, size_t nbytes) {
65 BOOL ok = CryptHashData(hash_, reinterpret_cast<CONST BYTE*>(data),
66 static_cast<DWORD>(nbytes), 0);
67 CHECK(ok) << "CryptHashData failed: " << GetLastError();
68}
69
70void SecureHashAlgorithm::Final() {
71 DWORD hash_len = 0;
72 DWORD buffer_size = sizeof(hash_len);
73 if (!CryptGetHashParam(hash_, HP_HASHSIZE,
74 reinterpret_cast<unsigned char*>(&hash_len),
75 &buffer_size, 0)) {
76 LOG(ERROR) << "CryptGetHashParam(HP_HASHSIZE) failed: " << GetLastError();
77 result_.assign(SHA1_LENGTH, '\0');
78 return;
79 }
80
81 // Get the hash data.
82 if (!CryptGetHashParam(hash_, HP_HASHVAL,
83 reinterpret_cast<BYTE*>(WriteInto(&result_,
84 hash_len + 1)),
85 &hash_len, 0)) {
86 LOG(ERROR) << "CryptGetHashParam(HP_HASHVAL) failed: " << GetLastError();
87 result_.assign(SHA1_LENGTH, '\0');
88 return;
89 }
90}
91
92void SecureHashAlgorithm::Cleanup() {
93 BOOL ok;
94 if (hash_) {
95 ok = CryptDestroyHash(hash_);
96 DCHECK(ok);
97 hash_ = NULL;
98 }
99 if (prov_) {
100 ok = CryptReleaseContext(prov_, 0);
101 DCHECK(ok);
102 prov_ = NULL;
103 }
104 result_.clear();
105}
106
107std::string SHA1HashString(const std::string& str) {
108 SecureHashAlgorithm sha;
109 sha.Update(str.c_str(), str.length());
110 sha.Final();
111 std::string out(reinterpret_cast<const char*>(sha.Digest()), SHA1_LENGTH);
112 return out;
113}
114
115} // namespace base