rc4_decryptor.h revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
1// Copyright 2013 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#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_CRYPTO_RC4_DECRYPTOR_H_ 6#define COMPONENTS_AUTOFILL_CORE_BROWSER_CRYPTO_RC4_DECRYPTOR_H_ 7 8#include <string> 9#include "base/basictypes.h" 10#include "base/memory/scoped_ptr.h" 11 12namespace autofill { 13 14// This is modified RC4 decryption used for import of Toolbar autofill data 15// only. The difference from the Crypto Api implementation is twofold: 16// First, it uses a non-standard key size (160 bit), not supported by Microsoft 17// (it supports only 40 and 128 bit for RC4). Second, it codes 128 words with 18// value 0x0020 at the beginning of the code to enhance security. 19// 20// This class used in 21// components/autofill/core/browser/autofill_ie_toolbar_import_win.cc. 22// 23// This class should not be used anywhere else!!! 24class RC4Decryptor { 25 public: 26 explicit RC4Decryptor(wchar_t const* password) { 27 PrepareKey(reinterpret_cast<const uint8 *>(password), 28 wcslen(password) * sizeof(wchar_t)); 29 std::wstring data; 30 // First 128 bytes should be spaces. 31 data.resize(128, L' '); 32 Run(data.c_str()); 33 } 34 35 // Run the algorithm 36 std::wstring Run(const std::wstring& data) { 37 int data_size = data.length() * sizeof(wchar_t); 38 39 scoped_ptr<wchar_t[]> buffer(new wchar_t[data.length() + 1]); 40 memset(buffer.get(), 0, (data.length() + 1) * sizeof(wchar_t)); 41 memcpy(buffer.get(), data.c_str(), data_size); 42 43 RunInternal(reinterpret_cast<uint8 *>(buffer.get()), data_size); 44 45 std::wstring result(buffer.get()); 46 47 // Clear the memory 48 memset(buffer.get(), 0, data_size); 49 return result; 50 } 51 52 private: 53 static const int kKeyDataSize = 256; 54 struct Rc4Key { 55 uint8 state[kKeyDataSize]; 56 uint8 x; 57 uint8 y; 58 }; 59 60 void SwapByte(uint8* byte1, uint8* byte2) { 61 uint8 temp = *byte1; 62 *byte1 = *byte2; 63 *byte2 = temp; 64 } 65 66 void PrepareKey(const uint8 *key_data, int key_data_len) { 67 uint8 index1 = 0; 68 uint8 index2 = 0; 69 uint8* state; 70 short counter; 71 72 state = &key_.state[0]; 73 for (counter = 0; counter < kKeyDataSize; ++counter) 74 state[counter] = static_cast<uint8>(counter); 75 76 key_.x = key_.y = 0; 77 78 for (counter = 0; counter < kKeyDataSize; counter++) { 79 index2 = (key_data[index1] + state[counter] + index2) % kKeyDataSize; 80 SwapByte(&state[counter], &state[index2]); 81 index1 = (index1 + 1) % key_data_len; 82 } 83 } 84 85 void RunInternal(uint8 *buffer, int buffer_len) { 86 uint8 x, y; 87 uint8 xor_index = 0; 88 uint8* state; 89 int counter; 90 91 x = key_.x; 92 y = key_.y; 93 state = &key_.state[0]; 94 for (counter = 0; counter < buffer_len; ++counter) { 95 x = (x + 1) % kKeyDataSize; 96 y = (state[x] + y) % kKeyDataSize; 97 SwapByte(&state[x], &state[y]); 98 xor_index = (state[x] + state[y]) % kKeyDataSize; 99 buffer[counter] ^= state[xor_index]; 100 } 101 key_.x = x; 102 key_.y = y; 103 } 104 105 Rc4Key key_; 106}; 107 108} // namespace autofill 109 110#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_CRYPTO_RC4_DECRYPTOR_H_ 111