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