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