• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package com.google.crypto.tink.signature;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static org.junit.Assert.assertThrows;
21 
22 import com.google.crypto.tink.InsecureSecretKeyAccess;
23 import com.google.crypto.tink.internal.KeyTester;
24 import com.google.crypto.tink.subtle.Hex;
25 import com.google.crypto.tink.util.Bytes;
26 import com.google.crypto.tink.util.SecretBytes;
27 import java.security.GeneralSecurityException;
28 import org.junit.Test;
29 import org.junit.runner.RunWith;
30 import org.junit.runners.JUnit4;
31 
32 @RunWith(JUnit4.class)
33 public final class Ed25519PrivateKeyTest {
34   // Test case from https://www.rfc-editor.org/rfc/rfc8032#page-24
35   private static final byte[] SECRET_KEY =
36       Hex.decode("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60");
37   private static final byte[] PUBLIC_KEY =
38       Hex.decode("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a");
39 
40   private static final SecretBytes PRIVATE_KEY_BYTES =
41       SecretBytes.copyFrom(SECRET_KEY, InsecureSecretKeyAccess.get());
42   private static final Bytes PUBLIC_KEY_BYTES = Bytes.copyFrom(PUBLIC_KEY);
43 
44   @Test
createNoPrefixVariantAndGetProperties()45   public void createNoPrefixVariantAndGetProperties() throws Exception {
46     Ed25519PublicKey publicKey = Ed25519PublicKey.create(PUBLIC_KEY_BYTES);
47     Ed25519PrivateKey privateKey = Ed25519PrivateKey.create(publicKey, PRIVATE_KEY_BYTES);
48 
49     assertThat(privateKey.getParameters()).isEqualTo(Ed25519Parameters.create());
50     assertThat(privateKey.getPrivateKeyBytes()).isEqualTo(PRIVATE_KEY_BYTES);
51     assertThat(privateKey.getPublicKey()).isEqualTo(publicKey);
52     assertThat(privateKey.getOutputPrefix()).isEqualTo(Bytes.copyFrom(new byte[] {}));
53     assertThat(privateKey.getIdRequirementOrNull()).isNull();
54   }
55 
56   @Test
createTinkVariantAndGetProperties()57   public void createTinkVariantAndGetProperties() throws Exception {
58     Ed25519PublicKey publicKey =
59         Ed25519PublicKey.create(
60             Ed25519Parameters.Variant.TINK, PUBLIC_KEY_BYTES, /* idRequirement= */ 0x0708090a);
61     Ed25519PrivateKey privateKey = Ed25519PrivateKey.create(publicKey, PRIVATE_KEY_BYTES);
62 
63     assertThat(privateKey.getParameters())
64         .isEqualTo(Ed25519Parameters.create(Ed25519Parameters.Variant.TINK));
65     assertThat(privateKey.getPrivateKeyBytes()).isEqualTo(PRIVATE_KEY_BYTES);
66     assertThat(privateKey.getPublicKey()).isEqualTo(publicKey);
67     assertThat(privateKey.getOutputPrefix())
68         .isEqualTo(Bytes.copyFrom(new byte[] {0x01, 0x07, 0x08, 0x09, 0x0a}));
69     assertThat(privateKey.getIdRequirementOrNull()).isEqualTo(0x708090a);
70   }
71 
72   @Test
createCrunchyVariantAndGetProperties()73   public void createCrunchyVariantAndGetProperties() throws Exception {
74     Ed25519PublicKey publicKey =
75         Ed25519PublicKey.create(
76             Ed25519Parameters.Variant.CRUNCHY, PUBLIC_KEY_BYTES, /* idRequirement= */ 0x0708090a);
77     Ed25519PrivateKey privateKey = Ed25519PrivateKey.create(publicKey, PRIVATE_KEY_BYTES);
78 
79     assertThat(privateKey.getParameters())
80         .isEqualTo(Ed25519Parameters.create(Ed25519Parameters.Variant.CRUNCHY));
81     assertThat(privateKey.getPrivateKeyBytes()).isEqualTo(PRIVATE_KEY_BYTES);
82     assertThat(privateKey.getPublicKey()).isEqualTo(publicKey);
83     assertThat(privateKey.getOutputPrefix())
84         .isEqualTo(Bytes.copyFrom(new byte[] {0x00, 0x07, 0x08, 0x09, 0x0a}));
85     assertThat(privateKey.getIdRequirementOrNull()).isEqualTo(0x708090a);
86   }
87 
88   @Test
createLegacyVariantAndGetProperties()89   public void createLegacyVariantAndGetProperties() throws Exception {
90     Ed25519PublicKey publicKey =
91         Ed25519PublicKey.create(
92             Ed25519Parameters.Variant.LEGACY, PUBLIC_KEY_BYTES, /* idRequirement= */ 0x0708090a);
93     Ed25519PrivateKey privateKey = Ed25519PrivateKey.create(publicKey, PRIVATE_KEY_BYTES);
94 
95     assertThat(privateKey.getParameters())
96         .isEqualTo(Ed25519Parameters.create(Ed25519Parameters.Variant.LEGACY));
97     assertThat(privateKey.getPrivateKeyBytes()).isEqualTo(PRIVATE_KEY_BYTES);
98     assertThat(privateKey.getPublicKey()).isEqualTo(publicKey);
99     assertThat(privateKey.getOutputPrefix())
100         .isEqualTo(Bytes.copyFrom(new byte[] {0x00, 0x07, 0x08, 0x09, 0x0a}));
101     assertThat(privateKey.getIdRequirementOrNull()).isEqualTo(0x708090a);
102   }
103 
104   @Test
invalidKeySize()105   public void invalidKeySize() throws Exception {
106     SecretBytes invalidSizePrivateKeyBytes = SecretBytes.randomBytes(64);
107 
108     Ed25519PublicKey publicKey = Ed25519PublicKey.create(PUBLIC_KEY_BYTES);
109 
110     assertThrows(
111         GeneralSecurityException.class,
112         () -> Ed25519PrivateKey.create(publicKey, invalidSizePrivateKeyBytes));
113   }
114 
115   @Test
keysMismatch_fails()116   public void keysMismatch_fails() throws Exception {
117     SecretBytes invalidPrivateKeyBytes = SecretBytes.randomBytes(32);
118 
119     Ed25519PublicKey publicKey = Ed25519PublicKey.create(PUBLIC_KEY_BYTES);
120 
121     assertThrows(
122         GeneralSecurityException.class,
123         () -> Ed25519PrivateKey.create(publicKey, invalidPrivateKeyBytes));
124   }
125 
126   @Test
nullPublicKey()127   public void nullPublicKey() throws Exception {
128     assertThrows(
129         GeneralSecurityException.class, () -> Ed25519PrivateKey.create(null, PRIVATE_KEY_BYTES));
130   }
131 
132   @Test
testEqualities()133   public void testEqualities() throws Exception {
134     SecretBytes privateKeyBytesCopy =
135         SecretBytes.copyFrom(
136             PRIVATE_KEY_BYTES.toByteArray(InsecureSecretKeyAccess.get()),
137             InsecureSecretKeyAccess.get());
138 
139     Ed25519PublicKey publicKey = Ed25519PublicKey.create(PUBLIC_KEY_BYTES);
140     Ed25519PublicKey publicKeyCopy = Ed25519PublicKey.create(PUBLIC_KEY_BYTES);
141 
142     // Test case from https://www.rfc-editor.org/rfc/rfc8032#page-24
143     Bytes publicKeyBytesDiff =
144         Bytes.copyFrom(
145             Hex.decode("3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c"));
146     Ed25519PublicKey publicKeyDiff = Ed25519PublicKey.create(publicKeyBytesDiff);
147     SecretBytes privateKeyBytesDiff =
148         SecretBytes.copyFrom(
149             Hex.decode("4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb"),
150             InsecureSecretKeyAccess.get());
151 
152     Ed25519PublicKey publicKeyTink =
153         Ed25519PublicKey.create(
154             Ed25519Parameters.Variant.TINK, PUBLIC_KEY_BYTES, /* idRequirement= */ 0x0708090a);
155     Ed25519PublicKey publicKeyCrunchy =
156         Ed25519PublicKey.create(
157             Ed25519Parameters.Variant.CRUNCHY, PUBLIC_KEY_BYTES, /* idRequirement= */ 0x0708090a);
158     Ed25519PublicKey publicKeyLegacy =
159         Ed25519PublicKey.create(
160             Ed25519Parameters.Variant.LEGACY, PUBLIC_KEY_BYTES, /* idRequirement= */ 0x0708090a);
161 
162     new KeyTester()
163         .addEqualityGroup(
164             "No prefix, keyBytes",
165             Ed25519PrivateKey.create(publicKey, PRIVATE_KEY_BYTES),
166             Ed25519PrivateKey.create(publicKey, privateKeyBytesCopy),
167             Ed25519PrivateKey.create(publicKeyCopy, PRIVATE_KEY_BYTES))
168         .addEqualityGroup(
169             "No prefix, different key bytes",
170             Ed25519PrivateKey.create(publicKeyDiff, privateKeyBytesDiff))
171         .addEqualityGroup(
172             "Tink public key, keyBytes", Ed25519PrivateKey.create(publicKeyTink, PRIVATE_KEY_BYTES))
173         .addEqualityGroup(
174             "Crunchy public key, keyBytes",
175             Ed25519PrivateKey.create(publicKeyCrunchy, PRIVATE_KEY_BYTES))
176         .addEqualityGroup(
177             "Legacy public key, keyBytes",
178             Ed25519PrivateKey.create(publicKeyLegacy, PRIVATE_KEY_BYTES))
179         .doTests();
180   }
181 
182   @Test
testDifferentKeyTypesEquality_fails()183   public void testDifferentKeyTypesEquality_fails() throws Exception {
184     Ed25519PublicKey publicKey = Ed25519PublicKey.create(PUBLIC_KEY_BYTES);
185     Ed25519PrivateKey privateKey = Ed25519PrivateKey.create(publicKey, PRIVATE_KEY_BYTES);
186 
187     assertThat(privateKey.equalsKey(publicKey)).isFalse();
188   }
189 }
190