910e62b5创建于 1月15日历史提交
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/aggregation_service/public_key_parsing_utils.h"

#include <string>
#include <vector>

#include "base/json/json_reader.h"
#include "base/strings/string_util.h"
#include "content/browser/aggregation_service/aggregation_service_test_utils.h"
#include "content/browser/aggregation_service/public_key.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace content {

TEST(PublicKeyParsingUtilsTest, WellFormedSingleKey_ParsedCorrectly) {
  aggregation_service::TestHpkeKey generated_key{/*key_id=*/"abcd"};

  std::string json_string = base::ReplaceStringPlaceholders(
      R"({
            "keys": [
                {
                   "id": "abcd",
                   "key": "$1"
                }
            ]
         })",
      {generated_key.GetPublicKeyBase64()}, /*offsets=*/nullptr);

  std::optional<base::Value> json_object =
      base::JSONReader::Read(json_string, base::JSON_PARSE_CHROMIUM_EXTENSIONS);
  ASSERT_TRUE(json_object) << "Incorrectly formatted JSON string.";

  std::vector<PublicKey> keys =
      aggregation_service::GetPublicKeys(json_object.value());
  EXPECT_TRUE(aggregation_service::PublicKeysEqual(
      {generated_key.GetPublicKey()}, keys));
}

TEST(PublicKeyParsingUtilsTest, WellFormedMultipleKeys_ParsedCorrectly) {
  aggregation_service::TestHpkeKey generated_key_1{/*key_id=*/"abcd"};
  aggregation_service::TestHpkeKey generated_key_2{/*key_id=*/"efgh"};

  std::string json_string = base::ReplaceStringPlaceholders(
      R"({
            "keys": [
                {
                    "id": "abcd",
                    "key": "$1"
                },
                {
                    "id": "efgh",
                    "key": "$2"
                }
            ]
         })",
      {generated_key_1.GetPublicKeyBase64(),
       generated_key_2.GetPublicKeyBase64()},
      /*offsets=*/nullptr);

  std::optional<base::Value> json_object =
      base::JSONReader::Read(json_string, base::JSON_PARSE_CHROMIUM_EXTENSIONS);
  ASSERT_TRUE(json_object) << "Incorrectly formatted JSON string.";

  std::vector<PublicKey> keys =
      aggregation_service::GetPublicKeys(json_object.value());
  EXPECT_TRUE(aggregation_service::PublicKeysEqual(
      {generated_key_1.GetPublicKey(), generated_key_2.GetPublicKey()}, keys));
}

TEST(PublicKeyParsingUtilsTest, MalformedMissingId_EmptyResult) {
  std::string json_string = base::ReplaceStringPlaceholders(
      R"({
            "keys": [
                {
                    "key": "$1"
                }
            ]
         })",
      {aggregation_service::TestHpkeKey().GetPublicKeyBase64()},
      /*offsets=*/nullptr);

  std::optional<base::Value> json_object =
      base::JSONReader::Read(json_string, base::JSON_PARSE_CHROMIUM_EXTENSIONS);
  ASSERT_TRUE(json_object) << "Incorrectly formatted JSON string.";

  std::vector<PublicKey> keys =
      aggregation_service::GetPublicKeys(json_object.value());
  EXPECT_TRUE(keys.empty());
}

TEST(PublicKeyParsingUtilsTest, MalformedMissingKey_EmptyResult) {
  std::string json_string = R"(
        {
            "keys": [
                {
                    "id": "abcd"
                }
            ]
        }
    )";

  std::optional<base::Value> json_object =
      base::JSONReader::Read(json_string, base::JSON_PARSE_CHROMIUM_EXTENSIONS);
  ASSERT_TRUE(json_object) << "Incorrectly formatted JSON string.";

  std::vector<PublicKey> keys =
      aggregation_service::GetPublicKeys(json_object.value());
  EXPECT_TRUE(keys.empty());
}

TEST(PublicKeyParsingUtilsTest, MalformedKeyNotValidBase64_EmptyResult) {
  std::string invalid_base64 =
      aggregation_service::TestHpkeKey().GetPublicKeyBase64();
  // Replace a character with an invalid one.
  invalid_base64[5] = '-';

  std::string json_string = base::ReplaceStringPlaceholders(
      R"({
            "keys": [
                {
                   "id": "abcd",
                   "key": "$1"
                }
            ]
         })",
      {invalid_base64}, /*offsets=*/nullptr);

  std::optional<base::Value> json_object =
      base::JSONReader::Read(json_string, base::JSON_PARSE_CHROMIUM_EXTENSIONS);
  ASSERT_TRUE(json_object) << "Incorrectly formatted JSON string.";

  std::vector<PublicKey> keys =
      aggregation_service::GetPublicKeys(json_object.value());
  EXPECT_TRUE(keys.empty());
}

