OSDN Git Service

original
[gb-231r1-is01/GB_2.3_IS01.git] / sdk / sdkmanager / libs / sdklib / src / com / android / sdklib / internal / build / DebugKeyProvider.java
diff --git a/sdk/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/build/DebugKeyProvider.java b/sdk/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/build/DebugKeyProvider.java
new file mode 100644 (file)
index 0000000..bef7ccf
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.sdklib.internal.build;
+
+import com.android.prefs.AndroidLocation;
+import com.android.prefs.AndroidLocation.AndroidLocationException;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.UnrecoverableEntryException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+
+/**
+ * A provider of a dummy key to sign Android application for debugging purpose.
+ * <p/>This provider uses a custom keystore to create and store a key with a known password.
+ */
+public class DebugKeyProvider {
+    
+    public interface IKeyGenOutput {
+        public void out(String message);
+        public void err(String message);
+    }
+    
+    private static final String PASSWORD_STRING = "android";
+    private static final char[] PASSWORD_CHAR = PASSWORD_STRING.toCharArray();
+    private static final String DEBUG_ALIAS = "AndroidDebugKey";
+    
+    // Certificate CN value. This is a hard-coded value for the debug key.
+    // Android Market checks against this value in order to refuse applications signed with
+    // debug keys.
+    private static final String CERTIFICATE_DESC = "CN=Android Debug,O=Android,C=US";
+    
+    private KeyStore.PrivateKeyEntry mEntry;
+    
+    public static class KeytoolException extends Exception {
+        /** default serial uid */
+        private static final long serialVersionUID = 1L;
+        private String mJavaHome = null;
+        private String mCommandLine = null;
+        
+        KeytoolException(String message) {
+            super(message);
+        }
+
+        KeytoolException(String message, String javaHome, String commandLine) {
+            super(message);
+            
+            mJavaHome = javaHome;
+            mCommandLine = commandLine;
+        }
+        
+        public String getJavaHome() {
+            return mJavaHome;
+        }
+        
+        public String getCommandLine() {
+            return mCommandLine;
+        }
+    }
+    
+    /**
+     * Creates a provider using a keystore at the given location.
+     * <p/>The keystore, and a new random android debug key are created if they do not yet exist.
+     * <p/>Password for the store/key is <code>android</code>, and the key alias is
+     * <code>AndroidDebugKey</code>.
+     * @param osKeyStorePath the OS path to the keystore, or <code>null</code> if the default one
+     * is to be used.
+     * @param storeType an optional keystore type, or <code>null</code> if the default is to
+     * be used.
+     * @param output an optional {@link IKeyGenOutput} object to get the stdout and stderr
+     * of the keytool process call.
+     * @throws KeytoolException If the creation of the debug key failed.
+     * @throws AndroidLocationException 
+     */
+    public DebugKeyProvider(String osKeyStorePath, String storeType, IKeyGenOutput output)
+            throws KeyStoreException, NoSuchAlgorithmException, CertificateException,
+            UnrecoverableEntryException, IOException, KeytoolException, AndroidLocationException {
+        
+        if (osKeyStorePath == null) {
+            osKeyStorePath = getDefaultKeyStoreOsPath();
+        }
+        
+        if (loadKeyEntry(osKeyStorePath, storeType) == false) {
+            // create the store with the key
+            createNewStore(osKeyStorePath, storeType, output);
+        }
+    }
+
+    /**
+     * Returns the OS path to the default debug keystore.
+     * 
+     * @return The OS path to the default debug keystore.
+     * @throws KeytoolException
+     * @throws AndroidLocationException
+     */
+    public static String getDefaultKeyStoreOsPath()
+            throws KeytoolException, AndroidLocationException {
+        String folder = AndroidLocation.getFolder();
+        if (folder == null) {
+            throw new KeytoolException("Failed to get HOME directory!\n");
+        }
+        String osKeyStorePath = folder + "debug.keystore";
+
+        return osKeyStorePath;
+    }
+
+    /**
+     * Returns the debug {@link PrivateKey} to use to sign applications for debug purpose.
+     * @return the private key or <code>null</code> if its creation failed.
+     */
+    public PrivateKey getDebugKey() throws KeyStoreException, NoSuchAlgorithmException,
+            UnrecoverableKeyException, UnrecoverableEntryException {
+        if (mEntry != null) {
+            return mEntry.getPrivateKey();
+        }
+        
+        return null;
+    }
+
+    /**
+     * Returns the debug {@link Certificate} to use to sign applications for debug purpose.
+     * @return the certificate or <code>null</code> if its creation failed.
+     */
+    public Certificate getCertificate() throws KeyStoreException, NoSuchAlgorithmException,
+            UnrecoverableKeyException, UnrecoverableEntryException {
+        if (mEntry != null) {
+            return mEntry.getCertificate();
+        }
+
+        return null;
+    }
+    
+    /**
+     * Loads the debug key from the keystore.
+     * @param osKeyStorePath the OS path to the keystore.
+     * @param storeType an optional keystore type, or <code>null</code> if the default is to
+     * be used.
+     * @return <code>true</code> if success, <code>false</code> if the keystore does not exist.
+     */
+    private boolean loadKeyEntry(String osKeyStorePath, String storeType) throws KeyStoreException,
+            NoSuchAlgorithmException, CertificateException, IOException,
+            UnrecoverableEntryException {
+        try {
+            KeyStore keyStore = KeyStore.getInstance(
+                    storeType != null ? storeType : KeyStore.getDefaultType());
+            FileInputStream fis = new FileInputStream(osKeyStorePath);
+            keyStore.load(fis, PASSWORD_CHAR);
+            fis.close();
+            mEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(
+                    DEBUG_ALIAS, new KeyStore.PasswordProtection(PASSWORD_CHAR));
+        } catch (FileNotFoundException e) {
+            return false;
+        }
+        
+        return true;
+    }
+
+    /**
+     * Creates a new store
+     * @param osKeyStorePath the location of the store
+     * @param storeType an optional keystore type, or <code>null</code> if the default is to
+     * be used.
+     * @param output an optional {@link IKeyGenOutput} object to get the stdout and stderr
+     * of the keytool process call.
+     * @throws KeyStoreException
+     * @throws NoSuchAlgorithmException
+     * @throws CertificateException
+     * @throws UnrecoverableEntryException
+     * @throws IOException
+     * @throws KeytoolException
+     */
+    private void createNewStore(String osKeyStorePath, String storeType, IKeyGenOutput output)
+            throws KeyStoreException, NoSuchAlgorithmException, CertificateException,
+            UnrecoverableEntryException, IOException, KeytoolException {
+        
+        if (KeystoreHelper.createNewStore(osKeyStorePath, storeType, PASSWORD_STRING, DEBUG_ALIAS,
+                PASSWORD_STRING, CERTIFICATE_DESC, 1 /* validity*/, output)) {
+            loadKeyEntry(osKeyStorePath, storeType);
+        }
+    }
+}