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 namespace anonymous_tokens {
37 namespace {
38 
39 using CreateTestKeyPairFunction =
40     absl::StatusOr<std::pair<RSAPublicKey, RSAPrivateKey>>();
41 
42 class RsaBlindSignerTest
43     : public ::testing::TestWithParam<CreateTestKeyPairFunction *> {
44  protected:
SetUp()45   void SetUp() override {
46     ANON_TOKENS_ASSERT_OK_AND_ASSIGN(auto keys_pair, (*GetParam())());
47     public_key_ = std::move(keys_pair.first);
48     private_key_ = std::move(keys_pair.second);
49     generator_.seed(0);
50     // NOTE: using recommended RsaSsaPssParams
51     sig_hash_ = EVP_sha384();
52     mgf1_hash_ = EVP_sha384();
53     salt_length_ = kSaltLengthInBytes48;
54   }
55 
56   RSAPrivateKey private_key_;
57   RSAPublicKey public_key_;
58   std::mt19937_64 generator_;
59   const EVP_MD *sig_hash_;   // Owned by BoringSSL.
60   const EVP_MD *mgf1_hash_;  // Owned by BoringSSL.
61   int salt_length_;
62   std::uniform_int_distribution<int> distr_u8_ =
63       std::uniform_int_distribution<int>{0, 255};
64 };
65 
66 // This test only tests whether the implemented signer 'signs' properly. The
67 // outline of method calls in this test should not be assumed a secure signature
68 // scheme (and used in other places) as the security has not been
69 // proven/analyzed.
70 //
71 // Test for the standard signer does not take public metadata as a parameter
72 // which means public metadata is set to std::nullopt.
TEST_P(RsaBlindSignerTest,StandardSignerWorks)73 TEST_P(RsaBlindSignerTest, StandardSignerWorks) {
74   absl::string_view message = "Hello World!";
75   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
76       std::string encoded_message,
77       EncodeMessageForTests(message, public_key_, sig_hash_, mgf1_hash_,
78                             salt_length_));
79   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
80       std::unique_ptr<RsaBlindSigner> signer,
81       RsaBlindSigner::New(private_key_, /*use_rsa_public_exponent=*/true));
82   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string potentially_insecure_signature,
83                                    signer->Sign(encoded_message));
84   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
85       const auto verifier,
86       RsaSsaPssVerifier::New(salt_length_, sig_hash_, mgf1_hash_, public_key_,
87                              /*use_rsa_public_exponent=*/true));
88   EXPECT_TRUE(verifier->Verify(potentially_insecure_signature, message).ok());
89 }
90 
TEST_P(RsaBlindSignerTest,SignerFails)91 TEST_P(RsaBlindSignerTest, SignerFails) {
92   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
93       std::unique_ptr<RsaBlindSigner> signer,
94       RsaBlindSigner::New(private_key_, /*use_rsa_public_exponent=*/true));
95   absl::string_view message = "Hello World!";
96 
97   absl::StatusOr<std::string> signature = signer->Sign(message);
98   EXPECT_EQ(signature.status().code(), absl::StatusCode::kInternal);
99   EXPECT_THAT(signature.status().message(),
100               ::testing::HasSubstr("Expected blind data size"));
101 
102   int sig_size = public_key_.n().size();
103   std::string message2 = RandomString(sig_size, &distr_u8_, &generator_);
104   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string insecure_sig,
105                                    signer->Sign(message2));
106   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
107       const auto verifier,
108       RsaSsaPssVerifier::New(salt_length_, sig_hash_, mgf1_hash_, public_key_,
109                              /*use_rsa_public_exponent=*/true));
110   absl::Status verification_result = verifier->Verify(insecure_sig, message2);
111   EXPECT_EQ(verification_result.code(), absl::StatusCode::kInvalidArgument);
112   EXPECT_THAT(verification_result.message(),
113               ::testing::HasSubstr("verification failed"));
114 }
115 
116 INSTANTIATE_TEST_SUITE_P(RsaBlindSignerTest, RsaBlindSignerTest,
117                          ::testing::Values(&GetStrongRsaKeys2048,
118                                            &GetAnotherStrongRsaKeys2048,
119                                            &GetStrongRsaKeys3072,
120                                            &GetStrongRsaKeys4096));
121 
122 using RsaBlindSignerPublicMetadataTestParams =
123     std::tuple<absl::StatusOr<std::pair<RSAPublicKey, RSAPrivateKey>>,
124                /*use_rsa_public_exponent*/ bool>;
125 
126 class RsaBlindSignerTestWithPublicMetadata
127     : public ::testing::TestWithParam<RsaBlindSignerPublicMetadataTestParams> {
128  protected:
SetUp()129   void SetUp() override {
130     ANON_TOKENS_ASSERT_OK_AND_ASSIGN(auto keys_pair, std::get<0>(GetParam()));
131     use_rsa_public_exponent_ = std::get<1>(GetParam());
132     public_key_ = std::move(keys_pair.first);
133     private_key_ = std::move(keys_pair.second);
134     // NOTE: using recommended RsaSsaPssParams
135     sig_hash_ = EVP_sha384();
136     mgf1_hash_ = EVP_sha384();
137     salt_length_ = kSaltLengthInBytes48;
138   }
139 
140   RSAPrivateKey private_key_;
141   RSAPublicKey public_key_;
142   const EVP_MD *sig_hash_;   // Owned by BoringSSL.
143   const EVP_MD *mgf1_hash_;  // Owned by BoringSSL.
144   int salt_length_;
145   bool use_rsa_public_exponent_;
146 };
147 
148 // This test only tests whether the implemented signer 'signs' properly under
149 // some public metadata. The outline of method calls in this test should not
150 // be assumed a secure signature scheme (and used in other places) as the
151 // security has not been proven/analyzed.
TEST_P(RsaBlindSignerTestWithPublicMetadata,SignerWorksWithPublicMetadata)152 TEST_P(RsaBlindSignerTestWithPublicMetadata, SignerWorksWithPublicMetadata) {
153   absl::string_view message = "Hello World!";
154   absl::string_view public_metadata = "pubmd!";
155   std::string augmented_message =
156       EncodeMessagePublicMetadata(message, public_metadata);
157   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
158       std::string encoded_message,
159       EncodeMessageForTests(augmented_message, public_key_, sig_hash_,
160                             mgf1_hash_, salt_length_));
161   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
162       std::unique_ptr<RsaBlindSigner> signer,
163       RsaBlindSigner::New(private_key_, use_rsa_public_exponent_,
164                           public_metadata));
165   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string potentially_insecure_signature,
166                                    signer->Sign(encoded_message));
167   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
168       auto verifier,
169       RsaSsaPssVerifier::New(salt_length_, sig_hash_, mgf1_hash_, public_key_,
170                              use_rsa_public_exponent_, public_metadata));
171   EXPECT_TRUE(verifier->Verify(potentially_insecure_signature, message).ok());
172 }
173 
TEST_P(RsaBlindSignerTestWithPublicMetadata,SignerWorksWithEmptyPublicMetadata)174 TEST_P(RsaBlindSignerTestWithPublicMetadata,
175        SignerWorksWithEmptyPublicMetadata) {
176   absl::string_view message = "Hello World!";
177   absl::string_view empty_public_metadata = "";
178   std::string augmented_message =
179       EncodeMessagePublicMetadata(message, empty_public_metadata);
180   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
181       std::string encoded_message,
182       EncodeMessageForTests(augmented_message, public_key_, sig_hash_,
183                             mgf1_hash_, salt_length_));
184   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
185       std::unique_ptr<RsaBlindSigner> signer,
186       RsaBlindSigner::New(private_key_, use_rsa_public_exponent_,
187                           empty_public_metadata));
188   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string potentially_insecure_signature,
189                                    signer->Sign(encoded_message));
190   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
191       auto verifier,
192       RsaSsaPssVerifier::New(salt_length_, sig_hash_, mgf1_hash_, public_key_,
193                              use_rsa_public_exponent_, empty_public_metadata));
194   EXPECT_TRUE(verifier->Verify(potentially_insecure_signature, message).ok());
195 }
196 
TEST_P(RsaBlindSignerTestWithPublicMetadata,SignatureFailstoVerifyWithWrongPublicMetadata)197 TEST_P(RsaBlindSignerTestWithPublicMetadata,
198        SignatureFailstoVerifyWithWrongPublicMetadata) {
199   absl::string_view message = "Hello World!";
200   absl::string_view public_metadata = "pubmd!";
201   absl::string_view public_metadata_2 = "pubmd2";
202   std::string augmented_message =
203       EncodeMessagePublicMetadata(message, public_metadata);
204   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
205       std::string encoded_message,
206       EncodeMessageForTests(augmented_message, public_key_, sig_hash_,
207                             mgf1_hash_, salt_length_));
208   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
209       std::unique_ptr<RsaBlindSigner> signer,
210       RsaBlindSigner::New(private_key_, use_rsa_public_exponent_,
211                           public_metadata));
212   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string potentially_insecure_signature,
213                                    signer->Sign(encoded_message));
214   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
215       auto verifier,
216       RsaSsaPssVerifier::New(salt_length_, sig_hash_, mgf1_hash_, public_key_,
217                              use_rsa_public_exponent_, public_metadata_2));
218   absl::Status verification_result =
219       verifier->Verify(potentially_insecure_signature, message);
220   EXPECT_EQ(verification_result.code(), absl::StatusCode::kInvalidArgument);
221   EXPECT_THAT(verification_result.message(),
222               ::testing::HasSubstr("verification failed"));
223 }
224 
TEST_P(RsaBlindSignerTestWithPublicMetadata,SignatureFailsToVerifyWithNoPublicMetadata)225 TEST_P(RsaBlindSignerTestWithPublicMetadata,
226        SignatureFailsToVerifyWithNoPublicMetadata) {
227   absl::string_view message = "Hello World!";
228   absl::string_view public_metadata = "pubmd!";
229   absl::string_view public_metadata_2 = "";
230   std::string augmented_message =
231       EncodeMessagePublicMetadata(message, public_metadata);
232   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
233       std::string encoded_message,
234       EncodeMessageForTests(augmented_message, public_key_, sig_hash_,
235                             mgf1_hash_, salt_length_));
236   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
237       std::unique_ptr<RsaBlindSigner> signer,
238       RsaBlindSigner::New(private_key_, use_rsa_public_exponent_,
239                           public_metadata));
240   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string potentially_insecure_signature,
241                                    signer->Sign(encoded_message));
242   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
243       auto verifier,
244       RsaSsaPssVerifier::New(salt_length_, sig_hash_, mgf1_hash_, public_key_,
245                              use_rsa_public_exponent_, public_metadata_2));
246   absl::Status verification_result =
247       verifier->Verify(potentially_insecure_signature, message);
248   EXPECT_EQ(verification_result.code(), absl::StatusCode::kInvalidArgument);
249   EXPECT_THAT(verification_result.message(),
250               ::testing::HasSubstr("verification failed"));
251 }
252 
253 INSTANTIATE_TEST_SUITE_P(
254     RsaBlindSignerTestWithPublicMetadata, RsaBlindSignerTestWithPublicMetadata,
255     ::testing::Combine(
256         ::testing::Values(GetStrongRsaKeys2048(), GetAnotherStrongRsaKeys2048(),
257                           GetStrongRsaKeys3072(), GetStrongRsaKeys4096()),
258         /*use_rsa_public_exponent*/ ::testing::Values(true, false)));
259 
TEST(IetfRsaBlindSignerTest,IetfRsaBlindSignaturesWithPublicMetadataTestVectorsSuccess)260 TEST(IetfRsaBlindSignerTest,
261      IetfRsaBlindSignaturesWithPublicMetadataTestVectorsSuccess) {
262   auto test_vectors = GetIetfRsaBlindSignatureWithPublicMetadataTestVectors();
263   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
264       const auto test_key,
265       GetIetfRsaBlindSignatureWithPublicMetadataTestKeys());
266   for (const auto &test_vector : test_vectors) {
267     ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
268         std::unique_ptr<RsaBlindSigner> signer,
269         RsaBlindSigner::New(test_key.second, /*use_rsa_public_exponent=*/true,
270                             test_vector.public_metadata));
271     ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string blind_signature,
272                                      signer->Sign(test_vector.blinded_message));
273     EXPECT_EQ(blind_signature, test_vector.blinded_signature);
274   }
275 }
276 
TEST(IetfRsaBlindSignerTest,IetfPartiallyBlindRsaSignaturesNoPublicExponentTestVectorsSuccess)277 TEST(IetfRsaBlindSignerTest,
278      IetfPartiallyBlindRsaSignaturesNoPublicExponentTestVectorsSuccess) {
279   auto test_vectors =
280       GetIetfPartiallyBlindRSASignatureNoPublicExponentTestVectors();
281   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
282       const auto test_key,
283       GetIetfRsaBlindSignatureWithPublicMetadataTestKeys());
284   for (const auto &test_vector : test_vectors) {
285     ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
286         std::unique_ptr<RsaBlindSigner> signer,
287         RsaBlindSigner::New(test_key.second, /*use_rsa_public_exponent=*/false,
288                             test_vector.public_metadata));
289     ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string blind_signature,
290                                      signer->Sign(test_vector.blinded_message));
291     EXPECT_EQ(blind_signature, test_vector.blinded_signature);
292   }
293 }
294 
295 }  // namespace
296 }  // namespace anonymous_tokens
297