TEST(PublicKeyParsingUtilsTest, MalformedKeyWrongLength_EmptyResult) {
  std::string wrong_length_key =
      aggregation_service::TestHpkeKey().GetPublicKeyBase64();
  wrong_length_key.resize(16);

  std::string json_string = base::ReplaceStringPlaceholders(
      R"({
            "keys": [
                {
                   "id": "abcd",
                   "key": "$1"
                }
            ]
         })",
      {wrong_length_key}, /*offsets=*/nullptr);

  std::optional<base::Value> json_object =
      base::JSONReader::Read(json_string, base::JSON_PARSE_CHROMIUM_EXTENSIONS);
  ASSERT_TRUE(json_object) << "Incorrectly formatted JSON string.";

  std::vector<PublicKey> keys =
      aggregation_service::GetPublicKeys(json_object.value());
  EXPECT_TRUE(keys.empty());
}

TEST(PublicKeyParsingUtilsTest, WellFormedAndMalformedKeys_EmptyResult) {
  std::string json_string = base::ReplaceStringPlaceholders(
      R"({
            "keys": [
                {
                    "id": "abcd",
                    "key": "$1"
                },
                {
                    "id": "efgh"
                }
            ]
         }
    )",
      {aggregation_service::TestHpkeKey().GetPublicKeyBase64()},
      /*offsets=*/nullptr);

  std::optional<base::Value> json_object =
      base::JSONReader::Read(json_string, base::JSON_PARSE_CHROMIUM_EXTENSIONS);
  ASSERT_TRUE(json_object) << "Incorrectly formatted JSON string.";

  std::vector<PublicKey> keys =
      aggregation_service::GetPublicKeys(json_object.value());
  EXPECT_TRUE(keys.empty());
}

TEST(PublicKeyParsingUtilsTest, MalformedKeyDuplicateKeyId_EmptyResult) {
  std::string json_string = base::ReplaceStringPlaceholders(
      R"({
            "keys": [
                {
                    "id": "abcd",
                    "key": "$1"
                },
                {
                    "id": "abcd",
                    "key": "$2"
                }
            ]
         })",
      {aggregation_service::TestHpkeKey(/*key_id=*/"abcd").GetPublicKeyBase64(),
       aggregation_service::TestHpkeKey(/*key_id=*/"abcd")
           .GetPublicKeyBase64()},
      /*offsets=*/nullptr);

  std::optional<base::Value> json_object =
      base::JSONReader::Read(json_string, base::JSON_PARSE_CHROMIUM_EXTENSIONS);
  ASSERT_TRUE(json_object) << "Incorrectly formatted JSON string.";

  std::vector<PublicKey> keys =
      aggregation_service::GetPublicKeys(json_object.value());
  EXPECT_TRUE(keys.empty());
}

TEST(PublicKeyParsingUtilsTest, VersionFieldSpecified_FieldIgnored) {
  aggregation_service::TestHpkeKey generated_key{/*key_id=*/"abcd"};

  std::string json_string = base::ReplaceStringPlaceholders(
      R"({
            "version": "",
            "keys": [
                {
                   "id": "abcd",
                   "key": "$1"
                }
            ]
         })",
      {generated_key.GetPublicKeyBase64()}, /*offsets=*/nullptr);

  std::optional<base::Value> json_object =
      base::JSONReader::Read(json_string, base::JSON_PARSE_CHROMIUM_EXTENSIONS);
  ASSERT_TRUE(json_object) << "Incorrectly formatted JSON string.";

  std::vector<PublicKey> keys =
      aggregation_service::GetPublicKeys(json_object.value());
  EXPECT_TRUE(aggregation_service::PublicKeysEqual(
      {generated_key.GetPublicKey()}, keys));
}

TEST(PublicKeyParsingUtilsTest, ExtraUnexpectedField_FieldIgnored) {
  aggregation_service::TestHpkeKey generated_key{/*key_id=*/"abcd"};

  std::string json_string = base::ReplaceStringPlaceholders(
      R"({
            "unexpected_field": [{ "foo": 123, "bar": "baz" }, {}],
            "keys": [
                {
                   "id": "abcd",
                   "key": "$1"
                }
            ]
         })",
      {generated_key.GetPublicKeyBase64()}, /*offsets=*/nullptr);

  std::optional<base::Value> json_object =
      base::JSONReader::Read(json_string, base::JSON_PARSE_CHROMIUM_EXTENSIONS);
  ASSERT_TRUE(json_object) << "Incorrectly formatted JSON string.";

  std::vector<PublicKey> keys =
      aggregation_service::GetPublicKeys(json_object.value());
  EXPECT_TRUE(aggregation_service::PublicKeysEqual(
      {generated_key.GetPublicKey()}, keys));
}

}  // namespace content