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