LocalRepoKeyStore move all creation logic to the constructor
This just makes the code clearer, and the get() method dead simple.
This commit is contained in:
parent
b7aad893a3
commit
d5488fc5f1
@ -2,6 +2,7 @@
|
|||||||
package org.fdroid.fdroid.localrepo;
|
package org.fdroid.fdroid.localrepo;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
import org.spongycastle.asn1.ASN1Sequence;
|
import org.spongycastle.asn1.ASN1Sequence;
|
||||||
@ -23,7 +24,6 @@ import java.security.cert.CertificateException;
|
|||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Formatter;
|
|
||||||
|
|
||||||
import javax.net.ssl.KeyManager;
|
import javax.net.ssl.KeyManager;
|
||||||
import javax.net.ssl.KeyManagerFactory;
|
import javax.net.ssl.KeyManagerFactory;
|
||||||
@ -53,79 +53,84 @@ public class LocalRepoKeyStore {
|
|||||||
private static LocalRepoKeyStore localRepoKeyStore;
|
private static LocalRepoKeyStore localRepoKeyStore;
|
||||||
private KeyStore keyStore;
|
private KeyStore keyStore;
|
||||||
private KeyManager[] keyManagers;
|
private KeyManager[] keyManagers;
|
||||||
private File backingFile;
|
private File keyStoreFile;
|
||||||
|
|
||||||
public static LocalRepoKeyStore get(Context context) {
|
public static LocalRepoKeyStore get(Context context) {
|
||||||
if (localRepoKeyStore == null) {
|
if (localRepoKeyStore == null)
|
||||||
File appKeyStoreDir = context.getDir("keystore", Context.MODE_PRIVATE);
|
localRepoKeyStore = new LocalRepoKeyStore(context);
|
||||||
File keyStoreFile = new File(appKeyStoreDir, "kerplapp.bks");
|
|
||||||
try {
|
|
||||||
localRepoKeyStore = new LocalRepoKeyStore(keyStoreFile);
|
|
||||||
} catch (UnrecoverableKeyException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (KeyStoreException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (CertificateException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (OperatorCreationException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return localRepoKeyStore;
|
return localRepoKeyStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LocalRepoKeyStore(File backingFile) throws KeyStoreException, NoSuchAlgorithmException,
|
private LocalRepoKeyStore(Context context) {
|
||||||
CertificateException, IOException, OperatorCreationException, UnrecoverableKeyException {
|
try {
|
||||||
this.backingFile = backingFile;
|
Log.d(TAG, "generating LocalRepoKeyStore instance");
|
||||||
this.keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
File appKeyStoreDir = context.getDir("keystore", Context.MODE_PRIVATE);
|
||||||
|
this.keyStoreFile = new File(appKeyStoreDir, "kerplapp.bks");
|
||||||
|
this.keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||||
|
|
||||||
// If there isn't a persisted BKS keystore on disk we need to
|
// If there isn't a persisted BKS keystore on disk we need to
|
||||||
// create a new empty keystore
|
// create a new empty keystore
|
||||||
if (!backingFile.exists()) {
|
if (!keyStoreFile.exists()) {
|
||||||
// Init a new keystore with a blank passphrase
|
// Init a new keystore with a blank passphrase
|
||||||
keyStore.load(null, "".toCharArray());
|
keyStore.load(null, "".toCharArray());
|
||||||
} else {
|
} else {
|
||||||
keyStore.load(new FileInputStream(backingFile), "".toCharArray());
|
keyStore.load(new FileInputStream(keyStoreFile), "".toCharArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the keystore we loaded doesn't have an INDEX_CERT_ALIAS entry
|
||||||
|
* we need to generate a new random keypair and a self signed
|
||||||
|
* certificate for this slot.
|
||||||
|
*/
|
||||||
|
if (keyStore.getKey(INDEX_CERT_ALIAS, "".toCharArray()) == null) {
|
||||||
|
/*
|
||||||
|
* Generate a random key pair to associate with the
|
||||||
|
* INDEX_CERT_ALIAS certificate in the keystore. This keypair
|
||||||
|
* will be used for the HTTPS cert as well.
|
||||||
|
*/
|
||||||
|
KeyPair rndKeys = generateRandomKeypair();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate a self signed certificate for signing the index.jar
|
||||||
|
* We can't generate the HTTPS certificate until we know what
|
||||||
|
* the IP address will be to use for the CN field.
|
||||||
|
*/
|
||||||
|
X500Name subject = new X500Name(DEFAULT_INDEX_CERT_INFO);
|
||||||
|
Certificate indexCert = generateSelfSignedCertChain(rndKeys, subject);
|
||||||
|
|
||||||
|
addToStore(INDEX_CERT_ALIAS, rndKeys, indexCert);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Kerplapp uses its own KeyManager to to ensure the correct
|
||||||
|
* keystore alias is used for the correct purpose. With the default
|
||||||
|
* key manager it is not possible to specify that HTTP_CERT_ALIAS
|
||||||
|
* should be used for TLS and INDEX_CERT_ALIAS for signing the
|
||||||
|
* index.jar.
|
||||||
|
*/
|
||||||
|
KeyManagerFactory keyManagerFactory = KeyManagerFactory
|
||||||
|
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||||
|
|
||||||
|
keyManagerFactory.init(keyStore, "".toCharArray());
|
||||||
|
KeyManager defaultKeyManager = keyManagerFactory.getKeyManagers()[0];
|
||||||
|
KeyManager wrappedKeyManager = new KerplappKeyManager(
|
||||||
|
(X509KeyManager) defaultKeyManager);
|
||||||
|
keyManagers = new KeyManager[] {
|
||||||
|
wrappedKeyManager
|
||||||
|
};
|
||||||
|
} catch (UnrecoverableKeyException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (KeyStoreException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (CertificateException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (OperatorCreationException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* If the keystore we loaded doesn't have an INDEX_CERT_ALIAS entry we
|
|
||||||
* need to generate a new random keypair and a self signed certificate
|
|
||||||
* for this slot.
|
|
||||||
*/
|
|
||||||
if (keyStore.getKey(INDEX_CERT_ALIAS, "".toCharArray()) == null) {
|
|
||||||
// Generate a random key pair to associate with the INDEX_CERT_ALIAS
|
|
||||||
// certificate in the keystore. This keypair will be used for the
|
|
||||||
// HTTPS cert as well.
|
|
||||||
KeyPair rndKeys = generateRandomKeypair();
|
|
||||||
|
|
||||||
// Generate a self signed certificate for signing the index.jar
|
|
||||||
// We can't generate the HTTPS certificate until we know what the IP
|
|
||||||
// address will be to use for the CN field.
|
|
||||||
X500Name subject = new X500Name(DEFAULT_INDEX_CERT_INFO);
|
|
||||||
Certificate indexCert = generateSelfSignedCertChain(rndKeys, subject);
|
|
||||||
|
|
||||||
addToStore(INDEX_CERT_ALIAS, rndKeys, indexCert);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kerplapp uses its own KeyManager to to ensure the correct keystore
|
|
||||||
// alias is used for the correct purpose. With the default key manager
|
|
||||||
// it is not possible to specify that HTTP_CERT_ALIAS should be used for
|
|
||||||
// TLS and INDEX_CERT_ALIAS for signing the index.jar.
|
|
||||||
KeyManagerFactory keyManagerFactory = KeyManagerFactory
|
|
||||||
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
|
||||||
|
|
||||||
keyManagerFactory.init(keyStore, "".toCharArray());
|
|
||||||
KeyManager defaultKeyManager = keyManagerFactory.getKeyManagers()[0];
|
|
||||||
KeyManager wrappedKeyManager = new KerplappKeyManager(
|
|
||||||
(X509KeyManager) defaultKeyManager);
|
|
||||||
keyManagers = new KeyManager[] {
|
|
||||||
wrappedKeyManager
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setupHTTPSCertificate() throws CertificateException,
|
public void setupHTTPSCertificate() throws CertificateException,
|
||||||
@ -149,7 +154,7 @@ public class LocalRepoKeyStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public File getKeyStoreFile() {
|
public File getKeyStoreFile() {
|
||||||
return backingFile;
|
return keyStoreFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyStore getKeyStore() {
|
public KeyStore getKeyStore() {
|
||||||
@ -235,7 +240,7 @@ public class LocalRepoKeyStore {
|
|||||||
keyStore.setKeyEntry(alias, kp.getPrivate(),
|
keyStore.setKeyEntry(alias, kp.getPrivate(),
|
||||||
"".toCharArray(), chain);
|
"".toCharArray(), chain);
|
||||||
|
|
||||||
keyStore.store(new FileOutputStream(backingFile), "".toCharArray());
|
keyStore.store(new FileOutputStream(keyStoreFile), "".toCharArray());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* After adding an entry to the keystore we need to create a fresh
|
* After adding an entry to the keystore we need to create a fresh
|
||||||
|
Loading…
x
Reference in New Issue
Block a user