在 android 中存储证书的正确方法及其将来的管理

Proper way to store certificates in android and their management in future

我有一个 .pfx a 和 .cer 证书。第一个用于签名数据,第二个用于打开 SSL。

我应该如何在 android 中存储证书?

我目前的做法:

        // Create Keystore containing servers certificate
        KeyStore keyStore = KeyStore.getInstance("BKS");

        // Different versions of Android use different BKSs
        // Need to export both versions using Portacle (1.9 worked for me)
        int bks_version;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            bks_version = R.raw.keystore; //The BKS file
        } else {
            bks_version = R.raw.keystorev1; //The BKS (v-1) file
        }

        keyStore.load(activity.getResources().openRawResource(bks_version), "password"); 

我写了一个 class 来管理我的证书,例如用于 SSL 和 PFX 的 CA 或用于个人签名的 P12。

我使用了内部存储并内置了 KeyStore。 如果你想知道我从哪里得到 PFX 的别名,你必须知道,我还没有找到更好的方法来处理 Android 中的这个问题。

public class CertificateManager {
private static final String CUSTOMER_CERTIFICATE_STORE = "CustomerKeyStore.keystore";
private static final String CUSTOMER_CERTIFICATE_ALIAS = "CZ1212121218";
private static final String CUSTOMER_KS_PASSWORD = "eet";

private static final String SERVER_CERTIFICATE_STORE = "ServerKeyStore.keystore";
private static final String SERVER_CERTIFICATE_ALIAS = "ca";
private static final String SERVER_KS_PASSWORD = "eet";

/**
 *  Get Customer's Keystore, containing personal certificate.
 * @param context
 * @return Customer's Keystore
 */
private static KeyStore getCustomerKeystore(Context context){
    try {
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        // Load Keystore form internal storage
        FileInputStream fis = context.openFileInput(CUSTOMER_CERTIFICATE_STORE);
        keyStore.load(fis, CUSTOMER_KS_PASSWORD.toCharArray());
        return  keyStore;
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException("Keystore not found.");
    }
}

/**
 * Get customer's certificate for signature.
 * @param context
 * @return Customer's certificate
 */
public static X509Certificate getCustomersCertificate(Context context){
    try {
        KeyStore keyStore= getCustomerKeystore(context);

        KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(
                        CUSTOMER_CERTIFICATE_ALIAS,
                        new KeyStore.PasswordProtection(CUSTOMER_KS_PASSWORD.toCharArray())
        );

        return  (X509Certificate) keyEntry.getCertificate();
    } catch (Exception e) {
        // Keystore not found ask user for uploading his certificate.
        e.printStackTrace();
        throw new RuntimeException("Wrong KeyStore");
    }
}

/**
 * Get customer's PrivateKey for encryption.
 * @param context
 * @return customer's PrivateKey
 */
public static PrivateKey getCustomersPrivateKey(Context context){
    try {
        KeyStore keyStore= getCustomerKeystore(context);

        //return customer's certificate
        return (PrivateKey)keyStore.getKey(CUSTOMER_CERTIFICATE_ALIAS, CUSTOMER_KS_PASSWORD.toCharArray());
    } catch (Exception e) {

        e.printStackTrace();
        throw new RuntimeException("Wrong KeyStore");
    }
}

/**
 * Loads Customer .p12 or .pfx certificate to keystore with password to Internal Storage
 * @param context
 * @return customer's PrivateKey
 */
public static void loadCustomerCertificate(Context context, InputStream inputStream) throws Exception{
    KeyStore keyStore = KeyStore.getInstance("pkcs12");
    keyStore.load(inputStream, CUSTOMER_KS_PASSWORD.toCharArray());

    //Save KeyStore in Internal Storage
    FileOutputStream fos = context.openFileOutput(CUSTOMER_CERTIFICATE_STORE, Context.MODE_PRIVATE);
    keyStore.store(fos, CUSTOMER_KS_PASSWORD.toCharArray());
    fos.close();
}

/**
 * Server certificate for SLL communication
 * @param context
 * @return HTTPS TrustStore
 */
public static KeyStore getServerKeystore(Context context){
    try {
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());

        // Load Keystore form internal storage
        FileInputStream fis = context.openFileInput(SERVER_CERTIFICATE_STORE);
        keyStore.load(fis, SERVER_KS_PASSWORD.toCharArray());
        return  keyStore;
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException("Keystore not found.");
    }
}

/**
 * Load Server certificate for SLL communication
 * @param context
 * @param inputStream server trusted CAs
 */
public static void loadServerKeystore(Context context, InputStream inputStream) throws Exception{
    // Load CAs from an InputStream
    CertificateFactory cf = CertificateFactory.getInstance("X.509");
    Certificate ca = cf.generateCertificate(inputStream);
    inputStream.close();

    // Create a KeyStore containing our trusted CAs
    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    keyStore.load(null, null);
    keyStore.setCertificateEntry(SERVER_CERTIFICATE_ALIAS, ca);

    // Save keystore to Internal Storage.
    FileOutputStream fos = context.openFileOutput(SERVER_CERTIFICATE_STORE, Context.MODE_PRIVATE);
    keyStore.store(fos, SERVER_KS_PASSWORD.toCharArray());
    fos.close();
}