mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
Replace encrypting metadata with CBC to AES.
Provide a new API to decrypt the device metadata inside a public credential PiperOrigin-RevId: 466936093
This commit is contained in:
@@ -77,6 +77,12 @@ class CredentialManager {
|
||||
location::nearby::api::CredentialSelector credential_selector,
|
||||
location::nearby::api::GetPublicCredentialsResultCallback callback) = 0;
|
||||
|
||||
// Decrypts the device metadata from a public credential.
|
||||
// Returns an empty string if decryption fails.
|
||||
virtual std::string DecryptDeviceMetadata(
|
||||
std::string device_metadata_encryption_key, std::string authenticity_key,
|
||||
std::string device_metadata_string) = 0;
|
||||
|
||||
// Decrypts Data Elements from an NP advertisement.
|
||||
// Returns an error if `metadata_key` is not associated with any known
|
||||
// credentials (identity).
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "internal/crypto/aead.h"
|
||||
#include "internal/crypto/ec_private_key.h"
|
||||
#include "internal/crypto/encryptor.h"
|
||||
#include "internal/crypto/symmetric_key.h"
|
||||
#include "internal/crypto/hkdf.h"
|
||||
#include "internal/platform/base64_utils.h"
|
||||
#include "internal/platform/implementation/crypto.h"
|
||||
#include "internal/platform/logging.h"
|
||||
@@ -151,23 +151,76 @@ CredentialManagerImpl::CreatePublicCredential(
|
||||
metadata_encryption_key_tag.AsStringView());
|
||||
|
||||
// Encrypt the device metadata
|
||||
crypto::Encryptor encryptor;
|
||||
auto sym_key = crypto::SymmetricKey::Import(
|
||||
crypto::SymmetricKey::AES, private_credential->metadata_encryption_key());
|
||||
auto encrypted_meta_data = EncryptDeviceMetadata(
|
||||
private_credential->metadata_encryption_key(),
|
||||
private_credential->authenticity_key(),
|
||||
private_credential->device_metadata().SerializeAsString());
|
||||
|
||||
auto iv = Encryption::CustomizeBytesSize(
|
||||
private_credential->authenticity_key(), kAesGcmIVSize);
|
||||
// It is GCM in the spec. Here we use CBC instead since GCM is not supported
|
||||
// now.
|
||||
if (!encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv)) {
|
||||
NEARBY_LOG(ERROR, "Fails to initialize the encryptor");
|
||||
if (encrypted_meta_data.empty()) {
|
||||
NEARBY_LOG(ERROR, "Fails to encrypt the device metadata.");
|
||||
return std::unique_ptr<PublicCredential>(nullptr);
|
||||
}
|
||||
|
||||
encryptor.Encrypt(private_credential->device_metadata().SerializeAsString(),
|
||||
public_credential_ptr->mutable_encrypted_metadata_bytes());
|
||||
public_credential_ptr->set_encrypted_metadata_bytes(encrypted_meta_data);
|
||||
return public_credential_ptr;
|
||||
}
|
||||
|
||||
std::string CredentialManagerImpl::DecryptDeviceMetadata(
|
||||
std::string device_metadata_encryption_key, std::string authenticity_key,
|
||||
std::string device_metadata_string) {
|
||||
crypto::Aead aead(crypto::Aead::AeadAlgorithm::AES_256_GCM);
|
||||
|
||||
std::vector<uint8_t> derived_key =
|
||||
ExtendMetadataEncryptionKey(device_metadata_encryption_key);
|
||||
aead.Init(derived_key);
|
||||
|
||||
auto iv = Encryption::CustomizeBytesSize(
|
||||
authenticity_key, CredentialManagerImpl::kAesGcmIVSize);
|
||||
std::vector<uint8_t> iv_bytes(iv.begin(), iv.end());
|
||||
std::vector<uint8_t> encrypted_device_metadata_bytes(
|
||||
device_metadata_string.begin(), device_metadata_string.end());
|
||||
|
||||
auto result = aead.Open(encrypted_device_metadata_bytes,
|
||||
/*nonce=*/
|
||||
iv_bytes,
|
||||
/*additional_data=*/absl::Span<uint8_t>());
|
||||
|
||||
return std::string(result.value().begin(), result.value().end());
|
||||
}
|
||||
|
||||
std::string CredentialManagerImpl::EncryptDeviceMetadata(
|
||||
std::string device_metadata_encryption_key, std::string authenticity_key,
|
||||
std::string device_metadata_string) {
|
||||
crypto::Aead aead(crypto::Aead::AeadAlgorithm::AES_256_GCM);
|
||||
|
||||
std::vector<uint8_t> derived_key =
|
||||
ExtendMetadataEncryptionKey(device_metadata_encryption_key);
|
||||
|
||||
aead.Init(derived_key);
|
||||
|
||||
auto iv = Encryption::CustomizeBytesSize(authenticity_key, kAesGcmIVSize);
|
||||
std::vector<uint8_t> iv_bytes(iv.begin(), iv.end());
|
||||
|
||||
std::vector<uint8_t> device_metadata_bytes(device_metadata_string.begin(),
|
||||
device_metadata_string.end());
|
||||
device_metadata_bytes.resize(device_metadata_string.size());
|
||||
|
||||
auto encrypted = aead.Seal(device_metadata_bytes,
|
||||
/*nonce=*/
|
||||
iv_bytes,
|
||||
/*additional_data=*/absl::Span<uint8_t>());
|
||||
|
||||
return std::string(encrypted.begin(), encrypted.end());
|
||||
}
|
||||
|
||||
std::vector<uint8_t> CredentialManagerImpl::ExtendMetadataEncryptionKey(
|
||||
std::string device_metadata_encryption_key) {
|
||||
return crypto::HkdfSha256(
|
||||
std::vector<uint8_t>(device_metadata_encryption_key.begin(),
|
||||
device_metadata_encryption_key.end()),
|
||||
/*salt=*/absl::Span<uint8_t>(),
|
||||
/*info=*/absl::Span<uint8_t>(), kNearbyPresenceNumBytesAesGcmKeySize);
|
||||
}
|
||||
|
||||
} // namespace presence
|
||||
} // namespace nearby
|
||||
|
||||
@@ -38,14 +38,17 @@ class CredentialManagerImpl : public CredentialManager {
|
||||
// AES only supports key sizes of 16, 24 or 32 bytes.
|
||||
static constexpr int kAuthenticityKeyByteSize = 16;
|
||||
|
||||
// Length of key in bytes required by AES-GCM encryption.
|
||||
static constexpr size_t kNearbyPresenceNumBytesAesGcmKeySize = 32;
|
||||
|
||||
// Modify this to 12 after use real AES.
|
||||
static constexpr int kAesGcmIVSize = 16;
|
||||
static constexpr int kAesGcmIVSize = 12;
|
||||
|
||||
void GenerateCredentials(
|
||||
proto::DeviceMetadata device_metadata,
|
||||
std::vector<proto::IdentityType> identity_types,
|
||||
int credential_life_cycle_days, int contiguous_copy_of_credentials,
|
||||
GenerateCredentialsCallback credentials_generated_cb);
|
||||
GenerateCredentialsCallback credentials_generated_cb) override;
|
||||
|
||||
void UpdateRemotePublicCredentials(
|
||||
std::string account_name,
|
||||
@@ -63,6 +66,10 @@ class CredentialManagerImpl : public CredentialManager {
|
||||
location::nearby::api::GetPublicCredentialsResultCallback callback)
|
||||
override {}
|
||||
|
||||
std::string DecryptDeviceMetadata(
|
||||
std::string device_metadata_encryption_key, std::string authenticity_key,
|
||||
std::string device_metadata_string) override;
|
||||
|
||||
absl::StatusOr<std::string> DecryptDataElements(
|
||||
absl::string_view metadata_key, absl::string_view salt,
|
||||
absl::string_view data_elements) override {
|
||||
@@ -93,6 +100,14 @@ class CredentialManagerImpl : public CredentialManager {
|
||||
std::unique_ptr<proto::PublicCredential> CreatePublicCredential(
|
||||
proto::PrivateCredential* private_credential_ptr,
|
||||
std::vector<uint8_t>* public_key);
|
||||
|
||||
std::string EncryptDeviceMetadata(std::string device_metadata_encryption_key,
|
||||
std::string authenticity_key,
|
||||
std::string device_metadata_string);
|
||||
|
||||
// Extend the key from 16 bytes to 32 bytes.
|
||||
std::vector<uint8_t> ExtendMetadataEncryptionKey(
|
||||
std::string device_metadata_encryption_key);
|
||||
};
|
||||
|
||||
} // namespace presence
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
#include "gmock/gmock.h"
|
||||
#include "protobuf-matchers/protocol-buffer-matchers.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "internal/crypto/encryptor.h"
|
||||
#include "internal/crypto/symmetric_key.h"
|
||||
#include "internal/crypto/aead.h"
|
||||
#include "internal/crypto/hkdf.h"
|
||||
#include "internal/platform/implementation/crypto.h"
|
||||
#include "presence/encryption.h"
|
||||
|
||||
@@ -80,19 +80,14 @@ TEST(CredentialManagerImpl, CreateOneCredentialSuccessfully) {
|
||||
EXPECT_FALSE(public_credential->encrypted_metadata_bytes().empty());
|
||||
|
||||
// Decrypt the device metadata
|
||||
crypto::Encryptor encryptor;
|
||||
auto sym_key = crypto::SymmetricKey::Import(
|
||||
crypto::SymmetricKey::AES, private_credential->metadata_encryption_key());
|
||||
EXPECT_TRUE(sym_key.get() != nullptr);
|
||||
auto iv =
|
||||
Encryption::CustomizeBytesSize(private_credential->authenticity_key(),
|
||||
CredentialManagerImpl::kAesGcmIVSize);
|
||||
encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv);
|
||||
std::string decrypted_metadata;
|
||||
EXPECT_TRUE(encryptor.Decrypt(public_credential->encrypted_metadata_bytes(),
|
||||
&decrypted_metadata));
|
||||
|
||||
auto decrypted_device_metadata = credential_manager.DecryptDeviceMetadata(
|
||||
private_credential->metadata_encryption_key(),
|
||||
public_credential->authenticity_key(),
|
||||
public_credential->encrypted_metadata_bytes());
|
||||
|
||||
EXPECT_EQ(private_credential->device_metadata().SerializeAsString(),
|
||||
decrypted_metadata);
|
||||
decrypted_device_metadata);
|
||||
}
|
||||
} // namespace presence
|
||||
} // namespace nearby
|
||||
|
||||
Reference in New Issue
Block a user