1 // Copyright (c) 2012 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 "components/webdata/encryptor/encryptor.h" 6 7 #include "base/logging.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/strings/utf_string_conversions.h" 10 #include "crypto/encryptor.h" 11 #include "crypto/symmetric_key.h" 12 13 namespace { 14 15 // Salt for Symmetric key derivation. 16 const char kSalt[] = "saltysalt"; 17 18 // Key size required for 128 bit AES. 19 const size_t kDerivedKeySizeInBits = 128; 20 21 // Constant for Symmetic key derivation. 22 const size_t kEncryptionIterations = 1; 23 24 // Size of initialization vector for AES 128-bit. 25 const size_t kIVBlockSizeAES128 = 16; 26 27 // Prefix for cypher text returned by obfuscation version. We prefix the 28 // cyphertext with this string so that future data migration can detect 29 // this and migrate to full encryption without data loss. 30 const char kObfuscationPrefix[] = "v10"; 31 32 // Generates a newly allocated SymmetricKey object based a hard-coded password. 33 // Ownership of the key is passed to the caller. Returns NULL key if a key 34 // generation error occurs. 35 crypto::SymmetricKey* GetEncryptionKey() { 36 // We currently "obfuscate" by encrypting and decrypting with hard-coded 37 // password. We need to improve this password situation by moving a secure 38 // password into a system-level key store. 39 // http://crbug.com/25404 and http://crbug.com/49115 40 std::string password = "peanuts"; 41 std::string salt(kSalt); 42 43 // Create an encryption key from our password and salt. 44 scoped_ptr<crypto::SymmetricKey> encryption_key( 45 crypto::SymmetricKey::DeriveKeyFromPassword(crypto::SymmetricKey::AES, 46 password, 47 salt, 48 kEncryptionIterations, 49 kDerivedKeySizeInBits)); 50 DCHECK(encryption_key.get()); 51 52 return encryption_key.release(); 53 } 54 55 } // namespace 56 57 bool Encryptor::EncryptString16(const base::string16& plaintext, 58 std::string* ciphertext) { 59 return EncryptString(UTF16ToUTF8(plaintext), ciphertext); 60 } 61 62 bool Encryptor::DecryptString16(const std::string& ciphertext, 63 base::string16* plaintext) { 64 std::string utf8; 65 if (!DecryptString(ciphertext, &utf8)) 66 return false; 67 68 *plaintext = UTF8ToUTF16(utf8); 69 return true; 70 } 71 72 bool Encryptor::EncryptString(const std::string& plaintext, 73 std::string* ciphertext) { 74 // This currently "obfuscates" by encrypting with hard-coded password. 75 // We need to improve this password situation by moving a secure password 76 // into a system-level key store. 77 // http://crbug.com/25404 and http://crbug.com/49115 78 79 if (plaintext.empty()) { 80 *ciphertext = std::string(); 81 return true; 82 } 83 84 scoped_ptr<crypto::SymmetricKey> encryption_key(GetEncryptionKey()); 85 if (!encryption_key.get()) 86 return false; 87 88 std::string iv(kIVBlockSizeAES128, ' '); 89 crypto::Encryptor encryptor; 90 if (!encryptor.Init(encryption_key.get(), crypto::Encryptor::CBC, iv)) 91 return false; 92 93 if (!encryptor.Encrypt(plaintext, ciphertext)) 94 return false; 95 96 // Prefix the cypher text with version information. 97 ciphertext->insert(0, kObfuscationPrefix); 98 return true; 99 } 100 101 bool Encryptor::DecryptString(const std::string& ciphertext, 102 std::string* plaintext) { 103 // This currently "obfuscates" by encrypting with hard-coded password. 104 // We need to improve this password situation by moving a secure password 105 // into a system-level key store. 106 // http://crbug.com/25404 and http://crbug.com/49115 107 108 if (ciphertext.empty()) { 109 *plaintext = std::string(); 110 return true; 111 } 112 113 // Check that the incoming cyphertext was indeed encrypted with the expected 114 // version. If the prefix is not found then we'll assume we're dealing with 115 // old data saved as clear text and we'll return it directly. 116 // Credit card numbers are current legacy data, so false match with prefix 117 // won't happen. 118 if (ciphertext.find(kObfuscationPrefix) != 0) { 119 *plaintext = ciphertext; 120 return true; 121 } 122 123 // Strip off the versioning prefix before decrypting. 124 std::string raw_ciphertext = ciphertext.substr(strlen(kObfuscationPrefix)); 125 126 scoped_ptr<crypto::SymmetricKey> encryption_key(GetEncryptionKey()); 127 if (!encryption_key.get()) 128 return false; 129 130 std::string iv(kIVBlockSizeAES128, ' '); 131 crypto::Encryptor encryptor; 132 if (!encryptor.Init(encryption_key.get(), crypto::Encryptor::CBC, iv)) 133 return false; 134 135 if (!encryptor.Decrypt(raw_ciphertext, plaintext)) 136 return false; 137 138 return true; 139 } 140