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