Updating anonymous token signing client-side code to start using public metadata in calls to cryptographic libraries.
PiperOrigin-RevId: 525817000
diff --git a/quiche/blind_sign_auth/anonymous_tokens/cpp/client/anonymous_tokens_rsa_bssa_client.cc b/quiche/blind_sign_auth/anonymous_tokens/cpp/client/anonymous_tokens_rsa_bssa_client.cc
index 2ccd9c5..77e2e9e 100644
--- a/quiche/blind_sign_auth/anonymous_tokens/cpp/client/anonymous_tokens_rsa_bssa_client.cc
+++ b/quiche/blind_sign_auth/anonymous_tokens/cpp/client/anonymous_tokens_rsa_bssa_client.cc
@@ -120,20 +120,20 @@
AnonymousTokensSignRequest request;
for (const PlaintextMessageWithPublicMetadata& input : inputs) {
- if (input.plaintext_message().empty()) {
- return absl::InvalidArgumentError(
- "Cannot send an empty message to sign.");
- }
-
// Generate nonce and masked message. For more details, see
// https://datatracker.ietf.org/doc/draft-irtf-cfrg-rsa-blind-signatures/
ANON_TOKENS_ASSIGN_OR_RETURN(std::string mask, GenerateMask(public_key_));
std::string masked_message =
MaskMessageConcat(mask, input.plaintext_message());
+ std::optional<std::string> public_metadata = std::nullopt;
+ if (public_key_.public_metadata_support()) {
+ // Empty public metadata is a valid value.
+ public_metadata = input.public_metadata();
+ }
// Generate RSA blinder.
ANON_TOKENS_ASSIGN_OR_RETURN(auto rsa_bssa_blinder,
- RsaBlinder::New(public_key_));
+ RsaBlinder::New(public_key_, public_metadata));
ANON_TOKENS_ASSIGN_OR_RETURN(const std::string blinded_message,
rsa_bssa_blinder->Blind(masked_message));
@@ -217,7 +217,7 @@
if (blinding_info.input.public_metadata() !=
anonymous_token.public_metadata()) {
return absl::InvalidArgumentError(
- "Response metadata does not match input.");
+ "Response public metadata does not match input.");
}
// Unblind the blinded anonymous token to obtain the final anonymous token
@@ -246,8 +246,9 @@
}
absl::Status AnonymousTokensRsaBssaClient::Verify(
- const RSABlindSignatureToken& /*token*/, absl::string_view /*message*/,
- absl::optional<absl::string_view> /*public_metadata*/) {
+ const RSABlindSignaturePublicKey& /*public_key*/,
+ const RSABlindSignatureToken& /*token*/,
+ const PlaintextMessageWithPublicMetadata& /*input*/) {
return absl::UnimplementedError("Verify not implemented yet.");
}
diff --git a/quiche/blind_sign_auth/anonymous_tokens/cpp/client/anonymous_tokens_rsa_bssa_client.h b/quiche/blind_sign_auth/anonymous_tokens/cpp/client/anonymous_tokens_rsa_bssa_client.h
index 0f2cd5c..e760182 100644
--- a/quiche/blind_sign_auth/anonymous_tokens/cpp/client/anonymous_tokens_rsa_bssa_client.h
+++ b/quiche/blind_sign_auth/anonymous_tokens/cpp/client/anonymous_tokens_rsa_bssa_client.h
@@ -77,12 +77,12 @@
absl::StatusOr<std::vector<RSABlindSignatureTokenWithInput>> ProcessResponse(
const AnonymousTokensSignResponse& response);
- // Method to verify whether a blind token is valid or not.
+ // Method to verify whether an anonymous token is valid or not.
//
// Returns OK on a valid token and non-OK otherwise.
- absl::Status Verify(
- const RSABlindSignatureToken& token, absl::string_view message,
- absl::optional<absl::string_view> public_metadata = absl::nullopt);
+ absl::Status Verify(const RSABlindSignaturePublicKey& public_key,
+ const RSABlindSignatureToken& token,
+ const PlaintextMessageWithPublicMetadata& input);
private:
struct BlindingInfo {
diff --git a/quiche/blind_sign_auth/anonymous_tokens/cpp/client/anonymous_tokens_rsa_bssa_client_test.cc b/quiche/blind_sign_auth/anonymous_tokens/cpp/client/anonymous_tokens_rsa_bssa_client_test.cc
index 84a297f..37d3a01 100644
--- a/quiche/blind_sign_auth/anonymous_tokens/cpp/client/anonymous_tokens_rsa_bssa_client_test.cc
+++ b/quiche/blind_sign_auth/anonymous_tokens/cpp/client/anonymous_tokens_rsa_bssa_client_test.cc
@@ -35,6 +35,7 @@
namespace anonymous_tokens {
namespace {
+using ::testing::SizeIs;
using quiche::test::StatusIs;
// Returns a fixed public private key pair by calling GetStrongRsaKeys4096().
@@ -159,9 +160,8 @@
class AnonymousTokensRsaBssaClientTest : public testing::Test {
protected:
void SetUp() override {
- ANON_TOKENS_ASSERT_OK_AND_ASSIGN(auto key_pair, CreateClientTestKey());
- public_key_ = std::move(key_pair.first);
- private_key_ = std::move(key_pair.second);
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::tie(public_key_, private_key_),
+ CreateClientTestKey());
ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
client_, AnonymousTokensRsaBssaClient::Create(public_key_));
}
@@ -179,8 +179,8 @@
client_->CreateRequest(input_messages));
ANON_TOKENS_ASSERT_OK_AND_ASSIGN(AnonymousTokensSignResponse response,
CreateResponse(request, private_key_));
+ EXPECT_THAT(response.anonymous_tokens(), SizeIs(1));
QUICHE_EXPECT_OK(client_->ProcessResponse(response));
- EXPECT_EQ(response.anonymous_tokens_size(), 1);
}
TEST_F(AnonymousTokensRsaBssaClientTest, SuccessMultipleMessages) {
@@ -191,7 +191,7 @@
client_->CreateRequest(input_messages));
ANON_TOKENS_ASSERT_OK_AND_ASSIGN(AnonymousTokensSignResponse response,
CreateResponse(request, private_key_));
- EXPECT_EQ(response.anonymous_tokens_size(), 4);
+ EXPECT_THAT(response.anonymous_tokens(), SizeIs(4));
QUICHE_EXPECT_OK(client_->ProcessResponse(response));
}
@@ -327,6 +327,144 @@
StatusIs(absl::StatusCode::kInvalidArgument));
}
+class AnonymousTokensRsaBssaClientWithPublicMetadataTest
+ : public testing::Test {
+ protected:
+ void SetUp() override {
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ std::tie(public_key_, private_key_),
+ CreateClientTestKey("TEST_USE_CASE", /*key_version=*/1,
+ AT_MESSAGE_MASK_CONCAT,
+ kRsaMessageMaskSizeInBytes32,
+ /*enable_public_metadata=*/true));
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ public_metadata_client_,
+ AnonymousTokensRsaBssaClient::Create(public_key_));
+ }
+
+ RSAPrivateKey private_key_;
+ RSABlindSignaturePublicKey public_key_;
+ std::unique_ptr<AnonymousTokensRsaBssaClient> public_metadata_client_;
+};
+
+TEST_F(AnonymousTokensRsaBssaClientWithPublicMetadataTest,
+ SuccessOneMessageWithPublicMetadata) {
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ std::vector<PlaintextMessageWithPublicMetadata> input_messages,
+ CreateInput({"message"}, {"md1"}));
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ AnonymousTokensSignRequest request,
+ public_metadata_client_->CreateRequest(input_messages));
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ AnonymousTokensSignResponse response,
+ CreateResponse(request, private_key_, /*enable_public_metadata=*/true));
+ EXPECT_THAT(response.anonymous_tokens(), SizeIs(1));
+ QUICHE_EXPECT_OK(public_metadata_client_->ProcessResponse(response));
+}
+
+TEST_F(AnonymousTokensRsaBssaClientWithPublicMetadataTest,
+ FailureWithEmptyPublicMetadata) {
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ std::vector<PlaintextMessageWithPublicMetadata> input_messages,
+ CreateInput({"message"}, {"md1"}));
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ AnonymousTokensSignRequest request,
+ public_metadata_client_->CreateRequest(input_messages));
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ AnonymousTokensSignResponse response,
+ CreateResponse(request, private_key_, /*enable_public_metadata=*/false));
+ EXPECT_THAT(public_metadata_client_->ProcessResponse(response),
+ StatusIs(absl::StatusCode::kInvalidArgument));
+}
+
+TEST_F(AnonymousTokensRsaBssaClientWithPublicMetadataTest,
+ FailureWithWrongPublicMetadata) {
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ std::vector<PlaintextMessageWithPublicMetadata> input_messages,
+ CreateInput({"message"}, {"md1"}));
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ AnonymousTokensSignRequest request,
+ public_metadata_client_->CreateRequest(input_messages));
+ request.mutable_blinded_tokens(0)->set_public_metadata(
+ "wrong_public_metadata");
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ AnonymousTokensSignResponse response,
+ CreateResponse(request, private_key_, /*enable_public_metadata=*/true));
+ EXPECT_THAT(public_metadata_client_->ProcessResponse(response),
+ StatusIs(absl::StatusCode::kInvalidArgument));
+}
+
+TEST_F(AnonymousTokensRsaBssaClientWithPublicMetadataTest,
+ FailureWithPublicMetadataSupportOff) {
+ // Create a client with public metadata support disabled.
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(auto key_pair, CreateClientTestKey());
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ std::unique_ptr<AnonymousTokensRsaBssaClient> non_public_metadata_client,
+ AnonymousTokensRsaBssaClient::Create(key_pair.first));
+
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ std::vector<PlaintextMessageWithPublicMetadata> input_messages,
+ CreateInput({"message"}, {"md1"}));
+ // Use client_ that does not support public metadata.
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ AnonymousTokensSignRequest request,
+ non_public_metadata_client->CreateRequest(input_messages));
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ AnonymousTokensSignResponse response,
+ CreateResponse(request, private_key_, /*enable_public_metadata=*/true));
+ EXPECT_THAT(non_public_metadata_client->ProcessResponse(response),
+ StatusIs(absl::StatusCode::kInvalidArgument));
+}
+
+TEST_F(AnonymousTokensRsaBssaClientWithPublicMetadataTest,
+ SuccessMultipleMessagesWithDistinctPublicMetadata) {
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ std::vector<PlaintextMessageWithPublicMetadata> input_messages,
+ CreateInput({"message1", "msg2", "anotherMessage", "one_more_message"},
+ {"md1", "md2", "md3", "md4"}));
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ AnonymousTokensSignRequest request,
+ public_metadata_client_->CreateRequest(input_messages));
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ AnonymousTokensSignResponse response,
+ CreateResponse(request, private_key_, /*enable_public_metadata=*/true));
+ EXPECT_THAT(response.anonymous_tokens(), SizeIs(4));
+ QUICHE_EXPECT_OK(public_metadata_client_->ProcessResponse(response));
+}
+
+TEST_F(AnonymousTokensRsaBssaClientWithPublicMetadataTest,
+ SuccessMultipleMessagesWithRepeatedPublicMetadata) {
+ // Create input with repeated public metadata
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ std::vector<PlaintextMessageWithPublicMetadata> input_messages,
+ CreateInput({"message1", "msg2", "anotherMessage", "one_more_message"},
+ {"md1", "md2", "md2", "md1"}));
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ AnonymousTokensSignRequest request,
+ public_metadata_client_->CreateRequest(input_messages));
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ AnonymousTokensSignResponse response,
+ CreateResponse(request, private_key_, /*enable_public_metadata=*/true));
+ EXPECT_THAT(response.anonymous_tokens(), SizeIs(4));
+ QUICHE_EXPECT_OK(public_metadata_client_->ProcessResponse(response));
+}
+
+TEST_F(AnonymousTokensRsaBssaClientWithPublicMetadataTest,
+ SuccessMultipleMessagesWithEmptyStringPublicMetadata) {
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ std::vector<PlaintextMessageWithPublicMetadata> input_messages,
+ CreateInput({"message1", "msg2", "anotherMessage", "one_more_message"},
+ {"md1", "", "", "md4"}));
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ AnonymousTokensSignRequest request,
+ public_metadata_client_->CreateRequest(input_messages));
+ ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
+ AnonymousTokensSignResponse response,
+ CreateResponse(request, private_key_, /*enable_public_metadata=*/true));
+ EXPECT_THAT(response.anonymous_tokens(), SizeIs(4));
+ QUICHE_EXPECT_OK(public_metadata_client_->ProcessResponse(response));
+}
+
} // namespace
} // namespace anonymous_tokens
} // namespace private_membership