Skip to content

Commit

Permalink
Export keys in PEM/armored and as PKCS#12 pack (closes #93)
Browse files Browse the repository at this point in the history
Signed-off-by: Daniele Ricci <[email protected]>
  • Loading branch information
daniele-athome committed Jul 8, 2014
1 parent ba1c1ed commit bbba67d
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 10 deletions.
5 changes: 4 additions & 1 deletion src/org/kontalk/Kontalk.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
package org.kontalk;

import java.io.IOException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.cert.CertificateException;

Expand Down Expand Up @@ -188,7 +190,8 @@ public PersonalKey getPersonalKey() throws PGPException, IOException, Certificat
}

public void exportPersonalKey()
throws CertificateException, PGPException, IOException, NoSuchProviderException {
throws CertificateException, PGPException, IOException,
NoSuchProviderException, KeyStoreException, NoSuchAlgorithmException {

Authenticator.exportDefaultPersonalKey(this, getCachedPassphrase(), true);
}
Expand Down
37 changes: 28 additions & 9 deletions src/org/kontalk/authenticator/Authenticator.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,27 @@

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import org.kontalk.R;
import org.kontalk.crypto.PGP;
import org.kontalk.crypto.PersonalKey;
import org.kontalk.crypto.X509Bridge;
import org.kontalk.ui.NumberValidation;
import org.kontalk.util.MessageUtils;
import org.spongycastle.bcpg.ArmoredOutputStream;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.util.io.pem.PemObject;
import org.spongycastle.util.io.pem.PemWriter;

import android.accounts.AbstractAccountAuthenticator;
import android.accounts.Account;
Expand Down Expand Up @@ -70,6 +80,7 @@ public class Authenticator extends AbstractAccountAuthenticator {
public static final String PRIVATE_KEY_FILENAME = "kontalk-private.pgp";
public static final String BRIDGE_CERT_FILENAME = "kontalk-login.crt";
public static final String BRIDGE_KEY_FILENAME = "kontalk-login.key";
public static final String BRIDGE_CERTPACK_FILENAME = "kontalk-login.p12";

private final Context mContext;
private final Handler mHandler;
Expand Down Expand Up @@ -127,7 +138,8 @@ public static PersonalKey loadDefaultPersonalKey(Context ctx, String passphrase)
}

public static void exportDefaultPersonalKey(Context ctx, String passphrase, boolean bridgeCertificate)
throws CertificateException, NoSuchProviderException, PGPException, IOException {
throws CertificateException, NoSuchProviderException, PGPException,
IOException, KeyStoreException, NoSuchAlgorithmException {

AccountManager m = AccountManager.get(ctx);
Account acc = getDefaultAccount(m);
Expand All @@ -136,7 +148,7 @@ public static void exportDefaultPersonalKey(Context ctx, String passphrase, bool
String pubKeyData = m.getUserData(acc, DATA_PUBLICKEY);

File path = Environment.getExternalStorageDirectory();
FileOutputStream out;
OutputStream out;

byte[] publicKey = Base64.decode(pubKeyData, Base64.DEFAULT);
byte[] privateKey = Base64.decode(privKeyData, Base64.DEFAULT);
Expand All @@ -147,24 +159,31 @@ public static void exportDefaultPersonalKey(Context ctx, String passphrase, bool
byte[] bridgeCert = Base64.decode(bridgeCertData, Base64.DEFAULT);

// export bridge certificate
out = new FileOutputStream(new File(path, BRIDGE_CERT_FILENAME));
out.write(bridgeCert);
out.close();
PemWriter writer = new PemWriter(new FileWriter(new File(path, BRIDGE_CERT_FILENAME)));
writer.writeObject(new PemObject(X509Bridge.PEM_TYPE_CERTIFICATE, bridgeCert));
writer.close();

// export bridge private key
PrivateKey bridgeKey = PGP.convertPrivateKey(privateKey, passphrase);
out = new FileOutputStream(new File(path, BRIDGE_KEY_FILENAME));
out.write(bridgeKey.getEncoded());
writer = new PemWriter(new FileWriter(new File(path, BRIDGE_KEY_FILENAME)));
writer.writeObject(new PemObject(X509Bridge.PEM_TYPE_PRIVATE_KEY, bridgeKey.getEncoded()));
writer.close();

// certificate pack in PKCS#12
X509Certificate certificate = X509Bridge.load(bridgeCert);
KeyStore pkcs12 = X509Bridge.exportCertificate(certificate, bridgeKey);
out = new FileOutputStream(new File(path, BRIDGE_CERTPACK_FILENAME));
pkcs12.store(out, passphrase.toCharArray());
out.close();
}

// export public key
out = new FileOutputStream(new File(path, PUBLIC_KEY_FILENAME));
out = new ArmoredOutputStream(new FileOutputStream(new File(path, PUBLIC_KEY_FILENAME)));
out.write(publicKey);
out.close();

// export private key
out = new FileOutputStream(new File(path, PRIVATE_KEY_FILENAME));
out = new ArmoredOutputStream(new FileOutputStream(new File(path, PRIVATE_KEY_FILENAME)));
out.write(privateKey);
out.close();
}
Expand Down
3 changes: 3 additions & 0 deletions src/org/kontalk/crypto/X509Bridge.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@
*/
public class X509Bridge {

public static final String PEM_TYPE_PRIVATE_KEY = "RSA PRIVATE KEY";
public static final String PEM_TYPE_CERTIFICATE = "CERTIFICATE";

private final static String DN_COMMON_PART_O = "OpenPGP to X.509 Bridge";

private X509Bridge() {
Expand Down

0 comments on commit bbba67d

Please sign in to comment.