• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 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.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.config.internal.TinkFipsUtil;
30 import com.google.crypto.tink.internal.KeyManagerRegistry;
31 import com.google.crypto.tink.internal.LegacyKeyManagerImpl;
32 import com.google.crypto.tink.internal.MutableKeyCreationRegistry;
33 import com.google.crypto.tink.internal.MutableParametersRegistry;
34 import com.google.crypto.tink.internal.MutablePrimitiveRegistry;
35 import com.google.crypto.tink.internal.PrimitiveConstructor;
36 import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
37 import com.google.crypto.tink.signature.internal.RsaSsaPssProtoSerialization;
38 import com.google.crypto.tink.subtle.EngineFactory;
39 import com.google.crypto.tink.subtle.RsaSsaPssSignJce;
40 import com.google.crypto.tink.subtle.RsaSsaPssVerifyJce;
41 import com.google.crypto.tink.util.SecretBigInteger;
42 import java.math.BigInteger;
43 import java.security.GeneralSecurityException;
44 import java.security.KeyPair;
45 import java.security.KeyPairGenerator;
46 import java.security.interfaces.RSAPrivateCrtKey;
47 import java.security.interfaces.RSAPublicKey;
48 import java.security.spec.RSAKeyGenParameterSpec;
49 import java.util.Collections;
50 import java.util.HashMap;
51 import java.util.Map;
52 import javax.annotation.Nullable;
53 
54 /**
55  * This key manager generates new {@code RsaSsaPssPrivateKey} keys and produces new instances of
56  * {@code RsaSsaPssSignJce}.
57  */
58 public final class RsaSsaPssSignKeyManager {
59   private static final PrimitiveConstructor<RsaSsaPssPrivateKey, PublicKeySign>
60       PUBLIC_KEY_SIGN_PRIMITIVE_CONSTRUCTOR =
61           PrimitiveConstructor.create(
62               RsaSsaPssSignJce::create, RsaSsaPssPrivateKey.class, PublicKeySign.class);
63 
64   private static final PrimitiveConstructor<RsaSsaPssPublicKey, PublicKeyVerify>
65       PUBLIC_KEY_VERIFY_PRIMITIVE_CONSTRUCTOR =
66           PrimitiveConstructor.create(
67               RsaSsaPssVerifyJce::create, RsaSsaPssPublicKey.class, PublicKeyVerify.class);
68 
69   private static final PrivateKeyManager<PublicKeySign> legacyPrivateKeyManager =
70       LegacyKeyManagerImpl.createPrivateKeyManager(
71           getKeyType(),
72           PublicKeySign.class,
73           com.google.crypto.tink.proto.RsaSsaPssPrivateKey.parser());
74 
75   private static final KeyManager<PublicKeyVerify> legacyPublicKeyManager =
76       LegacyKeyManagerImpl.create(
77           RsaSsaPssVerifyKeyManager.getKeyType(),
78           PublicKeyVerify.class,
79           KeyMaterialType.ASYMMETRIC_PUBLIC,
80           com.google.crypto.tink.proto.RsaSsaPssPublicKey.parser());
81 
getKeyType()82   static String getKeyType() {
83     return "type.googleapis.com/google.crypto.tink.RsaSsaPssPrivateKey";
84   }
85 
86   @AccessesPartialKey
createKey( RsaSsaPssParameters parameters, @Nullable Integer idRequirement)87   private static RsaSsaPssPrivateKey createKey(
88       RsaSsaPssParameters parameters, @Nullable Integer idRequirement)
89       throws GeneralSecurityException {
90         KeyPairGenerator keyGen = EngineFactory.KEY_PAIR_GENERATOR.getInstance("RSA");
91     RSAKeyGenParameterSpec spec =
92         new RSAKeyGenParameterSpec(
93             parameters.getModulusSizeBits(),
94             new BigInteger(1, parameters.getPublicExponent().toByteArray()));
95     keyGen.initialize(spec);
96     KeyPair keyPair = keyGen.generateKeyPair();
97     RSAPublicKey pubKey = (RSAPublicKey) keyPair.getPublic();
98     RSAPrivateCrtKey privKey = (RSAPrivateCrtKey) keyPair.getPrivate();
99 
100     // Creates RsaSsaPssPublicKey.
101     RsaSsaPssPublicKey rsaSsaPssPublicKey =
102         RsaSsaPssPublicKey.builder()
103             .setParameters(parameters)
104             .setModulus(pubKey.getModulus())
105             .setIdRequirement(idRequirement)
106             .build();
107 
108     // Creates RsaSsaPssPrivateKey.
109     return RsaSsaPssPrivateKey.builder()
110         .setPublicKey(rsaSsaPssPublicKey)
111         .setPrimes(
112             SecretBigInteger.fromBigInteger(privKey.getPrimeP(), InsecureSecretKeyAccess.get()),
113             SecretBigInteger.fromBigInteger(privKey.getPrimeQ(), InsecureSecretKeyAccess.get()))
114         .setPrivateExponent(
115             SecretBigInteger.fromBigInteger(
116                 privKey.getPrivateExponent(), InsecureSecretKeyAccess.get()))
117         .setPrimeExponents(
118             SecretBigInteger.fromBigInteger(
119                 privKey.getPrimeExponentP(), InsecureSecretKeyAccess.get()),
120             SecretBigInteger.fromBigInteger(
121                 privKey.getPrimeExponentQ(), InsecureSecretKeyAccess.get()))
122         .setCrtCoefficient(
123             SecretBigInteger.fromBigInteger(
124                 privKey.getCrtCoefficient(), InsecureSecretKeyAccess.get()))
125         .build();
126   }
127 
128   @SuppressWarnings("InlineLambdaConstant") // We need a correct Object#equals in registration.
129   private static final MutableKeyCreationRegistry.KeyCreator<RsaSsaPssParameters> KEY_CREATOR =
130       RsaSsaPssSignKeyManager::createKey;
131 
namedParameters()132   private static Map<String, Parameters> namedParameters() throws GeneralSecurityException {
133         Map<String, Parameters> result = new HashMap<>();
134         result.put(
135             "RSA_SSA_PSS_3072_SHA256_F4",
136             RsaSsaPssParameters.builder()
137                 .setSigHashType(RsaSsaPssParameters.HashType.SHA256)
138                 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256)
139                 .setSaltLengthBytes(32)
140                 .setModulusSizeBits(3072)
141                 .setPublicExponent(RsaSsaPssParameters.F4)
142                 .setVariant(RsaSsaPssParameters.Variant.TINK)
143                 .build());
144         result.put(
145             "RSA_SSA_PSS_3072_SHA256_F4_RAW",
146             RsaSsaPssParameters.builder()
147                 .setSigHashType(RsaSsaPssParameters.HashType.SHA256)
148                 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256)
149                 .setSaltLengthBytes(32)
150                 .setModulusSizeBits(3072)
151                 .setPublicExponent(RsaSsaPssParameters.F4)
152                 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX)
153                 .build());
154         // This is identical to RSA_SSA_PSS_3072_SHA256_F4. It is needed to maintain backward
155         // compatibility with SignatureKeyTemplates.
156         result.put(
157             "RSA_SSA_PSS_3072_SHA256_SHA256_32_F4",
158             PredefinedSignatureParameters.RSA_SSA_PSS_3072_SHA256_SHA256_32_F4);
159         result.put(
160             "RSA_SSA_PSS_4096_SHA512_F4",
161             RsaSsaPssParameters.builder()
162                 .setSigHashType(RsaSsaPssParameters.HashType.SHA512)
163                 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA512)
164                 .setSaltLengthBytes(64)
165                 .setModulusSizeBits(4096)
166                 .setPublicExponent(RsaSsaPssParameters.F4)
167                 .setVariant(RsaSsaPssParameters.Variant.TINK)
168                 .build());
169         result.put(
170             "RSA_SSA_PSS_4096_SHA512_F4_RAW",
171             RsaSsaPssParameters.builder()
172                 .setSigHashType(RsaSsaPssParameters.HashType.SHA512)
173                 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA512)
174                 .setSaltLengthBytes(64)
175                 .setModulusSizeBits(4096)
176                 .setPublicExponent(RsaSsaPssParameters.F4)
177                 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX)
178                 .build());
179         // This is identical to RSA_SSA_PSS_4096_SHA512_F4. It is needed to maintain backward
180         // compatibility with SignatureKeyTemplates.
181         result.put(
182             "RSA_SSA_PSS_4096_SHA512_SHA512_64_F4",
183             PredefinedSignatureParameters.RSA_SSA_PSS_4096_SHA512_SHA512_64_F4);
184         return Collections.unmodifiableMap(result);
185   }
186 
187   private static final TinkFipsUtil.AlgorithmFipsCompatibility FIPS =
188       TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_REQUIRES_BORINGCRYPTO;
189 
190   /**
191    * Registers the {@link RsaSsaPssSignKeyManager} and the {@link RsaSsaPssVerifyKeyManager} with
192    * the registry, so that the the RsaSsaPss-Keys can be used with Tink.
193    */
registerPair(boolean newKeyAllowed)194   public static void registerPair(boolean newKeyAllowed) throws GeneralSecurityException {
195     if (!FIPS.isCompatible()) {
196       throw new GeneralSecurityException(
197           "Can not use RSA SSA PSS in FIPS-mode, as BoringCrypto module is not available.");
198     }
199     RsaSsaPssProtoSerialization.register();
200     MutableParametersRegistry.globalInstance().putAll(namedParameters());
201     MutablePrimitiveRegistry.globalInstance()
202         .registerPrimitiveConstructor(PUBLIC_KEY_SIGN_PRIMITIVE_CONSTRUCTOR);
203     MutablePrimitiveRegistry.globalInstance()
204         .registerPrimitiveConstructor(PUBLIC_KEY_VERIFY_PRIMITIVE_CONSTRUCTOR);
205     MutableKeyCreationRegistry.globalInstance().add(KEY_CREATOR, RsaSsaPssParameters.class);
206     KeyManagerRegistry.globalInstance()
207         .registerKeyManagerWithFipsCompatibility(legacyPrivateKeyManager, FIPS, newKeyAllowed);
208     KeyManagerRegistry.globalInstance()
209         .registerKeyManagerWithFipsCompatibility(legacyPublicKeyManager, FIPS, false);
210   }
211 
212   /**
213    * @return A {@link KeyTemplate} that generates new instances of RSA-SSA-PSS key pairs with the
214    *     following parameters:
215    *     <ul>
216    *       <li>Signature hash: SHA256.
217    *       <li>MGF1 hash: SHA256.
218    *       <li>Salt length: 32 (i.e., SHA256's output length).
219    *       <li>Modulus size: 3072 bit.
220    *       <li>Public exponent: 65537 (aka F4).
221    *       <li>Prefix type: {@link KeyTemplate.OutputPrefixType#TINK}.
222    *     </ul>
223    */
rsa3072PssSha256F4Template()224   public static final KeyTemplate rsa3072PssSha256F4Template() {
225     return exceptionIsBug(
226         () ->
227             KeyTemplate.createFrom(
228                 RsaSsaPssParameters.builder()
229                     .setSigHashType(RsaSsaPssParameters.HashType.SHA256)
230                     .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256)
231                     .setSaltLengthBytes(32)
232                     .setModulusSizeBits(3072)
233                     .setPublicExponent(RsaSsaPssParameters.F4)
234                     .setVariant(RsaSsaPssParameters.Variant.TINK)
235                     .build()));
236   }
237   /**
238    * @return A {@link KeyTemplate} that generates new instances of RSA-SSA-PSS key pairs with the
239    *     following parameters:
240    *     <ul>
241    *       <li>Signature hash: SHA256.
242    *       <li>MGF1 hash: SHA256.
243    *       <li>Salt length: 32 (i.e., SHA256's output length).
244    *       <li>Modulus size: 3072 bit.
245    *       <li>Public exponent: 65537 (aka F4).
246    *       <li>Prefix type: {@link KeyTemplate.OutputPrefixType#RAW} (no prefix).
247    *     </ul>
248    *     <p>Keys generated from this template create signatures compatible with OpenSSL and other
249    *     libraries.
250    */
rawRsa3072PssSha256F4Template()251   public static final KeyTemplate rawRsa3072PssSha256F4Template() {
252     return exceptionIsBug(
253         () ->
254             KeyTemplate.createFrom(
255                 RsaSsaPssParameters.builder()
256                     .setSigHashType(RsaSsaPssParameters.HashType.SHA256)
257                     .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256)
258                     .setSaltLengthBytes(32)
259                     .setModulusSizeBits(3072)
260                     .setPublicExponent(RsaSsaPssParameters.F4)
261                     .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX)
262                     .build()));
263   }
264 
265   /**
266    * @return A {@link KeyTemplate} that generates new instances of RSA-SSA-PSS key pairs with the
267    *     following parameters:
268    *     <ul>
269    *       <li>Signature hash: SHA512.
270    *       <li>MGF1 hash: SHA512.
271    *       <li>Salt length: 64 (i.e., SHA512's output length).
272    *       <li>Modulus size: 4096 bit.
273    *       <li>Public exponent: 65537 (aka F4).
274    *       <li>Prefix type: {@link KeyTemplate.OutputPrefixType#TINK}.
275    *     </ul>
276    */
rsa4096PssSha512F4Template()277   public static final KeyTemplate rsa4096PssSha512F4Template() {
278     return exceptionIsBug(
279         () ->
280             KeyTemplate.createFrom(
281                 RsaSsaPssParameters.builder()
282                     .setSigHashType(RsaSsaPssParameters.HashType.SHA512)
283                     .setMgf1HashType(RsaSsaPssParameters.HashType.SHA512)
284                     .setSaltLengthBytes(64)
285                     .setModulusSizeBits(4096)
286                     .setPublicExponent(RsaSsaPssParameters.F4)
287                     .setVariant(RsaSsaPssParameters.Variant.TINK)
288                     .build()));
289   }
290 
291   /**
292    * @return A {@link KeyTemplate} that generates new instances of RSA-SSA-PSS key pairs with the
293    *     following parameters:
294    *     <ul>
295    *       <li>Signature hash: SHA512.
296    *       <li>MGF1 hash: SHA512.
297    *       <li>Salt length: 64 (i.e., SHA512's output length).
298    *       <li>Modulus size: 4096 bit.
299    *       <li>Public exponent: 65537 (aka F4).
300    *       <li>Prefix type: {@link KeyTemplate.OutputPrefixType#RAW} (no prefix).
301    *     </ul>
302    *     <p>Keys generated from this template create signatures compatible with OpenSSL and other
303    *     libraries.
304    */
rawRsa4096PssSha512F4Template()305   public static final KeyTemplate rawRsa4096PssSha512F4Template() {
306     return exceptionIsBug(
307         () ->
308             KeyTemplate.createFrom(
309                 RsaSsaPssParameters.builder()
310                     .setSigHashType(RsaSsaPssParameters.HashType.SHA512)
311                     .setMgf1HashType(RsaSsaPssParameters.HashType.SHA512)
312                     .setSaltLengthBytes(64)
313                     .setModulusSizeBits(4096)
314                     .setPublicExponent(RsaSsaPssParameters.F4)
315                     .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX)
316                     .build()));
317   }
318 
RsaSsaPssSignKeyManager()319   private RsaSsaPssSignKeyManager() {}
320 }
321