RandomPrivateKeyX509ExtendedKeyManager.java revision 0669a8cf8b08b2d66a7ff758e5e3dbd456855495
1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package libcore.javax.net.ssl;
18
19import junit.framework.Assert;
20import java.security.GeneralSecurityException;
21import java.security.KeyFactory;
22import java.security.KeyPairGenerator;
23import java.security.PrivateKey;
24import java.security.spec.DSAParameterSpec;
25import java.security.spec.DSAPrivateKeySpec;
26import java.security.spec.RSAPrivateKeySpec;
27import java.util.HashMap;
28import java.util.Map;
29import javax.net.ssl.X509ExtendedKeyManager;
30
31/**
32 * {@link X509ExtendedKeyManager} which forwards all calls to a delegate while substituting
33 * the returned private key with its own randomly generated keys of the same type (and parameters).
34 */
35public class RandomPrivateKeyX509ExtendedKeyManager extends ForwardingX509ExtendedKeyManager {
36
37  private final Map<String, PrivateKey> cachedKeys = new HashMap<String, PrivateKey>();
38
39  public RandomPrivateKeyX509ExtendedKeyManager(X509ExtendedKeyManager delegate) {
40    super(delegate);
41  }
42
43  @Override
44  public PrivateKey getPrivateKey(String alias) {
45    PrivateKey originalPrivateKey = super.getPrivateKey(alias);
46    if (originalPrivateKey == null) {
47      return null;
48    }
49
50    PrivateKey result;
51    String keyAlgorithm = originalPrivateKey.getAlgorithm();
52    try {
53      KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm);
54      if ("RSA".equals(keyAlgorithm)) {
55        RSAPrivateKeySpec originalKeySpec =
56            keyFactory.getKeySpec(originalPrivateKey, RSAPrivateKeySpec.class);
57        int keyLengthBits = originalKeySpec.getModulus().bitLength();
58        // Use a cache because RSA key generation is slow.
59        String cacheKey = keyAlgorithm + "-" + keyLengthBits;
60        result = cachedKeys.get(cacheKey);
61        if (result == null) {
62          KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(keyAlgorithm);
63          keyPairGenerator.initialize(keyLengthBits);
64          result = keyPairGenerator.generateKeyPair().getPrivate();
65          cachedKeys.put(cacheKey, result);
66        }
67      } else if ("DSA".equals(keyAlgorithm)) {
68        DSAPrivateKeySpec originalKeySpec =
69            keyFactory.getKeySpec(originalPrivateKey, DSAPrivateKeySpec.class);
70        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(keyAlgorithm);
71        keyPairGenerator.initialize(new DSAParameterSpec(
72            originalKeySpec.getP(), originalKeySpec.getQ(), originalKeySpec.getG()));
73        result = keyPairGenerator.generateKeyPair().getPrivate();
74      } else {
75        Assert.fail("Unsupported key algorithm: " + originalPrivateKey.getAlgorithm());
76        result = null;
77      }
78    } catch (GeneralSecurityException e) {
79      Assert.fail("Failed to generate private key: " + e);
80      result = null;
81    }
82
83    return result;
84  }
85}
86