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