在 android 中存储证书的正确方法及其将来的管理
Proper way to store certificates in android and their management in future
我有一个 .pfx a 和 .cer 证书。第一个用于签名数据,第二个用于打开 SSL。
我应该如何在 android 中存储证书?
- 我应该将它们放在 res/raw 的 Keystore 中还是资产中?
- 我应该将它们作为单个文件存储在 res/assets 中吗?
- 为了管理未来的变化,最有效的存储方式是什么?
我目前的做法:
// 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();
}
我有一个 .pfx a 和 .cer 证书。第一个用于签名数据,第二个用于打开 SSL。
我应该如何在 android 中存储证书?
- 我应该将它们放在 res/raw 的 Keystore 中还是资产中?
- 我应该将它们作为单个文件存储在 res/assets 中吗?
- 为了管理未来的变化,最有效的存储方式是什么?
我目前的做法:
// 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();
}