ash: migrate ash::Key to new crypto APIs
Specifically, from crypto/sha2 to crypto/hash and from crypto/symmetric_key to crypto/kdf. Bug: 372283556 Change-Id: If5dfd6a5f5f2e7ed3f02e0fa3591ed424d26966e Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6254501 Reviewed-by: Denis Kuznetsov <antrim@chromium.org> Commit-Queue: Elly FJ <ellyjones@chromium.org> Cr-Commit-Position: refs/heads/main@{#1419655}
This commit is contained in:
@ -11,19 +11,12 @@
|
||||
#include "base/notreached.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "crypto/sha2.h"
|
||||
#include "crypto/symmetric_key.h"
|
||||
#include "crypto/hash.h"
|
||||
#include "crypto/kdf.h"
|
||||
#include "crypto/subtle_passkey.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
namespace {
|
||||
|
||||
// Parameters for the transformation to KEY_TYPE_SALTED_AES256_1234.
|
||||
const int kNumIterations = 1234;
|
||||
const int kKeySizeInBits = 256;
|
||||
|
||||
} // namespace
|
||||
|
||||
Key::Key() : key_type_(KEY_TYPE_PASSWORD_PLAIN) {}
|
||||
|
||||
Key::Key(const Key& other) = default;
|
||||
@ -66,30 +59,37 @@ void Key::Transform(KeyType target_key_type, const std::string& salt) {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
std::string salted_secret = salt + secret_;
|
||||
switch (target_key_type) {
|
||||
case KEY_TYPE_SALTED_SHA256_TOP_HALF: {
|
||||
// TODO(stevenjb/nkostylev): Handle empty salt gracefully.
|
||||
CHECK(!salt.empty());
|
||||
char hash[crypto::kSHA256Length];
|
||||
crypto::SHA256HashString(salt + secret_, &hash, sizeof(hash));
|
||||
auto hash = crypto::hash::Sha256(base::as_byte_span(salted_secret));
|
||||
|
||||
// Keep only the first half of the hash for 'weak' hashing so that the
|
||||
// plain text secret cannot be reconstructed even if the hashing is
|
||||
// reversed.
|
||||
secret_ = base::ToLowerASCII(base::HexEncode(
|
||||
reinterpret_cast<const void*>(hash), sizeof(hash) / 2));
|
||||
//
|
||||
// Crypto note: this does not make much sense. An exhaustive search for
|
||||
// the input secret would just need to check for the first half of the
|
||||
// hash matching to have an extremely high probability of being the
|
||||
// correct secret anyway, and there's not (nor is there likely to be) any
|
||||
// feasible way to invert SHA-256 directly.
|
||||
secret_ = base::ToLowerASCII(
|
||||
base::HexEncode(base::span(hash).first(hash.size() / 2)));
|
||||
break;
|
||||
}
|
||||
case KEY_TYPE_SALTED_PBKDF2_AES256_1234: {
|
||||
std::unique_ptr<crypto::SymmetricKey> key(
|
||||
crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
|
||||
crypto::SymmetricKey::AES, secret_, salt, kNumIterations,
|
||||
kKeySizeInBits));
|
||||
secret_ = base::Base64Encode(key->key());
|
||||
std::array<uint8_t, 32> derived;
|
||||
crypto::kdf::DeriveKeyPbkdf2HmacSha1(
|
||||
{.iterations = 1234}, base::as_byte_span(secret_),
|
||||
base::as_byte_span(salt), derived, crypto::SubtlePassKey{});
|
||||
secret_ = base::Base64Encode(derived);
|
||||
break;
|
||||
}
|
||||
case KEY_TYPE_SALTED_SHA256:
|
||||
secret_ = base::Base64Encode(crypto::SHA256HashString(salt + secret_));
|
||||
secret_ = base::Base64Encode(
|
||||
crypto::hash::Sha256(base::as_byte_span(salted_secret)));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
namespace ash {
|
||||
class CryptohomeTokenEncryptor;
|
||||
class Key;
|
||||
}
|
||||
|
||||
namespace syncer {
|
||||
@ -65,6 +66,10 @@ class CRYPTO_EXPORT SubtlePassKey final {
|
||||
// compatibility with existing persisted data.
|
||||
friend class ::OSCryptImpl;
|
||||
friend class os_crypt_async::FreedesktopSecretKeyProvider;
|
||||
|
||||
// This class uses custom PBKDF2 parameters which cannot be changed for
|
||||
// compatibility with persisted data.
|
||||
friend class ash::Key;
|
||||
};
|
||||
|
||||
} // namespace crypto
|
||||
|
Reference in New Issue
Block a user