OSDN Git Service

android-2.1_r1 snapshot
[android-x86/sdk.git] / jarutils / src / com / android / jarutils / DebugKeyProvider.java
1 /*
2  * Copyright (C) 2008 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
17 package com.android.jarutils;
18
19 import com.android.prefs.AndroidLocation;
20 import com.android.prefs.AndroidLocation.AndroidLocationException;
21
22 import java.io.FileInputStream;
23 import java.io.FileNotFoundException;
24 import java.io.IOException;
25 import java.security.KeyStore;
26 import java.security.KeyStoreException;
27 import java.security.NoSuchAlgorithmException;
28 import java.security.PrivateKey;
29 import java.security.UnrecoverableEntryException;
30 import java.security.UnrecoverableKeyException;
31 import java.security.cert.Certificate;
32 import java.security.cert.CertificateException;
33
34 /**
35  * A provider of a dummy key to sign Android application for debugging purpose.
36  * <p/>This provider uses a custom keystore to create and store a key with a known password.
37  */
38 public class DebugKeyProvider {
39     
40     public interface IKeyGenOutput {
41         public void out(String message);
42         public void err(String message);
43     }
44     
45     private static final String PASSWORD_STRING = "android";
46     private static final char[] PASSWORD_CHAR = PASSWORD_STRING.toCharArray();
47     private static final String DEBUG_ALIAS = "AndroidDebugKey";
48     
49     // Certificate CN value. This is a hard-coded value for the debug key.
50     // Android Market checks against this value in order to refuse applications signed with
51     // debug keys.
52     private static final String CERTIFICATE_DESC = "CN=Android Debug,O=Android,C=US";
53     
54     private KeyStore.PrivateKeyEntry mEntry;
55     
56     public static class KeytoolException extends Exception {
57         /** default serial uid */
58         private static final long serialVersionUID = 1L;
59         private String mJavaHome = null;
60         private String mCommandLine = null;
61         
62         KeytoolException(String message) {
63             super(message);
64         }
65
66         KeytoolException(String message, String javaHome, String commandLine) {
67             super(message);
68             
69             mJavaHome = javaHome;
70             mCommandLine = commandLine;
71         }
72         
73         public String getJavaHome() {
74             return mJavaHome;
75         }
76         
77         public String getCommandLine() {
78             return mCommandLine;
79         }
80     }
81     
82     /**
83      * Creates a provider using a keystore at the given location.
84      * <p/>The keystore, and a new random android debug key are created if they do not yet exist.
85      * <p/>Password for the store/key is <code>android</code>, and the key alias is
86      * <code>AndroidDebugKey</code>.
87      * @param osKeyStorePath the OS path to the keystore, or <code>null</code> if the default one
88      * is to be used.
89      * @param storeType an optional keystore type, or <code>null</code> if the default is to
90      * be used.
91      * @param output an optional {@link IKeyGenOutput} object to get the stdout and stderr
92      * of the keytool process call.
93      * @throws KeytoolException If the creation of the debug key failed.
94      * @throws AndroidLocationException 
95      */
96     public DebugKeyProvider(String osKeyStorePath, String storeType, IKeyGenOutput output)
97             throws KeyStoreException, NoSuchAlgorithmException, CertificateException,
98             UnrecoverableEntryException, IOException, KeytoolException, AndroidLocationException {
99         
100         if (osKeyStorePath == null) {
101             osKeyStorePath = getDefaultKeyStoreOsPath();
102         }
103         
104         if (loadKeyEntry(osKeyStorePath, storeType) == false) {
105             // create the store with the key
106             createNewStore(osKeyStorePath, storeType, output);
107         }
108     }
109
110     /**
111      * Returns the OS path to the default debug keystore.
112      * 
113      * @return The OS path to the default debug keystore.
114      * @throws KeytoolException
115      * @throws AndroidLocationException
116      */
117     public static String getDefaultKeyStoreOsPath()
118             throws KeytoolException, AndroidLocationException {
119         String folder = AndroidLocation.getFolder();
120         if (folder == null) {
121             throw new KeytoolException("Failed to get HOME directory!\n");
122         }
123         String osKeyStorePath = folder + "debug.keystore";
124
125         return osKeyStorePath;
126     }
127
128     /**
129      * Returns the debug {@link PrivateKey} to use to sign applications for debug purpose.
130      * @return the private key or <code>null</code> if its creation failed.
131      */
132     public PrivateKey getDebugKey() throws KeyStoreException, NoSuchAlgorithmException,
133             UnrecoverableKeyException, UnrecoverableEntryException {
134         if (mEntry != null) {
135             return mEntry.getPrivateKey();
136         }
137         
138         return null;
139     }
140
141     /**
142      * Returns the debug {@link Certificate} to use to sign applications for debug purpose.
143      * @return the certificate or <code>null</code> if its creation failed.
144      */
145     public Certificate getCertificate() throws KeyStoreException, NoSuchAlgorithmException,
146             UnrecoverableKeyException, UnrecoverableEntryException {
147         if (mEntry != null) {
148             return mEntry.getCertificate();
149         }
150
151         return null;
152     }
153     
154     /**
155      * Loads the debug key from the keystore.
156      * @param osKeyStorePath the OS path to the keystore.
157      * @param storeType an optional keystore type, or <code>null</code> if the default is to
158      * be used.
159      * @return <code>true</code> if success, <code>false</code> if the keystore does not exist.
160      */
161     private boolean loadKeyEntry(String osKeyStorePath, String storeType) throws KeyStoreException,
162             NoSuchAlgorithmException, CertificateException, IOException,
163             UnrecoverableEntryException {
164         try {
165             KeyStore keyStore = KeyStore.getInstance(
166                     storeType != null ? storeType : KeyStore.getDefaultType());
167             FileInputStream fis = new FileInputStream(osKeyStorePath);
168             keyStore.load(fis, PASSWORD_CHAR);
169             fis.close();
170             mEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(
171                     DEBUG_ALIAS, new KeyStore.PasswordProtection(PASSWORD_CHAR));
172         } catch (FileNotFoundException e) {
173             return false;
174         }
175         
176         return true;
177     }
178
179     /**
180      * Creates a new store
181      * @param osKeyStorePath the location of the store
182      * @param storeType an optional keystore type, or <code>null</code> if the default is to
183      * be used.
184      * @param output an optional {@link IKeyGenOutput} object to get the stdout and stderr
185      * of the keytool process call.
186      * @throws KeyStoreException
187      * @throws NoSuchAlgorithmException
188      * @throws CertificateException
189      * @throws UnrecoverableEntryException
190      * @throws IOException
191      * @throws KeytoolException
192      */
193     private void createNewStore(String osKeyStorePath, String storeType, IKeyGenOutput output)
194             throws KeyStoreException, NoSuchAlgorithmException, CertificateException,
195             UnrecoverableEntryException, IOException, KeytoolException {
196         
197         if (KeystoreHelper.createNewStore(osKeyStorePath, storeType, PASSWORD_STRING, DEBUG_ALIAS,
198                 PASSWORD_STRING, CERTIFICATE_DESC, 1 /* validity*/, output)) {
199             loadKeyEntry(osKeyStorePath, storeType);
200         }
201     }
202 }