• 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.RsaSsaPkcs1ProtoSerialization;
38 import com.google.crypto.tink.subtle.EngineFactory;
39 import com.google.crypto.tink.subtle.RsaSsaPkcs1SignJce;
40 import com.google.crypto.tink.subtle.RsaSsaPkcs1VerifyJce;
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.HashMap;
50 import java.util.Map;
51 import javax.annotation.Nullable;
52 
53 /**
54  * This key manager generates new {@code RsaSsaPkcs1PrivateKey} keys and produces new instances of
55  * {@code RsaSsaPkcs1SignJce}.
56  */
57 public final class RsaSsaPkcs1SignKeyManager {
58   private static final PrimitiveConstructor<RsaSsaPkcs1PrivateKey, PublicKeySign>
59       PUBLIC_KEY_SIGN_PRIMITIVE_CONSTRUCTOR =
60           PrimitiveConstructor.create(
61               RsaSsaPkcs1SignJce::create, RsaSsaPkcs1PrivateKey.class, PublicKeySign.class);
62 
63   private static final PrimitiveConstructor<RsaSsaPkcs1PublicKey, PublicKeyVerify>
64       PUBLIC_KEY_VERIFY_PRIMITIVE_CONSTRUCTOR =
65           PrimitiveConstructor.create(
66               RsaSsaPkcs1VerifyJce::create, RsaSsaPkcs1PublicKey.class, PublicKeyVerify.class);
67 
68   private static final PrivateKeyManager<PublicKeySign> legacyPrivateKeyManager =
69       LegacyKeyManagerImpl.createPrivateKeyManager(
70           getKeyType(),
71           PublicKeySign.class,
72           com.google.crypto.tink.proto.RsaSsaPkcs1PrivateKey.parser());
73 
74   private static final KeyManager<PublicKeyVerify> legacyPublicKeyManager =
75       LegacyKeyManagerImpl.create(
76           RsaSsaPkcs1VerifyKeyManager.getKeyType(),
77           PublicKeyVerify.class,
78           KeyMaterialType.ASYMMETRIC_PUBLIC,
79           com.google.crypto.tink.proto.RsaSsaPkcs1PublicKey.parser());
80 
getKeyType()81   static String getKeyType() {
82     return "type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PrivateKey";
83   }
84 
85   @AccessesPartialKey
createKey( RsaSsaPkcs1Parameters parameters, @Nullable Integer idRequirement)86   private static RsaSsaPkcs1PrivateKey createKey(
87       RsaSsaPkcs1Parameters parameters, @Nullable Integer idRequirement)
88       throws GeneralSecurityException {
89         KeyPairGenerator keyGen = EngineFactory.KEY_PAIR_GENERATOR.getInstance("RSA");
90     RSAKeyGenParameterSpec spec =
91         new RSAKeyGenParameterSpec(
92             parameters.getModulusSizeBits(),
93             new BigInteger(1, parameters.getPublicExponent().toByteArray()));
94     keyGen.initialize(spec);
95     KeyPair keyPair = keyGen.generateKeyPair();
96     RSAPublicKey pubKey = (RSAPublicKey) keyPair.getPublic();
97     RSAPrivateCrtKey privKey = (RSAPrivateCrtKey) keyPair.getPrivate();
98 
99     // Creates RsaSsaPkcs1PublicKey.
100     RsaSsaPkcs1PublicKey rsaSsaPkcs1PublicKey =
101         RsaSsaPkcs1PublicKey.builder()
102             .setParameters(parameters)
103             .setModulus(pubKey.getModulus())
104             .setIdRequirement(idRequirement)
105             .build();
106 
107     // Creates RsaSsaPkcs1PrivateKey.
108     return RsaSsaPkcs1PrivateKey.builder()
109         .setPublicKey(rsaSsaPkcs1PublicKey)
110         .setPrimes(
111             SecretBigInteger.fromBigInteger(privKey.getPrimeP(), InsecureSecretKeyAccess.get()),
112             SecretBigInteger.fromBigInteger(privKey.getPrimeQ(), InsecureSecretKeyAccess.get()))
113         .setPrivateExponent(
114             SecretBigInteger.fromBigInteger(
115                 privKey.getPrivateExponent(), InsecureSecretKeyAccess.get()))
116         .setPrimeExponents(
117             SecretBigInteger.fromBigInteger(
118                 privKey.getPrimeExponentP(), InsecureSecretKeyAccess.get()),
119             SecretBigInteger.fromBigInteger(
120                 privKey.getPrimeExponentQ(), InsecureSecretKeyAccess.get()))
121         .setCrtCoefficient(
122             SecretBigInteger.fromBigInteger(
123                 privKey.getCrtCoefficient(), InsecureSecretKeyAccess.get()))
124         .build();
125   }
126 
127   @SuppressWarnings("InlineLambdaConstant") // We need a correct Object#equals in registration.
128   private static final MutableKeyCreationRegistry.KeyCreator<RsaSsaPkcs1Parameters> KEY_CREATOR =
129       RsaSsaPkcs1SignKeyManager::createKey;
130 
namedParameters()131   private static Map<String, Parameters> namedParameters() throws GeneralSecurityException {
132     Map<String, Parameters> result = new HashMap<>();
133     result.put(
134         "RSA_SSA_PKCS1_3072_SHA256_F4", PredefinedSignatureParameters.RSA_SSA_PKCS1_3072_SHA256_F4);
135     result.put(
136         "RSA_SSA_PKCS1_3072_SHA256_F4_RAW",
137         RsaSsaPkcs1Parameters.builder()
138             .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
139             .setModulusSizeBits(3072)
140             .setPublicExponent(RsaSsaPkcs1Parameters.F4)
141             .setVariant(RsaSsaPkcs1Parameters.Variant.NO_PREFIX)
142             .build());
143     // This is identical to RSA_SSA_PKCS1_3072_SHA256_F4_RAW. It is needed to maintain backward
144     // compatibility with SignatureKeyTemplates.
145     result.put(
146         "RSA_SSA_PKCS1_3072_SHA256_F4_WITHOUT_PREFIX",
147         PredefinedSignatureParameters.RSA_SSA_PKCS1_3072_SHA256_F4_WITHOUT_PREFIX);
148     result.put(
149         "RSA_SSA_PKCS1_4096_SHA512_F4", PredefinedSignatureParameters.RSA_SSA_PKCS1_4096_SHA512_F4);
150     result.put(
151         "RSA_SSA_PKCS1_4096_SHA512_F4_RAW",
152         RsaSsaPkcs1Parameters.builder()
153             .setHashType(RsaSsaPkcs1Parameters.HashType.SHA512)
154             .setModulusSizeBits(4096)
155             .setPublicExponent(RsaSsaPkcs1Parameters.F4)
156             .setVariant(RsaSsaPkcs1Parameters.Variant.NO_PREFIX)
157             .build());
158     return result;
159   }
160 
161   private static final TinkFipsUtil.AlgorithmFipsCompatibility FIPS =
162       TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_REQUIRES_BORINGCRYPTO;
163 
164   /**
165    * Registers the {@link RsaSsaPkcs1SignKeyManager} and the {@link RsaSsaPkcs1VerifyKeyManager}
166    * with the registry, so that the the RsaSsaPkcs1-Keys can be used with Tink.
167    */
registerPair(boolean newKeyAllowed)168   public static void registerPair(boolean newKeyAllowed) throws GeneralSecurityException {
169     if (!FIPS.isCompatible()) {
170       throw new GeneralSecurityException(
171           "Can not use RSA SSA PKCS1 in FIPS-mode, as BoringCrypto module is not available.");
172     }
173     RsaSsaPkcs1ProtoSerialization.register();
174     MutableParametersRegistry.globalInstance().putAll(namedParameters());
175     MutablePrimitiveRegistry.globalInstance()
176         .registerPrimitiveConstructor(PUBLIC_KEY_SIGN_PRIMITIVE_CONSTRUCTOR);
177     MutablePrimitiveRegistry.globalInstance()
178         .registerPrimitiveConstructor(PUBLIC_KEY_VERIFY_PRIMITIVE_CONSTRUCTOR);
179     MutableKeyCreationRegistry.globalInstance().add(KEY_CREATOR, RsaSsaPkcs1Parameters.class);
180     KeyManagerRegistry.globalInstance()
181         .registerKeyManagerWithFipsCompatibility(legacyPrivateKeyManager, FIPS, newKeyAllowed);
182     KeyManagerRegistry.globalInstance()
183         .registerKeyManagerWithFipsCompatibility(legacyPublicKeyManager, FIPS, false);
184   }
185 
186   /**
187    * @return A {@link KeyTemplate} that generates new instances of RSA-SSA-PKCS1 key pairs with the
188    *     following parameters:
189    *     <ul>
190    *       <li>Hash function: SHA256.
191    *       <li>Modulus size: 3072 bit.
192    *       <li>Public exponent: 65537 (aka F4).
193    *       <li>Prefix type: {@link KeyTemplate.OutputPrefixType#TINK}.
194    *     </ul>
195    */
rsa3072SsaPkcs1Sha256F4Template()196   public static final KeyTemplate rsa3072SsaPkcs1Sha256F4Template() {
197     return exceptionIsBug(
198         () ->
199             KeyTemplate.createFrom(
200                 RsaSsaPkcs1Parameters.builder()
201                     .setModulusSizeBits(3072)
202                     .setPublicExponent(RsaSsaPkcs1Parameters.F4)
203                     .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
204                     .setVariant(RsaSsaPkcs1Parameters.Variant.TINK)
205                     .build()));
206   }
207 
208   /**
209    * @return A {@link KeyTemplate} that generates new instances of RSA-SSA-PKCS1 key pairs with the
210    *     following parameters:
211    *     <ul>
212    *       <li>Hash function: SHA256.
213    *       <li>Modulus size: 3072 bit.
214    *       <li>Public exponent: 65537 (aka F4).
215    *       <li>Prefix type: {@link KeyTemplate.OutputPrefixType#RAW} (no prefix).
216    *     </ul>
217    */
rawRsa3072SsaPkcs1Sha256F4Template()218   public static final KeyTemplate rawRsa3072SsaPkcs1Sha256F4Template() {
219     return exceptionIsBug(
220         () ->
221             KeyTemplate.createFrom(
222                 RsaSsaPkcs1Parameters.builder()
223                     .setModulusSizeBits(3072)
224                     .setPublicExponent(RsaSsaPkcs1Parameters.F4)
225                     .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
226                     .setVariant(RsaSsaPkcs1Parameters.Variant.NO_PREFIX)
227                     .build()));
228   }
229 
230   /**
231    * @return A {@link KeyTemplate} that generates new instances of RSA-SSA-PKCS1 key pairs with the
232    *     following parameters:
233    *     <ul>
234    *       <li>Hash function: SHA512.
235    *       <li>Modulus size: 4096 bit.
236    *       <li>Public exponent: 65537 (aka F4).
237    *       <li>Prefix type: {@link KeyTemplate.OutputPrefixType#TINK}.
238    *     </ul>
239    */
rsa4096SsaPkcs1Sha512F4Template()240   public static final KeyTemplate rsa4096SsaPkcs1Sha512F4Template() {
241     return exceptionIsBug(
242         () ->
243             KeyTemplate.createFrom(
244                 RsaSsaPkcs1Parameters.builder()
245                     .setModulusSizeBits(4096)
246                     .setPublicExponent(RsaSsaPkcs1Parameters.F4)
247                     .setHashType(RsaSsaPkcs1Parameters.HashType.SHA512)
248                     .setVariant(RsaSsaPkcs1Parameters.Variant.TINK)
249                     .build()));
250   }
251 
252   /**
253    * @return A {@link KeyTemplate} that generates new instances of RSA-SSA-PKCS1 key pairs with the
254    *     following parameters:
255    *     <ul>
256    *       <li>Hash function: SHA512.
257    *       <li>Modulus size: 4096 bit.
258    *       <li>Public exponent: 65537 (aka F4).
259    *       <li>Prefix type: {@link KeyTemplate.OutputPrefixType#RAW} (no prefix).
260    *     </ul>
261    */
rawRsa4096SsaPkcs1Sha512F4Template()262   public static final KeyTemplate rawRsa4096SsaPkcs1Sha512F4Template() {
263     return exceptionIsBug(
264         () ->
265             KeyTemplate.createFrom(
266                 RsaSsaPkcs1Parameters.builder()
267                     .setModulusSizeBits(4096)
268                     .setPublicExponent(RsaSsaPkcs1Parameters.F4)
269                     .setHashType(RsaSsaPkcs1Parameters.HashType.SHA512)
270                     .setVariant(RsaSsaPkcs1Parameters.Variant.NO_PREFIX)
271                     .build()));
272   }
273 
RsaSsaPkcs1SignKeyManager()274   private RsaSsaPkcs1SignKeyManager() {}
275 }
276