• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 Google Inc.
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.crypto.tink.internal.TinkBugException.exceptionIsBug;
20 
21 import com.google.crypto.tink.AccessesPartialKey;
22 import com.google.crypto.tink.InsecureSecretKeyAccess;
23 import com.google.crypto.tink.KeyManager;
24 import com.google.crypto.tink.KeyTemplate;
25 import com.google.crypto.tink.Parameters;
26 import com.google.crypto.tink.PrivateKeyManager;
27 import com.google.crypto.tink.PublicKeySign;
28 import com.google.crypto.tink.PublicKeyVerify;
29 import com.google.crypto.tink.SecretKeyAccess;
30 import com.google.crypto.tink.config.internal.TinkFipsUtil;
31 import com.google.crypto.tink.internal.KeyManagerRegistry;
32 import com.google.crypto.tink.internal.LegacyKeyManagerImpl;
33 import com.google.crypto.tink.internal.MutableKeyCreationRegistry;
34 import com.google.crypto.tink.internal.MutableKeyDerivationRegistry;
35 import com.google.crypto.tink.internal.MutableParametersRegistry;
36 import com.google.crypto.tink.internal.MutablePrimitiveRegistry;
37 import com.google.crypto.tink.internal.PrimitiveConstructor;
38 import com.google.crypto.tink.internal.Util;
39 import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
40 import com.google.crypto.tink.signature.internal.Ed25519ProtoSerialization;
41 import com.google.crypto.tink.subtle.Ed25519Sign;
42 import com.google.crypto.tink.subtle.Ed25519Verify;
43 import com.google.crypto.tink.util.Bytes;
44 import com.google.crypto.tink.util.SecretBytes;
45 import java.io.InputStream;
46 import java.security.GeneralSecurityException;
47 import java.util.Collections;
48 import java.util.HashMap;
49 import java.util.Map;
50 import javax.annotation.Nullable;
51 
52 /**
53  * This instance of {@code KeyManager} generates new {@code Ed25519PrivateKey} keys and produces new
54  * instances of {@code Ed25519Sign}.
55  */
56 public final class Ed25519PrivateKeyManager {
57   private static final PrimitiveConstructor<Ed25519PrivateKey, PublicKeySign>
58       PUBLIC_KEY_SIGN_PRIMITIVE_CONSTRUCTOR =
59           PrimitiveConstructor.create(
60               Ed25519Sign::create, Ed25519PrivateKey.class, PublicKeySign.class);
61 
62   private static final PrimitiveConstructor<Ed25519PublicKey, PublicKeyVerify>
63       PUBLIC_KEY_VERIFY_PRIMITIVE_CONSTRUCTOR =
64           PrimitiveConstructor.create(
65               Ed25519Verify::create, Ed25519PublicKey.class, PublicKeyVerify.class);
66 
67   private static final PrivateKeyManager<PublicKeySign> legacyPrivateKeyManager =
68       LegacyKeyManagerImpl.createPrivateKeyManager(
69           getKeyType(),
70           PublicKeySign.class,
71           com.google.crypto.tink.proto.Ed25519PrivateKey.parser());
72 
73   private static final KeyManager<PublicKeyVerify> legacyPublicKeyManager =
74       LegacyKeyManagerImpl.create(
75           Ed25519PublicKeyManager.getKeyType(),
76           PublicKeyVerify.class,
77           KeyMaterialType.ASYMMETRIC_PUBLIC,
78           com.google.crypto.tink.proto.Ed25519PublicKey.parser());
79 
getKeyType()80   static String getKeyType() {
81     return "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey";
82   }
83 
84   @AccessesPartialKey
createEd25519KeyFromRandomness( Ed25519Parameters parameters, InputStream stream, @Nullable Integer idRequirement, SecretKeyAccess access)85   static com.google.crypto.tink.signature.Ed25519PrivateKey createEd25519KeyFromRandomness(
86       Ed25519Parameters parameters,
87       InputStream stream,
88       @Nullable Integer idRequirement,
89       SecretKeyAccess access)
90       throws GeneralSecurityException {
91     SecretBytes pseudorandomness =
92         Util.readIntoSecretBytes(stream, Ed25519Sign.SECRET_KEY_LEN, access);
93     Ed25519Sign.KeyPair keyPair =
94         Ed25519Sign.KeyPair.newKeyPairFromSeed(pseudorandomness.toByteArray(access));
95     com.google.crypto.tink.signature.Ed25519PublicKey publicKey =
96         com.google.crypto.tink.signature.Ed25519PublicKey.create(
97             parameters.getVariant(), Bytes.copyFrom(keyPair.getPublicKey()), idRequirement);
98     return com.google.crypto.tink.signature.Ed25519PrivateKey.create(
99         publicKey, SecretBytes.copyFrom(keyPair.getPrivateKey(), access));
100   }
101 
102   @SuppressWarnings("InlineLambdaConstant") // We need a correct Object#equals in registration.
103   private static final MutableKeyDerivationRegistry.InsecureKeyCreator<Ed25519Parameters>
104       KEY_DERIVER = Ed25519PrivateKeyManager::createEd25519KeyFromRandomness;
105 
106   @AccessesPartialKey
createEd25519Key( Ed25519Parameters parameters, @Nullable Integer idRequirement)107   static com.google.crypto.tink.signature.Ed25519PrivateKey createEd25519Key(
108       Ed25519Parameters parameters, @Nullable Integer idRequirement)
109       throws GeneralSecurityException {
110     Ed25519Sign.KeyPair keyPair = Ed25519Sign.KeyPair.newKeyPair();
111     com.google.crypto.tink.signature.Ed25519PublicKey publicKey =
112         com.google.crypto.tink.signature.Ed25519PublicKey.create(
113             parameters.getVariant(), Bytes.copyFrom(keyPair.getPublicKey()), idRequirement);
114     return com.google.crypto.tink.signature.Ed25519PrivateKey.create(
115         publicKey, SecretBytes.copyFrom(keyPair.getPrivateKey(), InsecureSecretKeyAccess.get()));
116   }
117 
118   @SuppressWarnings("InlineLambdaConstant") // We need a correct Object#equals in registration.
119   private static final MutableKeyCreationRegistry.KeyCreator<Ed25519Parameters> KEY_CREATOR =
120       Ed25519PrivateKeyManager::createEd25519Key;
121 
namedParameters()122   private static Map<String, Parameters> namedParameters() throws GeneralSecurityException {
123         Map<String, Parameters> result = new HashMap<>();
124         result.put("ED25519", Ed25519Parameters.create(Ed25519Parameters.Variant.TINK));
125         result.put("ED25519_RAW", Ed25519Parameters.create(Ed25519Parameters.Variant.NO_PREFIX));
126         // This is identical to ED25519_RAW.
127         // It is needed to maintain backward compatibility with SignatureKeyTemplates.
128         result.put(
129             "ED25519WithRawOutput", Ed25519Parameters.create(Ed25519Parameters.Variant.NO_PREFIX));
130         return Collections.unmodifiableMap(result);
131   }
132 
133   /**
134    * Registers the {@link Ed25519PrivateKeyManager} and the {@link Ed25519PublicKeyManager} with the
135    * registry, so that the the Ed25519-Keys can be used with Tink.
136    */
registerPair(boolean newKeyAllowed)137   public static void registerPair(boolean newKeyAllowed) throws GeneralSecurityException {
138     if (!TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_NOT_FIPS.isCompatible()) {
139       throw new GeneralSecurityException("Registering AES GCM SIV is not supported in FIPS mode");
140     }
141     Ed25519ProtoSerialization.register();
142     MutableParametersRegistry.globalInstance().putAll(namedParameters());
143     MutableKeyCreationRegistry.globalInstance().add(KEY_CREATOR, Ed25519Parameters.class);
144     MutableKeyDerivationRegistry.globalInstance().add(KEY_DERIVER, Ed25519Parameters.class);
145     MutablePrimitiveRegistry.globalInstance()
146         .registerPrimitiveConstructor(PUBLIC_KEY_SIGN_PRIMITIVE_CONSTRUCTOR);
147     MutablePrimitiveRegistry.globalInstance()
148         .registerPrimitiveConstructor(PUBLIC_KEY_VERIFY_PRIMITIVE_CONSTRUCTOR);
149     KeyManagerRegistry.globalInstance().registerKeyManager(legacyPrivateKeyManager, newKeyAllowed);
150     KeyManagerRegistry.globalInstance()
151         .registerKeyManager(legacyPublicKeyManager, /* newKeyAllowed= */ false);
152   }
153 
154   /**
155    * @return A {@link KeyTemplate} that generates new instances of ED25519 keys.
156    */
ed25519Template()157   public static final KeyTemplate ed25519Template() {
158     return exceptionIsBug(
159         () -> KeyTemplate.createFrom(Ed25519Parameters.create(Ed25519Parameters.Variant.TINK)));
160   }
161 
162   /**
163    * @return A {@link KeyTemplate} that generates new instances of Ed25519 keys. Keys generated from
164    *     this template creates raw signatures of exactly 64 bytes. It's compatible with most other
165    *     libraries.
166    */
rawEd25519Template()167   public static final KeyTemplate rawEd25519Template() {
168     return exceptionIsBug(
169         () ->
170             KeyTemplate.createFrom(Ed25519Parameters.create(Ed25519Parameters.Variant.NO_PREFIX)));
171   }
172 
Ed25519PrivateKeyManager()173   private Ed25519PrivateKeyManager() {}
174 }
175