• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "anonymous_tokens/cpp/crypto/rsa_blind_signer.h"
16 
17 #include <memory>
18 #include <random>
19 #include <string>
20 #include <utility>
21 
22 #include <gmock/gmock.h>
23 #include <gtest/gtest.h>
24 #include "absl/status/status.h"
25 #include "absl/status/statusor.h"
26 #include "absl/strings/string_view.h"
27 #include "anonymous_tokens/cpp/crypto/constants.h"
28 #include "anonymous_tokens/cpp/crypto/crypto_utils.h"
29 #include "anonymous_tokens/cpp/crypto/rsa_ssa_pss_verifier.h"
30 #include "anonymous_tokens/cpp/testing/proto_utils.h"
31 #include "anonymous_tokens/cpp/testing/utils.h"
32 #include "anonymous_tokens/proto/anonymous_tokens.pb.h"
33 #include <openssl/digest.h>
34 #include <openssl/rsa.h>
35 
36 
37 namespace anonymous_tokens {
38 namespace {
39 
40 using CreateTestKeyPairFunction =
41     absl::StatusOr<std::pair<RSAPublicKey, RSAPrivateKey>>();
42 
43 class RsaBlindSignerTest
44     : public ::testing::TestWithParam<CreateTestKeyPairFunction *> {
45  protected:
SetUp()46   void SetUp() override {
47     ANON_TOKENS_ASSERT_OK_AND_ASSIGN(auto keys_pair, (*GetParam())());
48     public_key_ = std::move(keys_pair.first);
49     private_key_ = std::move(keys_pair.second);
50     generator_.seed(0);
51     // NOTE: using recommended RsaSsaPssParams
52     sig_hash_ = EVP_sha384();
53     mgf1_hash_ = EVP_sha384();
54     salt_length_ = kSaltLengthInBytes48;
55   }
56 
57   RSAPrivateKey private_key_;
58   RSAPublicKey public_key_;
59   std::mt19937_64 generator_;
60   const EVP_MD *sig_hash_;   // Owned by BoringSSL.
61   const EVP_MD *mgf1_hash_;  // Owned by BoringSSL.
62   int salt_length_;
63   std::uniform_int_distribution<int> distr_u8_ =
64       std::uniform_int_distribution<int>{0, 255};
65 };
66 
67 // This test only tests whether the implemented signer 'signs' properly. The
68 // outline of method calls in this test should not be assumed a secure signature
69 // scheme (and used in other places) as the security has not been
70 // proven/analyzed.
71 //
72 // Test for the standard signer does not take public metadata as a parameter
73 // which means public metadata is set to std::nullopt.
TEST_P(RsaBlindSignerTest,StandardSignerWorks)74 TEST_P(RsaBlindSignerTest, StandardSignerWorks) {
75   absl::string_view message = "Hello World!";
76   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
77       std::string encoded_message,
78       EncodeMessageForTests(message, public_key_, sig_hash_, mgf1_hash_,
79                             salt_length_));
80   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
81       std::unique_ptr<RsaBlindSigner> signer,
82       RsaBlindSigner::New(private_key_, /*use_rsa_public_exponent=*/true));
83   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string potentially_insecure_signature,
84                                    signer->Sign(encoded_message));
85   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
86       const auto verifier,
87       RsaSsaPssVerifier::New(salt_length_, sig_hash_, mgf1_hash_, public_key_,
88                              /*use_rsa_public_exponent=*/true));
89   EXPECT_TRUE(verifier->Verify(potentially_insecure_signature, message).ok());
90 }
91 
TEST_P(RsaBlindSignerTest,SignerFails)92 TEST_P(RsaBlindSignerTest, SignerFails) {
93   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
94       std::unique_ptr<RsaBlindSigner> signer,
95       RsaBlindSigner::New(private_key_, /*use_rsa_public_exponent=*/true));
96   absl::string_view message = "Hello World!";
97 
98   absl::StatusOr<std::string> signature = signer->Sign(message);
99   EXPECT_EQ(signature.status().code(), absl::StatusCode::kInternal);
100   EXPECT_THAT(signature.status().message(),
101               ::testing::HasSubstr("Expected blind data size"));
102 
103   int sig_size = public_key_.n().size();
104   std::string message2 = RandomString(sig_size, &distr_u8_, &generator_);
105   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string insecure_sig,
106                                    signer->Sign(message2));
107   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
108       const auto verifier,
109       RsaSsaPssVerifier::New(salt_length_, sig_hash_, mgf1_hash_, public_key_,
110                              /*use_rsa_public_exponent=*/true));
111   absl::Status verification_result = verifier->Verify(insecure_sig, message2);
112   EXPECT_EQ(verification_result.code(), absl::StatusCode::kInvalidArgument);
113   EXPECT_THAT(verification_result.message(),
114               ::testing::HasSubstr("verification failed"));
115 }
116 
117 INSTANTIATE_TEST_SUITE_P(RsaBlindSignerTest, RsaBlindSignerTest,
118                          ::testing::Values(&GetStrongRsaKeys2048,
119                                            &GetAnotherStrongRsaKeys2048,
120                                            &GetStrongRsaKeys3072,
121                                            &GetStrongRsaKeys4096));
122 
123 using RsaBlindSignerPublicMetadataTestParams =
124     std::tuple<absl::StatusOr<std::pair<RSAPublicKey, RSAPrivateKey>>,
125                /*use_rsa_public_exponent*/ bool>;
126 
127 class RsaBlindSignerTestWithPublicMetadata
128     : public ::testing::TestWithParam<RsaBlindSignerPublicMetadataTestParams> {
129  protected:
SetUp()130   void SetUp() override {
131     ANON_TOKENS_ASSERT_OK_AND_ASSIGN(auto keys_pair, std::get<0>(GetParam()));
132     use_rsa_public_exponent_ = std::get<1>(GetParam());
133     public_key_ = std::move(keys_pair.first);
134     private_key_ = std::move(keys_pair.second);
135     // NOTE: using recommended RsaSsaPssParams
136     sig_hash_ = EVP_sha384();
137     mgf1_hash_ = EVP_sha384();
138     salt_length_ = kSaltLengthInBytes48;
139   }
140 
141   RSAPrivateKey private_key_;
142   RSAPublicKey public_key_;
143   const EVP_MD *sig_hash_;   // Owned by BoringSSL.
144   const EVP_MD *mgf1_hash_;  // Owned by BoringSSL.
145   int salt_length_;
146   bool use_rsa_public_exponent_;
147 };
148 
149 // This test only tests whether the implemented signer 'signs' properly under
150 // some public metadata. The outline of method calls in this test should not
151 // be assumed a secure signature scheme (and used in other places) as the
152 // security has not been proven/analyzed.
TEST_P(RsaBlindSignerTestWithPublicMetadata,SignerWorksWithPublicMetadata)153 TEST_P(RsaBlindSignerTestWithPublicMetadata, SignerWorksWithPublicMetadata) {
154   absl::string_view message = "Hello World!";
155   absl::string_view public_metadata = "pubmd!";
156   std::string augmented_message =
157       EncodeMessagePublicMetadata(message, public_metadata);
158   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
159       std::string encoded_message,
160       EncodeMessageForTests(augmented_message, public_key_, sig_hash_,
161                             mgf1_hash_, salt_length_));
162   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
163       std::unique_ptr<RsaBlindSigner> signer,
164       RsaBlindSigner::New(private_key_, use_rsa_public_exponent_,
165                           public_metadata));
166   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string potentially_insecure_signature,
167                                    signer->Sign(encoded_message));
168   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
169       auto verifier,
170       RsaSsaPssVerifier::New(salt_length_, sig_hash_, mgf1_hash_, public_key_,
171                              use_rsa_public_exponent_, public_metadata));
172   EXPECT_TRUE(verifier->Verify(potentially_insecure_signature, message).ok());
173 }
174 
TEST_P(RsaBlindSignerTestWithPublicMetadata,SignerWorksWithEmptyPublicMetadata)175 TEST_P(RsaBlindSignerTestWithPublicMetadata,
176        SignerWorksWithEmptyPublicMetadata) {
177   absl::string_view message = "Hello World!";
178   absl::string_view empty_public_metadata = "";
179   std::string augmented_message =
180       EncodeMessagePublicMetadata(message, empty_public_metadata);
181   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
182       std::string encoded_message,
183       EncodeMessageForTests(augmented_message, public_key_, sig_hash_,
184                             mgf1_hash_, salt_length_));
185   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
186       std::unique_ptr<RsaBlindSigner> signer,
187       RsaBlindSigner::New(private_key_, use_rsa_public_exponent_,
188                           empty_public_metadata));
189   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string potentially_insecure_signature,
190                                    signer->Sign(encoded_message));
191   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
192       auto verifier,
193       RsaSsaPssVerifier::New(salt_length_, sig_hash_, mgf1_hash_, public_key_,
194                              use_rsa_public_exponent_, empty_public_metadata));
195   EXPECT_TRUE(verifier->Verify(potentially_insecure_signature, message).ok());
196 }
197 
TEST_P(RsaBlindSignerTestWithPublicMetadata,SignatureFailstoVerifyWithWrongPublicMetadata)198 TEST_P(RsaBlindSignerTestWithPublicMetadata,
199        SignatureFailstoVerifyWithWrongPublicMetadata) {
200   absl::string_view message = "Hello World!";
201   absl::string_view public_metadata = "pubmd!";
202   absl::string_view public_metadata_2 = "pubmd2";
203   std::string augmented_message =
204       EncodeMessagePublicMetadata(message, public_metadata);
205   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
206       std::string encoded_message,
207       EncodeMessageForTests(augmented_message, public_key_, sig_hash_,
208                             mgf1_hash_, salt_length_));
209   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
210       std::unique_ptr<RsaBlindSigner> signer,
211       RsaBlindSigner::New(private_key_, use_rsa_public_exponent_,
212                           public_metadata));
213   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string potentially_insecure_signature,
214                                    signer->Sign(encoded_message));
215   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
216       auto verifier,
217       RsaSsaPssVerifier::New(salt_length_, sig_hash_, mgf1_hash_, public_key_,
218                              use_rsa_public_exponent_, public_metadata_2));
219   absl::Status verification_result =
220       verifier->Verify(potentially_insecure_signature, message);
221   EXPECT_EQ(verification_result.code(), absl::StatusCode::kInvalidArgument);
222   EXPECT_THAT(verification_result.message(),
223               ::testing::HasSubstr("verification failed"));
224 }
225 
TEST_P(RsaBlindSignerTestWithPublicMetadata,SignatureFailsToVerifyWithNoPublicMetadata)226 TEST_P(RsaBlindSignerTestWithPublicMetadata,
227        SignatureFailsToVerifyWithNoPublicMetadata) {
228   absl::string_view message = "Hello World!";
229   absl::string_view public_metadata = "pubmd!";
230   absl::string_view public_metadata_2 = "";
231   std::string augmented_message =
232       EncodeMessagePublicMetadata(message, public_metadata);
233   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
234       std::string encoded_message,
235       EncodeMessageForTests(augmented_message, public_key_, sig_hash_,
236                             mgf1_hash_, salt_length_));
237   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
238       std::unique_ptr<RsaBlindSigner> signer,
239       RsaBlindSigner::New(private_key_, use_rsa_public_exponent_,
240                           public_metadata));
241   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string potentially_insecure_signature,
242                                    signer->Sign(encoded_message));
243   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
244       auto verifier,
245       RsaSsaPssVerifier::New(salt_length_, sig_hash_, mgf1_hash_, public_key_,
246                              use_rsa_public_exponent_, public_metadata_2));
247   absl::Status verification_result =
248       verifier->Verify(potentially_insecure_signature, message);
249   EXPECT_EQ(verification_result.code(), absl::StatusCode::kInvalidArgument);
250   EXPECT_THAT(verification_result.message(),
251               ::testing::HasSubstr("verification failed"));
252 }
253 
254 INSTANTIATE_TEST_SUITE_P(
255     RsaBlindSignerTestWithPublicMetadata, RsaBlindSignerTestWithPublicMetadata,
256     ::testing::Combine(
257         ::testing::Values(GetStrongRsaKeys2048(), GetAnotherStrongRsaKeys2048(),
258                           GetStrongRsaKeys3072(), GetStrongRsaKeys4096()),
259         /*use_rsa_public_exponent*/ ::testing::Values(true, false)));
260 
TEST(IetfRsaBlindSignerTest,IetfRsaBlindSignaturesWithPublicMetadataTestVectorsSuccess)261 TEST(IetfRsaBlindSignerTest,
262      IetfRsaBlindSignaturesWithPublicMetadataTestVectorsSuccess) {
263   auto test_vectors = GetIetfRsaBlindSignatureWithPublicMetadataTestVectors();
264   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
265       const auto test_key,
266       GetIetfRsaBlindSignatureWithPublicMetadataTestKeys());
267   for (const auto &test_vector : test_vectors) {
268     ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
269         std::unique_ptr<RsaBlindSigner> signer,
270         RsaBlindSigner::New(test_key.second, /*use_rsa_public_exponent=*/true,
271                             test_vector.public_metadata));
272     ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string blind_signature,
273                                      signer->Sign(test_vector.blinded_message));
274     EXPECT_EQ(blind_signature, test_vector.blinded_signature);
275   }
276 }
277 
TEST(IetfRsaBlindSignerTest,IetfPartiallyBlindRsaSignaturesNoPublicExponentTestVectorsSuccess)278 TEST(IetfRsaBlindSignerTest,
279      IetfPartiallyBlindRsaSignaturesNoPublicExponentTestVectorsSuccess) {
280   auto test_vectors =
281       GetIetfPartiallyBlindRSASignatureNoPublicExponentTestVectors();
282   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
283       const auto test_key,
284       GetIetfRsaBlindSignatureWithPublicMetadataTestKeys());
285   for (const auto &test_vector : test_vectors) {
286     ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
287         std::unique_ptr<RsaBlindSigner> signer,
288         RsaBlindSigner::New(test_key.second, /*use_rsa_public_exponent=*/false,
289                             test_vector.public_metadata));
290     ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string blind_signature,
291                                      signer->Sign(test_vector.blinded_message));
292     EXPECT_EQ(blind_signature, test_vector.blinded_signature);
293   }
294 }
295 
296 }  // namespace
297 }  // namespace anonymous_tokens
298 
299