Add some test data helpers for BlindSignAuth

The test helper is added to the quiche library which already has the needed
visibility for the various proto types.

The test data helper created here is based on the test items created in
blind_sign_auth_test.cc.

PiperOrigin-RevId: 786727752
diff --git a/build/source_list.bzl b/build/source_list.bzl
index 8d16362..2c98197 100644
--- a/build/source_list.bzl
+++ b/build/source_list.bzl
@@ -1710,6 +1710,7 @@
     "blind_sign_auth/blind_sign_auth.h",
     "blind_sign_auth/blind_sign_auth_interface.h",
     "blind_sign_auth/blind_sign_auth_protos.h",
+    "blind_sign_auth/blind_sign_auth_test_data.h",
     "blind_sign_auth/blind_sign_message_interface.h",
     "blind_sign_auth/blind_sign_message_response.h",
     "blind_sign_auth/cached_blind_sign_auth.h",
@@ -1718,6 +1719,7 @@
 ]
 blind_sign_auth_srcs = [
     "blind_sign_auth/blind_sign_auth.cc",
+    "blind_sign_auth/blind_sign_auth_test_data.cc",
     "blind_sign_auth/blind_sign_message_response.cc",
     "blind_sign_auth/cached_blind_sign_auth.cc",
 ]
@@ -1725,6 +1727,7 @@
 ]
 blind_sign_auth_tests_srcs = [
     "blind_sign_auth/blind_sign_auth_test.cc",
+    "blind_sign_auth/blind_sign_auth_test_data_test.cc",
     "blind_sign_auth/cached_blind_sign_auth_test.cc",
 ]
 protobuf_blind_sign_auth = [
diff --git a/build/source_list.gni b/build/source_list.gni
index 726384e..6be36a6 100644
--- a/build/source_list.gni
+++ b/build/source_list.gni
@@ -1714,6 +1714,7 @@
     "src/quiche/blind_sign_auth/blind_sign_auth.h",
     "src/quiche/blind_sign_auth/blind_sign_auth_interface.h",
     "src/quiche/blind_sign_auth/blind_sign_auth_protos.h",
+    "src/quiche/blind_sign_auth/blind_sign_auth_test_data.h",
     "src/quiche/blind_sign_auth/blind_sign_message_interface.h",
     "src/quiche/blind_sign_auth/blind_sign_message_response.h",
     "src/quiche/blind_sign_auth/cached_blind_sign_auth.h",
@@ -1722,6 +1723,7 @@
 ]
 blind_sign_auth_srcs = [
     "src/quiche/blind_sign_auth/blind_sign_auth.cc",
+    "src/quiche/blind_sign_auth/blind_sign_auth_test_data.cc",
     "src/quiche/blind_sign_auth/blind_sign_message_response.cc",
     "src/quiche/blind_sign_auth/cached_blind_sign_auth.cc",
 ]
@@ -1730,6 +1732,7 @@
 ]
 blind_sign_auth_tests_srcs = [
     "src/quiche/blind_sign_auth/blind_sign_auth_test.cc",
+    "src/quiche/blind_sign_auth/blind_sign_auth_test_data_test.cc",
     "src/quiche/blind_sign_auth/cached_blind_sign_auth_test.cc",
 ]
 protobuf_blind_sign_auth = [
diff --git a/build/source_list.json b/build/source_list.json
index da96f98..19b4cdf 100644
--- a/build/source_list.json
+++ b/build/source_list.json
@@ -1713,6 +1713,7 @@
     "quiche/blind_sign_auth/blind_sign_auth.h",
     "quiche/blind_sign_auth/blind_sign_auth_interface.h",
     "quiche/blind_sign_auth/blind_sign_auth_protos.h",
+    "quiche/blind_sign_auth/blind_sign_auth_test_data.h",
     "quiche/blind_sign_auth/blind_sign_message_interface.h",
     "quiche/blind_sign_auth/blind_sign_message_response.h",
     "quiche/blind_sign_auth/cached_blind_sign_auth.h",
@@ -1721,6 +1722,7 @@
   ],
   "blind_sign_auth_srcs": [
     "quiche/blind_sign_auth/blind_sign_auth.cc",
+    "quiche/blind_sign_auth/blind_sign_auth_test_data.cc",
     "quiche/blind_sign_auth/blind_sign_message_response.cc",
     "quiche/blind_sign_auth/cached_blind_sign_auth.cc"
   ],
