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_public_key.h"
18
19 #include <string>
20
21 #include "gmock/gmock.h"
22 #include "gtest/gtest.h"
23 #include "tink/partial_key_access.h"
24 #include "tink/subtle/random.h"
25 #include "tink/util/statusor.h"
26 #include "tink/util/test_matchers.h"
27
28 namespace crypto {
29 namespace tink {
30 namespace {
31
32 using ::crypto::tink::test::IsOk;
33 using ::crypto::tink::test::StatusIs;
34 using ::testing::Eq;
35 using ::testing::TestWithParam;
36 using ::testing::Values;
37
38 struct TestCase {
39 Ed25519Parameters::Variant variant;
40 absl::optional<int> id_requirement;
41 std::string output_prefix;
42 };
43
44 using Ed25519PublicKeyTest = TestWithParam<TestCase>;
45
46 INSTANTIATE_TEST_SUITE_P(
47 Ed25519PublicKeyTestSuite, Ed25519PublicKeyTest,
48 Values(TestCase{Ed25519Parameters::Variant::kTink, 0x02030400,
49 std::string("\x01\x02\x03\x04\x00", 5)},
50 TestCase{Ed25519Parameters::Variant::kCrunchy, 0x01030005,
51 std::string("\x00\x01\x03\x00\x05", 5)},
52 TestCase{Ed25519Parameters::Variant::kLegacy, 0x07080910,
53 std::string("\x00\x07\x08\x09\x10", 5)},
54 TestCase{Ed25519Parameters::Variant::kNoPrefix, absl::nullopt, ""}));
55
TEST_P(Ed25519PublicKeyTest,CreateSucceeds)56 TEST_P(Ed25519PublicKeyTest, CreateSucceeds) {
57 TestCase test_case = GetParam();
58
59 util::StatusOr<Ed25519Parameters> params =
60 Ed25519Parameters::Create(test_case.variant);
61 ASSERT_THAT(params, IsOk());
62
63 std::string public_key_bytes = subtle::Random::GetRandomBytes(32);
64 util::StatusOr<Ed25519PublicKey> public_key =
65 Ed25519PublicKey::Create(*params, public_key_bytes,
66 test_case.id_requirement, GetPartialKeyAccess());
67 ASSERT_THAT(public_key, IsOk());
68
69 EXPECT_THAT(public_key->GetParameters(), Eq(*params));
70 EXPECT_THAT(public_key->GetIdRequirement(), Eq(test_case.id_requirement));
71 EXPECT_THAT(public_key->GetOutputPrefix(), Eq(test_case.output_prefix));
72 EXPECT_THAT(public_key->GetPublicKeyBytes(GetPartialKeyAccess()),
73 Eq(public_key_bytes));
74 }
75
TEST(Ed25519PublicKeyTest,CreateWithInvalidPublicKeyLength)76 TEST(Ed25519PublicKeyTest, CreateWithInvalidPublicKeyLength) {
77 util::StatusOr<Ed25519Parameters> params =
78 Ed25519Parameters::Create(Ed25519Parameters::Variant::kTink);
79 ASSERT_THAT(params, IsOk());
80
81 std::string public_key_bytes = subtle::Random::GetRandomBytes(31);
82
83 EXPECT_THAT(
84 Ed25519PublicKey::Create(*params, public_key_bytes,
85 /*id_requirement=*/123, GetPartialKeyAccess())
86 .status(),
87 StatusIs(absl::StatusCode::kInvalidArgument));
88 }
89
TEST(Ed25519PublicKeyTest,CreateKeyWithInvalidIdRequirementFails)90 TEST(Ed25519PublicKeyTest, CreateKeyWithInvalidIdRequirementFails) {
91 util::StatusOr<Ed25519Parameters> no_prefix_params =
92 Ed25519Parameters::Create(Ed25519Parameters::Variant::kNoPrefix);
93 ASSERT_THAT(no_prefix_params, IsOk());
94
95 util::StatusOr<Ed25519Parameters> tink_params =
96 Ed25519Parameters::Create(Ed25519Parameters::Variant::kTink);
97 ASSERT_THAT(tink_params, IsOk());
98
99 std::string public_key_bytes = subtle::Random::GetRandomBytes(32);
100
101 EXPECT_THAT(
102 Ed25519PublicKey::Create(*no_prefix_params, public_key_bytes,
103 /*id_requirement=*/123, GetPartialKeyAccess())
104 .status(),
105 StatusIs(absl::StatusCode::kInvalidArgument));
106
107 EXPECT_THAT(Ed25519PublicKey::Create(*tink_params, public_key_bytes,
108 /*id_requirement=*/absl::nullopt,
109 GetPartialKeyAccess())
110 .status(),
111 StatusIs(absl::StatusCode::kInvalidArgument));
112 }
113
TEST_P(Ed25519PublicKeyTest,KeyEquals)114 TEST_P(Ed25519PublicKeyTest, KeyEquals) {
115 TestCase test_case = GetParam();
116
117 util::StatusOr<Ed25519Parameters> params =
118 Ed25519Parameters::Create(test_case.variant);
119 ASSERT_THAT(params, IsOk());
120
121 std::string public_key_bytes = subtle::Random::GetRandomBytes(32);
122
123 util::StatusOr<Ed25519PublicKey> public_key =
124 Ed25519PublicKey::Create(*params, public_key_bytes,
125 test_case.id_requirement, GetPartialKeyAccess());
126 ASSERT_THAT(public_key, IsOk());
127
128 util::StatusOr<Ed25519PublicKey> other_public_key =
129 Ed25519PublicKey::Create(*params, public_key_bytes,
130 test_case.id_requirement, GetPartialKeyAccess());
131 ASSERT_THAT(other_public_key, IsOk());
132
133 EXPECT_TRUE(*public_key == *other_public_key);
134 EXPECT_TRUE(*other_public_key == *public_key);
135 EXPECT_FALSE(*public_key != *other_public_key);
136 EXPECT_FALSE(*other_public_key != *public_key);
137 }
138
TEST(Ed25519PublicKeyTest,DifferentVariantNotEqual)139 TEST(Ed25519PublicKeyTest, DifferentVariantNotEqual) {
140 util::StatusOr<Ed25519Parameters> crunchy_params =
141 Ed25519Parameters::Create(Ed25519Parameters::Variant::kCrunchy);
142 ASSERT_THAT(crunchy_params, IsOk());
143
144 util::StatusOr<Ed25519Parameters> tink_params =
145 Ed25519Parameters::Create(Ed25519Parameters::Variant::kTink);
146 ASSERT_THAT(tink_params, IsOk());
147
148 std::string public_key_bytes = subtle::Random::GetRandomBytes(32);
149
150 util::StatusOr<Ed25519PublicKey> public_key = Ed25519PublicKey::Create(
151 *crunchy_params, public_key_bytes, /*id_requirement=*/0x01020304,
152 GetPartialKeyAccess());
153 ASSERT_THAT(public_key, IsOk());
154
155 util::StatusOr<Ed25519PublicKey> other_public_key = Ed25519PublicKey::Create(
156 *tink_params, public_key_bytes, /*id_requirement=*/0x01020304,
157 GetPartialKeyAccess());
158 ASSERT_THAT(other_public_key, IsOk());
159
160 EXPECT_TRUE(*public_key != *other_public_key);
161 EXPECT_TRUE(*other_public_key != *public_key);
162 EXPECT_FALSE(*public_key == *other_public_key);
163 EXPECT_FALSE(*other_public_key == *public_key);
164 }
165
TEST(Ed25519PublicKeyTest,DifferentPublicKeyBytesNotEqual)166 TEST(Ed25519PublicKeyTest, DifferentPublicKeyBytesNotEqual) {
167 util::StatusOr<Ed25519Parameters> params =
168 Ed25519Parameters::Create(Ed25519Parameters::Variant::kTink);
169 ASSERT_THAT(params, IsOk());
170
171 std::string public_key_bytes1 = subtle::Random::GetRandomBytes(32);
172 std::string public_key_bytes2 = subtle::Random::GetRandomBytes(32);
173
174 util::StatusOr<Ed25519PublicKey> public_key = Ed25519PublicKey::Create(
175 *params, public_key_bytes1, /*id_requirement=*/0x01020304,
176 GetPartialKeyAccess());
177 ASSERT_THAT(public_key, IsOk());
178
179 util::StatusOr<Ed25519PublicKey> other_public_key = Ed25519PublicKey::Create(
180 *params, public_key_bytes2, /*id_requirement=*/0x01020304,
181 GetPartialKeyAccess());
182 ASSERT_THAT(other_public_key, IsOk());
183
184 EXPECT_TRUE(*public_key != *other_public_key);
185 EXPECT_TRUE(*other_public_key != *public_key);
186 EXPECT_FALSE(*public_key == *other_public_key);
187 EXPECT_FALSE(*other_public_key == *public_key);
188 }
189
TEST(Ed25519PublicKeyTest,DifferentIdRequirementNotEqual)190 TEST(Ed25519PublicKeyTest, DifferentIdRequirementNotEqual) {
191 util::StatusOr<Ed25519Parameters> params =
192 Ed25519Parameters::Create(Ed25519Parameters::Variant::kTink);
193 ASSERT_THAT(params, IsOk());
194
195 std::string public_key_bytes = subtle::Random::GetRandomBytes(32);
196
197 util::StatusOr<Ed25519PublicKey> public_key = Ed25519PublicKey::Create(
198 *params, public_key_bytes, /*id_requirement=*/0x01020304,
199 GetPartialKeyAccess());
200 ASSERT_THAT(public_key, IsOk());
201
202 util::StatusOr<Ed25519PublicKey> other_public_key = Ed25519PublicKey::Create(
203 *params, public_key_bytes, /*id_requirement=*/0x02030405,
204 GetPartialKeyAccess());
205 ASSERT_THAT(other_public_key, IsOk());
206
207 EXPECT_TRUE(*public_key != *other_public_key);
208 EXPECT_TRUE(*other_public_key != *public_key);
209 EXPECT_FALSE(*public_key == *other_public_key);
210 EXPECT_FALSE(*other_public_key == *public_key);
211 }
212
213 } // namespace
214 } // namespace tink
215 } // namespace crypto
216