xref: /aosp_15_r20/external/tink/cc/signature/ed25519_proto_serialization_test.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
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 //      http://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 ////////////////////////////////////////////////////////////////////////////////
16 
17 #include "tink/signature/ed25519_proto_serialization.h"
18 
19 #include <memory>
20 #include <string>
21 
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "absl/status/status.h"
25 #include "absl/types/optional.h"
26 #include "tink/insecure_secret_key_access.h"
27 #include "tink/internal/ec_util.h"
28 #include "tink/internal/mutable_serialization_registry.h"
29 #include "tink/internal/proto_key_serialization.h"
30 #include "tink/internal/proto_parameters_serialization.h"
31 #include "tink/internal/serialization.h"
32 #include "tink/key.h"
33 #include "tink/parameters.h"
34 #include "tink/partial_key_access.h"
35 #include "tink/restricted_data.h"
36 #include "tink/signature/ed25519_parameters.h"
37 #include "tink/signature/ed25519_private_key.h"
38 #include "tink/signature/ed25519_public_key.h"
39 #include "tink/subtle/random.h"
40 #include "tink/util/statusor.h"
41 #include "tink/util/test_matchers.h"
42 #include "proto/ed25519.pb.h"
43 #include "proto/tink.pb.h"
44 
45 namespace crypto {
46 namespace tink {
47 namespace {
48 
49 using ::crypto::tink::subtle::Random;
50 using ::crypto::tink::test::IsOk;
51 using ::crypto::tink::test::StatusIs;
52 using ::google::crypto::tink::Ed25519KeyFormat;
53 using ::google::crypto::tink::KeyData;
54 using ::google::crypto::tink::OutputPrefixType;
55 using ::testing::Eq;
56 using ::testing::IsTrue;
57 using ::testing::NotNull;
58 using ::testing::TestWithParam;
59 using ::testing::Values;
60 
61 struct TestCase {
62   Ed25519Parameters::Variant variant;
63   OutputPrefixType output_prefix_type;
64   absl::optional<int> id;
65   std::string output_prefix;
66 };
67 
68 class Ed25519ProtoSerializationTest : public TestWithParam<TestCase> {
69  protected:
SetUp()70   void SetUp() override {
71     internal::MutableSerializationRegistry::GlobalInstance().Reset();
72   }
73 };
74 
75 INSTANTIATE_TEST_SUITE_P(
76     Ed25519ProtoSerializationTestSuite, Ed25519ProtoSerializationTest,
77     Values(TestCase{Ed25519Parameters::Variant::kTink, OutputPrefixType::TINK,
78                     /*id=*/0x02030400,
79                     /*output_prefix=*/std::string("\x01\x02\x03\x04\x00", 5)},
80            TestCase{Ed25519Parameters::Variant::kCrunchy,
81                     OutputPrefixType::CRUNCHY, /*id=*/0x01030005,
82                     /*output_prefix=*/std::string("\x00\x01\x03\x00\x05", 5)},
83            TestCase{Ed25519Parameters::Variant::kLegacy,
84                     OutputPrefixType::LEGACY, /*id=*/0x07080910,
85                     /*output_prefix=*/std::string("\x00\x07\x08\x09\x10", 5)},
86            TestCase{Ed25519Parameters::Variant::kNoPrefix,
87                     OutputPrefixType::RAW, /*id=*/absl::nullopt,
88                     /*output_prefix=*/""}));
89 
TEST_P(Ed25519ProtoSerializationTest,ParseParameters)90 TEST_P(Ed25519ProtoSerializationTest, ParseParameters) {
91   TestCase test_case = GetParam();
92   ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk());
93 
94   Ed25519KeyFormat key_format_proto;
95   key_format_proto.set_version(0);
96 
97   util::StatusOr<internal::ProtoParametersSerialization> serialization =
98       internal::ProtoParametersSerialization::Create(
99           "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey",
100           test_case.output_prefix_type, key_format_proto.SerializeAsString());
101   ASSERT_THAT(serialization, IsOk());
102 
103   util::StatusOr<std::unique_ptr<Parameters>> params =
104       internal::MutableSerializationRegistry::GlobalInstance().ParseParameters(
105           *serialization);
106   ASSERT_THAT(params, IsOk());
107   EXPECT_THAT((*params)->HasIdRequirement(), test_case.id.has_value());
108 
109   const Ed25519Parameters* ed25519_params =
110       dynamic_cast<const Ed25519Parameters*>(params->get());
111   ASSERT_THAT(ed25519_params, NotNull());
112   EXPECT_THAT(ed25519_params->GetVariant(), Eq(test_case.variant));
113 }
114 
TEST_F(Ed25519ProtoSerializationTest,ParseParametersWithInvalidSerialization)115 TEST_F(Ed25519ProtoSerializationTest, ParseParametersWithInvalidSerialization) {
116   ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk());
117 
118   util::StatusOr<internal::ProtoParametersSerialization> serialization =
119       internal::ProtoParametersSerialization::Create(
120           "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey",
121           OutputPrefixType::RAW, "invalid_serialization");
122   ASSERT_THAT(serialization, IsOk());
123 
124   util::StatusOr<std::unique_ptr<Parameters>> params =
125       internal::MutableSerializationRegistry::GlobalInstance().ParseParameters(
126           *serialization);
127   EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument));
128 }
129 
TEST_F(Ed25519ProtoSerializationTest,ParseParametersWithUnkownOutputPrefix)130 TEST_F(Ed25519ProtoSerializationTest, ParseParametersWithUnkownOutputPrefix) {
131   ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk());
132 
133   Ed25519KeyFormat key_format_proto;
134   key_format_proto.set_version(0);
135 
136   util::StatusOr<internal::ProtoParametersSerialization> serialization =
137       internal::ProtoParametersSerialization::Create(
138           "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey",
139           OutputPrefixType::UNKNOWN_PREFIX,
140           key_format_proto.SerializeAsString());
141   ASSERT_THAT(serialization, IsOk());
142 
143   util::StatusOr<std::unique_ptr<Parameters>> params =
144       internal::MutableSerializationRegistry::GlobalInstance().ParseParameters(
145           *serialization);
146   EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument));
147 }
148 
TEST_F(Ed25519ProtoSerializationTest,ParseParametersWithInvalidVersion)149 TEST_F(Ed25519ProtoSerializationTest, ParseParametersWithInvalidVersion) {
150   ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk());
151 
152   Ed25519KeyFormat key_format_proto;
153   key_format_proto.set_version(1);
154 
155   util::StatusOr<internal::ProtoParametersSerialization> serialization =
156       internal::ProtoParametersSerialization::Create(
157           "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey",
158           OutputPrefixType::RAW, key_format_proto.SerializeAsString());
159   ASSERT_THAT(serialization, IsOk());
160 
161   util::StatusOr<std::unique_ptr<Parameters>> params =
162       internal::MutableSerializationRegistry::GlobalInstance().ParseParameters(
163           *serialization);
164   EXPECT_THAT(params.status(), StatusIs(absl::StatusCode::kInvalidArgument));
165 }
166 
TEST_P(Ed25519ProtoSerializationTest,SerializeParameters)167 TEST_P(Ed25519ProtoSerializationTest, SerializeParameters) {
168   TestCase test_case = GetParam();
169   ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk());
170 
171   util::StatusOr<Ed25519Parameters> parameters =
172       Ed25519Parameters::Create(test_case.variant);
173   ASSERT_THAT(parameters, IsOk());
174 
175   util::StatusOr<std::unique_ptr<Serialization>> serialization =
176       internal::MutableSerializationRegistry::GlobalInstance()
177           .SerializeParameters<internal::ProtoParametersSerialization>(
178               *parameters);
179   ASSERT_THAT(serialization, IsOk());
180   EXPECT_THAT((*serialization)->ObjectIdentifier(),
181               Eq("type.googleapis.com/google.crypto.tink.Ed25519PrivateKey"));
182 
183   const internal::ProtoParametersSerialization* proto_serialization =
184       dynamic_cast<const internal::ProtoParametersSerialization*>(
185           serialization->get());
186   ASSERT_THAT(proto_serialization, NotNull());
187   EXPECT_THAT(proto_serialization->GetKeyTemplate().type_url(),
188               Eq("type.googleapis.com/google.crypto.tink.Ed25519PrivateKey"));
189   EXPECT_THAT(proto_serialization->GetKeyTemplate().output_prefix_type(),
190               Eq(test_case.output_prefix_type));
191 
192   Ed25519KeyFormat key_format;
193   ASSERT_THAT(
194       key_format.ParseFromString(proto_serialization->GetKeyTemplate().value()),
195       IsTrue());
196   EXPECT_THAT(key_format.version(), Eq(0));
197 }
198 
TEST_P(Ed25519ProtoSerializationTest,ParsePublicKey)199 TEST_P(Ed25519ProtoSerializationTest, ParsePublicKey) {
200   TestCase test_case = GetParam();
201   ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk());
202 
203   std::string raw_key_bytes = Random::GetRandomBytes(32);
204   google::crypto::tink::Ed25519PublicKey key_proto;
205   key_proto.set_version(0);
206   key_proto.set_key_value(raw_key_bytes);
207   RestrictedData serialized_key = RestrictedData(
208       key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get());
209 
210   util::StatusOr<internal::ProtoKeySerialization> serialization =
211       internal::ProtoKeySerialization::Create(
212           "type.googleapis.com/google.crypto.tink.Ed25519PublicKey",
213           serialized_key, KeyData::ASYMMETRIC_PUBLIC,
214           test_case.output_prefix_type, test_case.id);
215   ASSERT_THAT(serialization, IsOk());
216 
217   util::StatusOr<std::unique_ptr<Key>> key =
218       internal::MutableSerializationRegistry::GlobalInstance().ParseKey(
219           *serialization, /*token=*/absl::nullopt);
220   ASSERT_THAT(key, IsOk());
221   EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id));
222   EXPECT_THAT((*key)->GetParameters().HasIdRequirement(),
223               test_case.id.has_value());
224 
225   util::StatusOr<Ed25519Parameters> expected_parameters =
226       Ed25519Parameters::Create(test_case.variant);
227   ASSERT_THAT(expected_parameters, IsOk());
228 
229   util::StatusOr<Ed25519PublicKey> expected_key = Ed25519PublicKey::Create(
230       *expected_parameters, raw_key_bytes, test_case.id, GetPartialKeyAccess());
231   ASSERT_THAT(expected_key, IsOk());
232 
233   EXPECT_THAT(**key, Eq(*expected_key));
234 }
235 
TEST_F(Ed25519ProtoSerializationTest,ParsePublicKeyWithInvalidSerialization)236 TEST_F(Ed25519ProtoSerializationTest, ParsePublicKeyWithInvalidSerialization) {
237   ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk());
238 
239   RestrictedData serialized_key =
240       RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get());
241 
242   util::StatusOr<internal::ProtoKeySerialization> serialization =
243       internal::ProtoKeySerialization::Create(
244           "type.googleapis.com/google.crypto.tink.Ed25519PublicKey",
245           serialized_key, KeyData::ASYMMETRIC_PUBLIC, OutputPrefixType::TINK,
246           /*id_requirement=*/0x23456789);
247   ASSERT_THAT(serialization, IsOk());
248 
249   util::StatusOr<std::unique_ptr<Key>> key =
250       internal::MutableSerializationRegistry::GlobalInstance().ParseKey(
251           *serialization, InsecureSecretKeyAccess::Get());
252   EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument));
253 }
254 
TEST_F(Ed25519ProtoSerializationTest,ParsePublicKeyWithInvalidVersion)255 TEST_F(Ed25519ProtoSerializationTest, ParsePublicKeyWithInvalidVersion) {
256   ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk());
257 
258   std::string raw_key_bytes = Random::GetRandomBytes(32);
259   google::crypto::tink::Ed25519PublicKey key_proto;
260   key_proto.set_version(1);  // Invalid version number.
261   key_proto.set_key_value(raw_key_bytes);
262   RestrictedData serialized_key = RestrictedData(
263       key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get());
264 
265   util::StatusOr<internal::ProtoKeySerialization> serialization =
266       internal::ProtoKeySerialization::Create(
267           "type.googleapis.com/google.crypto.tink.Ed25519PublicKey",
268           serialized_key, KeyData::ASYMMETRIC_PUBLIC, OutputPrefixType::TINK,
269           /*id_requirement=*/0x23456789);
270   ASSERT_THAT(serialization, IsOk());
271 
272   util::StatusOr<std::unique_ptr<Key>> key =
273       internal::MutableSerializationRegistry::GlobalInstance().ParseKey(
274           *serialization, /*token=*/absl::nullopt);
275   EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument));
276 }
277 
TEST_P(Ed25519ProtoSerializationTest,SerializePublicKey)278 TEST_P(Ed25519ProtoSerializationTest, SerializePublicKey) {
279   TestCase test_case = GetParam();
280   ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk());
281 
282   util::StatusOr<Ed25519Parameters> parameters =
283       Ed25519Parameters::Create(test_case.variant);
284   ASSERT_THAT(parameters, IsOk());
285 
286   std::string raw_key_bytes = Random::GetRandomBytes(32);
287   util::StatusOr<Ed25519PublicKey> key = Ed25519PublicKey::Create(
288       *parameters, raw_key_bytes, test_case.id, GetPartialKeyAccess());
289   ASSERT_THAT(key, IsOk());
290 
291   util::StatusOr<std::unique_ptr<Serialization>> serialization =
292       internal::MutableSerializationRegistry::GlobalInstance()
293           .SerializeKey<internal::ProtoKeySerialization>(
294               *key, /*token=*/absl::nullopt);
295   ASSERT_THAT(serialization, IsOk());
296   EXPECT_THAT((*serialization)->ObjectIdentifier(),
297               Eq("type.googleapis.com/google.crypto.tink.Ed25519PublicKey"));
298 
299   const internal::ProtoKeySerialization* proto_serialization =
300       dynamic_cast<const internal::ProtoKeySerialization*>(
301           serialization->get());
302   ASSERT_THAT(proto_serialization, NotNull());
303   EXPECT_THAT(proto_serialization->TypeUrl(),
304               Eq("type.googleapis.com/google.crypto.tink.Ed25519PublicKey"));
305   EXPECT_THAT(proto_serialization->KeyMaterialType(),
306               Eq(KeyData::ASYMMETRIC_PUBLIC));
307   EXPECT_THAT(proto_serialization->GetOutputPrefixType(),
308               Eq(test_case.output_prefix_type));
309   EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id));
310 
311   google::crypto::tink::Ed25519PublicKey proto_key;
312   // OSS proto library complains if input is not converted to a string.
313   ASSERT_THAT(proto_key.ParseFromString(std::string(
314                   proto_serialization->SerializedKeyProto().GetSecret(
315                       InsecureSecretKeyAccess::Get()))),
316               IsTrue());
317   EXPECT_THAT(proto_key.version(), Eq(0));
318   EXPECT_THAT(proto_key.key_value(), Eq(raw_key_bytes));
319 }
320 
TEST_P(Ed25519ProtoSerializationTest,ParsePrivateKey)321 TEST_P(Ed25519ProtoSerializationTest, ParsePrivateKey) {
322   TestCase test_case = GetParam();
323   ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk());
324 
325   util::StatusOr<std::unique_ptr<internal::Ed25519Key>> key_pair =
326       internal::NewEd25519Key();
327   ASSERT_THAT(key_pair, IsOk());
328 
329   google::crypto::tink::Ed25519PublicKey public_key_proto;
330   public_key_proto.set_version(0);
331   public_key_proto.set_key_value((*key_pair)->public_key);
332 
333   google::crypto::tink::Ed25519PrivateKey private_key_proto;
334   private_key_proto.set_version(0);
335   *private_key_proto.mutable_public_key() = public_key_proto;
336   private_key_proto.set_key_value((*key_pair)->private_key);
337 
338   RestrictedData serialized_key = RestrictedData(
339       private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get());
340 
341   util::StatusOr<internal::ProtoKeySerialization> serialization =
342       internal::ProtoKeySerialization::Create(
343           "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey",
344           serialized_key, KeyData::ASYMMETRIC_PRIVATE,
345           test_case.output_prefix_type, test_case.id);
346   ASSERT_THAT(serialization, IsOk());
347 
348   util::StatusOr<std::unique_ptr<Key>> key =
349       internal::MutableSerializationRegistry::GlobalInstance().ParseKey(
350           *serialization, InsecureSecretKeyAccess::Get());
351   ASSERT_THAT(key, IsOk());
352   EXPECT_THAT((*key)->GetIdRequirement(), Eq(test_case.id));
353   EXPECT_THAT((*key)->GetParameters().HasIdRequirement(),
354               test_case.id.has_value());
355 
356   util::StatusOr<Ed25519Parameters> expected_parameters =
357       Ed25519Parameters::Create(test_case.variant);
358   ASSERT_THAT(expected_parameters, IsOk());
359 
360   util::StatusOr<Ed25519PublicKey> expected_public_key =
361       Ed25519PublicKey::Create(*expected_parameters, (*key_pair)->public_key,
362                                test_case.id, GetPartialKeyAccess());
363   ASSERT_THAT(expected_public_key, IsOk());
364 
365   util::StatusOr<Ed25519PrivateKey> expected_private_key =
366       Ed25519PrivateKey::Create(*expected_public_key,
367                                 RestrictedData((*key_pair)->private_key,
368                                                InsecureSecretKeyAccess::Get()),
369                                 GetPartialKeyAccess());
370   ASSERT_THAT(expected_private_key, IsOk());
371 
372   EXPECT_THAT(**key, Eq(*expected_private_key));
373 }
374 
TEST_F(Ed25519ProtoSerializationTest,ParsePrivateKeyWithInvalidSerialization)375 TEST_F(Ed25519ProtoSerializationTest, ParsePrivateKeyWithInvalidSerialization) {
376   ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk());
377 
378   RestrictedData serialized_key =
379       RestrictedData("invalid_serialization", InsecureSecretKeyAccess::Get());
380 
381   util::StatusOr<internal::ProtoKeySerialization> serialization =
382       internal::ProtoKeySerialization::Create(
383           "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey",
384           serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK,
385           /*id_requirement=*/0x23456789);
386   ASSERT_THAT(serialization, IsOk());
387 
388   util::StatusOr<std::unique_ptr<Key>> key =
389       internal::MutableSerializationRegistry::GlobalInstance().ParseKey(
390           *serialization, InsecureSecretKeyAccess::Get());
391   EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument));
392 }
393 
TEST_F(Ed25519ProtoSerializationTest,ParsePrivateKeyWithInvalidVersion)394 TEST_F(Ed25519ProtoSerializationTest, ParsePrivateKeyWithInvalidVersion) {
395   ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk());
396 
397   util::StatusOr<std::unique_ptr<internal::Ed25519Key>> key_pair =
398       internal::NewEd25519Key();
399   ASSERT_THAT(key_pair, IsOk());
400 
401   google::crypto::tink::Ed25519PublicKey public_key_proto;
402   public_key_proto.set_version(0);
403   public_key_proto.set_key_value((*key_pair)->public_key);
404 
405   google::crypto::tink::Ed25519PrivateKey private_key_proto;
406   private_key_proto.set_version(1);
407   *private_key_proto.mutable_public_key() = public_key_proto;
408   private_key_proto.set_key_value((*key_pair)->private_key);
409 
410   RestrictedData serialized_key = RestrictedData(
411       private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get());
412 
413   util::StatusOr<internal::ProtoKeySerialization> serialization =
414       internal::ProtoKeySerialization::Create(
415           "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey",
416           serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK,
417           /*id_requirement=*/0x23456789);
418   ASSERT_THAT(serialization, IsOk());
419 
420   util::StatusOr<std::unique_ptr<Key>> key =
421       internal::MutableSerializationRegistry::GlobalInstance().ParseKey(
422           *serialization, InsecureSecretKeyAccess::Get());
423   EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kInvalidArgument));
424 }
425 
TEST_F(Ed25519ProtoSerializationTest,ParsePrivateKeyNoSecretKeyAccess)426 TEST_F(Ed25519ProtoSerializationTest, ParsePrivateKeyNoSecretKeyAccess) {
427   ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk());
428 
429   util::StatusOr<std::unique_ptr<internal::Ed25519Key>> key_pair =
430       internal::NewEd25519Key();
431   ASSERT_THAT(key_pair, IsOk());
432 
433   google::crypto::tink::Ed25519PublicKey public_key_proto;
434   public_key_proto.set_version(0);
435   public_key_proto.set_key_value((*key_pair)->public_key);
436 
437   google::crypto::tink::Ed25519PrivateKey private_key_proto;
438   private_key_proto.set_version(0);
439   *private_key_proto.mutable_public_key() = public_key_proto;
440   private_key_proto.set_key_value((*key_pair)->private_key);
441 
442   RestrictedData serialized_key = RestrictedData(
443       private_key_proto.SerializeAsString(), InsecureSecretKeyAccess::Get());
444 
445   util::StatusOr<internal::ProtoKeySerialization> serialization =
446       internal::ProtoKeySerialization::Create(
447           "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey",
448           serialized_key, KeyData::ASYMMETRIC_PRIVATE, OutputPrefixType::TINK,
449           /*id_requirement=*/0x23456789);
450   ASSERT_THAT(serialization, IsOk());
451 
452   util::StatusOr<std::unique_ptr<Key>> key =
453       internal::MutableSerializationRegistry::GlobalInstance().ParseKey(
454           *serialization, /*token=*/absl::nullopt);
455   EXPECT_THAT(key.status(), StatusIs(absl::StatusCode::kPermissionDenied));
456 }
457 
TEST_P(Ed25519ProtoSerializationTest,SerializePrivateKey)458 TEST_P(Ed25519ProtoSerializationTest, SerializePrivateKey) {
459   TestCase test_case = GetParam();
460   ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk());
461 
462   util::StatusOr<Ed25519Parameters> parameters =
463       Ed25519Parameters::Create(test_case.variant);
464   ASSERT_THAT(parameters, IsOk());
465 
466   util::StatusOr<std::unique_ptr<internal::Ed25519Key>> key_pair =
467       internal::NewEd25519Key();
468   ASSERT_THAT(key_pair, IsOk());
469 
470   util::StatusOr<Ed25519PublicKey> public_key =
471       Ed25519PublicKey::Create(*parameters, (*key_pair)->public_key,
472                                test_case.id, GetPartialKeyAccess());
473   ASSERT_THAT(public_key, IsOk());
474 
475   util::StatusOr<Ed25519PrivateKey> private_key = Ed25519PrivateKey::Create(
476       *public_key,
477       RestrictedData((*key_pair)->private_key, InsecureSecretKeyAccess::Get()),
478       GetPartialKeyAccess());
479   ASSERT_THAT(private_key, IsOk());
480 
481   util::StatusOr<std::unique_ptr<Serialization>> serialization =
482       internal::MutableSerializationRegistry::GlobalInstance()
483           .SerializeKey<internal::ProtoKeySerialization>(
484               *private_key, InsecureSecretKeyAccess::Get());
485   ASSERT_THAT(serialization, IsOk());
486   EXPECT_THAT((*serialization)->ObjectIdentifier(),
487               Eq("type.googleapis.com/google.crypto.tink.Ed25519PrivateKey"));
488 
489   const internal::ProtoKeySerialization* proto_serialization =
490       dynamic_cast<const internal::ProtoKeySerialization*>(
491           serialization->get());
492   ASSERT_THAT(proto_serialization, NotNull());
493   EXPECT_THAT(proto_serialization->TypeUrl(),
494               Eq("type.googleapis.com/google.crypto.tink.Ed25519PrivateKey"));
495   EXPECT_THAT(proto_serialization->KeyMaterialType(),
496               Eq(KeyData::ASYMMETRIC_PRIVATE));
497   EXPECT_THAT(proto_serialization->GetOutputPrefixType(),
498               Eq(test_case.output_prefix_type));
499   EXPECT_THAT(proto_serialization->IdRequirement(), Eq(test_case.id));
500 
501   google::crypto::tink::Ed25519PrivateKey proto_key;
502   // OSS proto library complains if input is not converted to a string.
503   ASSERT_THAT(proto_key.ParseFromString(std::string(
504                   proto_serialization->SerializedKeyProto().GetSecret(
505                       InsecureSecretKeyAccess::Get()))),
506               IsTrue());
507   EXPECT_THAT(proto_key.version(), Eq(0));
508   EXPECT_THAT(proto_key.key_value(), Eq((*key_pair)->private_key));
509   EXPECT_THAT(proto_key.has_public_key(), IsTrue());
510   EXPECT_THAT(proto_key.public_key().version(), Eq(0));
511   EXPECT_THAT(proto_key.public_key().key_value(), Eq((*key_pair)->public_key));
512 }
513 
TEST_F(Ed25519ProtoSerializationTest,SerializePrivateKeyNoSecretKeyAccess)514 TEST_F(Ed25519ProtoSerializationTest, SerializePrivateKeyNoSecretKeyAccess) {
515   ASSERT_THAT(RegisterEd25519ProtoSerialization(), IsOk());
516 
517   util::StatusOr<Ed25519Parameters> parameters =
518       Ed25519Parameters::Create(Ed25519Parameters::Variant::kTink);
519   ASSERT_THAT(parameters, IsOk());
520 
521   util::StatusOr<std::unique_ptr<internal::Ed25519Key>> key_pair =
522       internal::NewEd25519Key();
523   ASSERT_THAT(key_pair, IsOk());
524 
525   util::StatusOr<Ed25519PublicKey> public_key =
526       Ed25519PublicKey::Create(*parameters, (*key_pair)->public_key,
527                                /*id_requirement=*/123, GetPartialKeyAccess());
528   ASSERT_THAT(public_key, IsOk());
529 
530   util::StatusOr<Ed25519PrivateKey> private_key = Ed25519PrivateKey::Create(
531       *public_key,
532       RestrictedData((*key_pair)->private_key, InsecureSecretKeyAccess::Get()),
533       GetPartialKeyAccess());
534   ASSERT_THAT(private_key, IsOk());
535 
536   util::StatusOr<std::unique_ptr<Serialization>> serialization =
537       internal::MutableSerializationRegistry::GlobalInstance()
538           .SerializeKey<internal::ProtoKeySerialization>(
539               *private_key, /*token=*/absl::nullopt);
540   ASSERT_THAT(serialization.status(),
541               StatusIs(absl::StatusCode::kPermissionDenied));
542 }
543 
544 }  // namespace
545 }  // namespace tink
546 }  // namespace crypto
547