@@ -1729,6 +1731,7 @@
   ],
   "blind_sign_auth_tests_srcs": [
     "quiche/blind_sign_auth/blind_sign_auth_test.cc",
+    "quiche/blind_sign_auth/blind_sign_auth_test_data_test.cc",
     "quiche/blind_sign_auth/cached_blind_sign_auth_test.cc"
   ],
   "protobuf_blind_sign_auth": [
diff --git a/quiche/blind_sign_auth/blind_sign_auth_test_data.cc b/quiche/blind_sign_auth/blind_sign_auth_test_data.cc
new file mode 100644
index 0000000..d9e1318
--- /dev/null
+++ b/quiche/blind_sign_auth/blind_sign_auth_test_data.cc
@@ -0,0 +1,221 @@
+// Copyright (c) 2025 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "quiche/blind_sign_auth/blind_sign_auth_test_data.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/clock.h"
+#include "absl/time/time.h"
+#include "anonymous_tokens/cpp/crypto/crypto_utils.h"
+#include "anonymous_tokens/cpp/privacy_pass/token_encodings.h"
+#include "anonymous_tokens/cpp/testing/utils.h"
+#include "openssl/base.h"
+#include "openssl/digest.h"
+
+namespace quiche::test {
+
+using ::privacy::ppn::AttestAndSignResponse;
+using ::privacy::ppn::GetInitialDataResponse;
+using ::anonymous_tokens::AT_HASH_TYPE_SHA384;
+using ::anonymous_tokens::AT_MESSAGE_MASK_NO_MASK;
+using ::anonymous_tokens::AT_MGF_SHA384;
+using ::anonymous_tokens::ComputeHash;
+using ::anonymous_tokens::CreatePrivateKeyRSA;
+using ::anonymous_tokens::CreatePublicKeyRSA;
+using ::anonymous_tokens::DebugMode;
+using ::anonymous_tokens::EncodeExtensions;
+using ::anonymous_tokens::ExpirationTimestamp;
+using ::anonymous_tokens::Extension;
+using ::anonymous_tokens::Extensions;
+using ::anonymous_tokens::GeoHint;
+using ::anonymous_tokens::GetStrongTestRsaKeyPair2048;
+using ::anonymous_tokens::ProxyLayer;
+using ::anonymous_tokens::RSABlindSignaturePublicKey;
+using ::anonymous_tokens::RSAPublicKey;
+using ::anonymous_tokens::RsaSsaPssPublicKeyToDerEncoding;
+using ::anonymous_tokens::ServiceType;
+using ::anonymous_tokens::TestRsaPublicKey;
+
+namespace {
+
+// Helpers
+absl::StatusOr<Extensions> CreateExtensions();
+RSABlindSignaturePublicKey CreatePublicKeyProto(
+    TestRsaPublicKey test_rsa_public_key);
+
+}  // namespace
+
+absl::StatusOr<std::unique_ptr<BlindSignAuthTestData>>
+BlindSignAuthTestData::Create() {
+  // Create keypair and populate protos.
+  auto [test_rsa_public_key, test_rsa_private_key] =
+      GetStrongTestRsaKeyPair2048();
+  absl::StatusOr<bssl::UniquePtr<RSA>> rsa_public_key =
+      CreatePublicKeyRSA(test_rsa_public_key.n, test_rsa_public_key.e);
+  if (!rsa_public_key.ok()) {
+    return rsa_public_key.status();
+  }
+
+  absl::StatusOr<bssl::UniquePtr<RSA>> rsa_private_key = CreatePrivateKeyRSA(
+      test_rsa_private_key.n, test_rsa_private_key.e, test_rsa_private_key.d,
+      test_rsa_private_key.p, test_rsa_private_key.q, test_rsa_private_key.dp,
+      test_rsa_private_key.dq, test_rsa_private_key.crt);
+  if (!rsa_private_key.ok()) {
+    return rsa_private_key.status();
+  }
+
+  // token_key_id is derived from public key.
+  absl::StatusOr<std::string> public_key_der =
+      RsaSsaPssPublicKeyToDerEncoding(rsa_public_key->get());
+  if (!public_key_der.ok()) {
+    return public_key_der.status();
+  }
+
+  const EVP_MD *sha256 = EVP_sha256();
+  absl::StatusOr<std::string> token_key_id =
+      ComputeHash(*public_key_der, *sha256);
+  if (!token_key_id.ok()) {
+    return token_key_id.status();
+  }
+
+  absl::StatusOr<Extensions> extensions = CreateExtensions();
+  if (!extensions.ok()) {
+    return extensions.status();
+  }
+
+  absl::StatusOr<std::string> serialized_extensions =
+      EncodeExtensions(*extensions);
+  if (!serialized_extensions.ok()) {
+    return serialized_extensions.status();
+  }
+
+  GetInitialDataResponse::PrivacyPassData privacy_pass_data;
+  privacy_pass_data.set_token_key_id(*token_key_id);
+  privacy_pass_data.set_public_metadata_extensions(*serialized_extensions);
+
+  return absl::WrapUnique(new BlindSignAuthTestData(
+      std::move(*rsa_public_key), std::move(*rsa_private_key),
+      CreatePublicKeyProto(test_rsa_public_key), privacy_pass_data));
+}
+
+GetInitialDataResponse BlindSignAuthTestData::CreateGetInitialDataResponse() {
+  GetInitialDataResponse response;
+
+  *response.mutable_at_public_metadata_public_key() = public_key_proto_;
+  *response.mutable_privacy_pass_data() = privacy_pass_data_;
+
+  // Create fake GetInitialDataResponse for attestation flow.
+  response.mutable_attestation()->set_attestation_nonce(
+      "test_attestation_nonce");
+  return response;
+}
+
+absl::StatusOr<privacy::ppn::AttestAndSignResponse>
+BlindSignAuthTestData::CreateAttestAndSignResponse(absl::string_view body) {
+  privacy::ppn::AttestAndSignRequest request;
+  if (!request.ParseFromString(body)) {
+    return absl::InvalidArgumentError("Failed to parse AttestAndSignRequest");
+  }
+
+  privacy::ppn::AttestAndSignResponse response;
+  for (const auto &request_token : request.blinded_tokens()) {
+    std::string decoded_blinded_token;
+    if (!absl::Base64Unescape(request_token, &decoded_blinded_token)) {
+      return absl::InvalidArgumentError("Failed to decode blinded token");
+    }
+    absl::StatusOr<std::string> signature =
+        anonymous_tokens::TestSignWithPublicMetadata(
+            decoded_blinded_token,
+            privacy_pass_data_.public_metadata_extensions(), *rsa_private_key_,
+            false);
+    if (!signature.ok()) {
+      return signature.status();
+    }
+    response.add_blinded_token_signatures(absl::Base64Escape(*signature));
+  }
+
+  return response;
+}
+
+namespace {
+
+absl::StatusOr<anonymous_tokens::Extensions>
+CreateExtensions() {
+  // Create and serialize fake extensions.
+  Extensions extensions;
+  ExpirationTimestamp expiration_timestamp;
+  int64_t one_hour_away = absl::ToUnixSeconds(absl::Now() + absl::Hours(1));
+  expiration_timestamp.timestamp = one_hour_away - (one_hour_away % 900);
+  expiration_timestamp.timestamp_precision = 900;
+  absl::StatusOr<anonymous_tokens::Extension>
+      expiration_extension = expiration_timestamp.AsExtension();
+  if (!expiration_extension.ok()) {
+    return expiration_extension.status();
+  }
+  extensions.extensions.push_back(*expiration_extension);
+
+  GeoHint geo_hint;
+  geo_hint.geo_hint = "US,US-AL,ALABASTER";
+  absl::StatusOr<Extension> geo_hint_extension = geo_hint.AsExtension();
+  if (!geo_hint_extension.ok()) {
+    return geo_hint_extension.status();
+  }
+  extensions.extensions.push_back(*geo_hint_extension);
+
+  ServiceType service_type;
+  service_type.service_type_id = ServiceType::kChromeIpBlinding;
+  absl::StatusOr<Extension> service_type_extension = service_type.AsExtension();
+  if (!service_type_extension.ok()) {
+    return service_type_extension.status();
+  }
+  extensions.extensions.push_back(*service_type_extension);
+
+  DebugMode debug_mode;
+  debug_mode.mode = DebugMode::kDebug;
+  absl::StatusOr<Extension> debug_mode_extension = debug_mode.AsExtension();
+  if (!debug_mode_extension.ok()) {
+    return debug_mode_extension.status();
+  }
+  extensions.extensions.push_back(*debug_mode_extension);
+
+  ProxyLayer proxy_layer;
+  proxy_layer.layer = ProxyLayer::kProxyA;
+  absl::StatusOr<Extension> proxy_layer_extension = proxy_layer.AsExtension();
+  if (!proxy_layer_extension.ok()) {
+    return proxy_layer_extension.status();
+  }
+  extensions.extensions.push_back(*proxy_layer_extension);
+
+  return extensions;
+}
+
+RSABlindSignaturePublicKey CreatePublicKeyProto(
+    TestRsaPublicKey test_rsa_public_key) {
+  RSAPublicKey public_key;
+  public_key.set_n(test_rsa_public_key.n);
+  public_key.set_e(test_rsa_public_key.e);
+  RSABlindSignaturePublicKey public_key_proto;
+  public_key_proto.set_key_version(1);
+  public_key_proto.set_use_case("TEST_USE_CASE");
+  public_key_proto.set_serialized_public_key(public_key.SerializeAsString());
+  public_key_proto.set_sig_hash_type(AT_HASH_TYPE_SHA384);
+  public_key_proto.set_mask_gen_function(AT_MGF_SHA384);
+  public_key_proto.set_salt_length(48);
+  public_key_proto.set_key_size(256);
+  public_key_proto.set_message_mask_type(AT_MESSAGE_MASK_NO_MASK);
+  public_key_proto.set_message_mask_size(0);
+
+  return public_key_proto;
+}
+
+}  // namespace
+
+}  // namespace quiche::test
diff --git a/quiche/blind_sign_auth/blind_sign_auth_test_data.h b/quiche/blind_sign_auth/blind_sign_auth_test_data.h
new file mode 100644
index 0000000..389afe1
--- /dev/null
+++ b/quiche/blind_sign_auth/blind_sign_auth_test_data.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2025 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_BLIND_SIGN_AUTH_BLIND_SIGN_AUTH_TEST_DATA_H_
+#define QUICHE_BLIND_SIGN_AUTH_BLIND_SIGN_AUTH_TEST_DATA_H_
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "absl/status/statusor.h"
+#include "absl/strings/string_view.h"
+#include "anonymous_tokens/cpp/crypto/crypto_utils.h"  // IWYU pragma: keep
+#include "openssl/base.h"
+#include "quiche/blind_sign_auth/blind_sign_auth_protos.h"
+#include "quiche/common/platform/api/quiche_export.h"
+
+namespace quiche::test {
+
+class QUICHE_NO_EXPORT BlindSignAuthTestData {
+ public:
+  static absl::StatusOr<std::unique_ptr<BlindSignAuthTestData>> Create();
+
+  privacy::ppn::GetInitialDataResponse CreateGetInitialDataResponse();
+
+  absl::StatusOr<privacy::ppn::AttestAndSignResponse>
+  CreateAttestAndSignResponse(absl::string_view body);
+
+ private:
+  BlindSignAuthTestData(
+      bssl::UniquePtr<RSA> rsa_public_key, bssl::UniquePtr<RSA> rsa_private_key,
+      anonymous_tokens::RSABlindSignaturePublicKey
+          public_key_proto,
+      privacy::ppn::GetInitialDataResponse::PrivacyPassData privacy_pass_data)
+      : rsa_public_key_(std::move(rsa_public_key)),
+        rsa_private_key_(std::move(rsa_private_key)),
+        public_key_proto_(std::move(public_key_proto)),
+        privacy_pass_data_(std::move(privacy_pass_data)) {}
+
+  bssl::UniquePtr<RSA> rsa_public_key_;
+  bssl::UniquePtr<RSA> rsa_private_key_;
+  anonymous_tokens::RSABlindSignaturePublicKey
+      public_key_proto_;
+  privacy::ppn::GetInitialDataResponse::PrivacyPassData privacy_pass_data_;
+};
+
+}  // namespace quiche::test
+
+#endif  // QUICHE_BLIND_SIGN_AUTH_BLIND_SIGN_AUTH_TEST_DATA_H_
diff --git a/quiche/blind_sign_auth/blind_sign_auth_test_data_test.cc b/quiche/blind_sign_auth/blind_sign_auth_test_data_test.cc
new file mode 100644
index 0000000..f0430a8
--- /dev/null
+++ b/quiche/blind_sign_auth/blind_sign_auth_test_data_test.cc
@@ -0,0 +1,14 @@
+#include "quiche/blind_sign_auth/blind_sign_auth_test_data.h"
+
+#include "quiche/common/platform/api/quiche_test.h"
+#include "quiche/common/test_tools/quiche_test_utils.h"
+
+namespace quiche::test {
+namespace {
+
+TEST(BlindSignAuthTestDataTest, CreateTestData) {
+  QUICHE_EXPECT_OK(BlindSignAuthTestData::Create());
+}
+
+}  // namespace
+}  // namespace quiche::test