diff --git a/OpenPGP-Keychain/AndroidManifest.xml b/OpenPGP-Keychain/AndroidManifest.xml
index 47ff181b3..6febe57f4 100644
--- a/OpenPGP-Keychain/AndroidManifest.xml
+++ b/OpenPGP-Keychain/AndroidManifest.xml
@@ -358,29 +358,6 @@
android:name="org.sufficientlysecure.keychain.service.KeychainIntentService"
android:exported="false" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-->
-
+
+ android:process=":remote_api"
+ android:taskAffinity=":remote_api" />
-
+
+ android:process=":remote_api" >
@@ -427,6 +404,22 @@
android:name="api_version"
android:value="1" />
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OpenPGP-Keychain/libs/scpkix-jdk15on-1.47.0.2.jar b/OpenPGP-Keychain/libs/scpkix-jdk15on-1.47.0.2.jar
new file mode 100644
index 000000000..e47eb02fc
Binary files /dev/null and b/OpenPGP-Keychain/libs/scpkix-jdk15on-1.47.0.2.jar differ
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/PgpToX509.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/PgpToX509.java
new file mode 100644
index 000000000..34815a53d
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/PgpToX509.java
@@ -0,0 +1,307 @@
+package org.sufficientlysecure.keychain.helper;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SignatureException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Vector;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.spongycastle.asn1.DERObjectIdentifier;
+import org.spongycastle.asn1.x509.AuthorityKeyIdentifier;
+import org.spongycastle.asn1.x509.BasicConstraints;
+import org.spongycastle.asn1.x509.GeneralName;
+import org.spongycastle.asn1.x509.GeneralNames;
+import org.spongycastle.asn1.x509.SubjectKeyIdentifier;
+import org.spongycastle.asn1.x509.X509Extensions;
+import org.spongycastle.asn1.x509.X509Name;
+import org.spongycastle.openpgp.PGPException;
+import org.spongycastle.openpgp.PGPPrivateKey;
+import org.spongycastle.openpgp.PGPPublicKey;
+import org.spongycastle.openpgp.PGPSecretKey;
+import org.spongycastle.x509.X509V3CertificateGenerator;
+import org.spongycastle.x509.extension.AuthorityKeyIdentifierStructure;
+import org.spongycastle.x509.extension.SubjectKeyIdentifierStructure;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.util.Log;
+
+public class PgpToX509 {
+ public final static String DN_COMMON_PART_O = "OpenPGP to X.509 Bridge";
+ public final static String DN_COMMON_PART_OU = "OpenPGP Keychain cert";
+
+ /**
+ * Creates a self-signed certificate from a public and private key. The (critical) key-usage
+ * extension is set up with: digital signature, non-repudiation, key-encipherment, key-agreement
+ * and certificate-signing. The (non-critical) Netscape extension is set up with: SSL client and
+ * S/MIME. A URI subjectAltName may also be set up.
+ *
+ * @param pubKey
+ * public key
+ * @param privKey
+ * private key
+ * @param subject
+ * subject (and issuer) DN for this certificate, RFC 2253 format preferred.
+ * @param startDate
+ * date from which the certificate will be valid (defaults to current date and time
+ * if null)
+ * @param endDate
+ * date until which the certificate will be valid (defaults to current date and time
+ * if null) *
+ * @param subjAltNameURI
+ * URI to be placed in subjectAltName
+ * @return self-signed certificate
+ * @throws InvalidKeyException
+ * @throws SignatureException
+ * @throws NoSuchAlgorithmException
+ * @throws IllegalStateException
+ * @throws NoSuchProviderException
+ * @throws CertificateException
+ * @throws Exception
+ *
+ * @author Bruno Harbulot
+ */
+ public static X509Certificate createSelfSignedCert(PublicKey pubKey, PrivateKey privKey,
+ X509Name subject, Date startDate, Date endDate, String subjAltNameURI)
+ throws InvalidKeyException, IllegalStateException, NoSuchAlgorithmException,
+ SignatureException, CertificateException, NoSuchProviderException {
+
+ X509V3CertificateGenerator certGenerator = new X509V3CertificateGenerator();
+
+ certGenerator.reset();
+ /*
+ * Sets up the subject distinguished name. Since it's a self-signed certificate, issuer and
+ * subject are the same.
+ */
+ certGenerator.setIssuerDN(subject);
+ certGenerator.setSubjectDN(subject);
+
+ /*
+ * Sets up the validity dates.
+ */
+ if (startDate == null) {
+ startDate = new Date(System.currentTimeMillis());
+ }
+ certGenerator.setNotBefore(startDate);
+ if (endDate == null) {
+ endDate = new Date(startDate.getTime() + (365L * 24L * 60L * 60L * 1000L));
+ Log.d(Constants.TAG, "end date is=" + DateFormat.getDateInstance().format(endDate));
+ }
+
+ certGenerator.setNotAfter(endDate);
+
+ /*
+ * The serial-number of this certificate is 1. It makes sense because it's self-signed.
+ */
+ certGenerator.setSerialNumber(BigInteger.ONE);
+ /*
+ * Sets the public-key to embed in this certificate.
+ */
+ certGenerator.setPublicKey(pubKey);
+ /*
+ * Sets the signature algorithm.
+ */
+ String pubKeyAlgorithm = pubKey.getAlgorithm();
+ if (pubKeyAlgorithm.equals("DSA")) {
+ certGenerator.setSignatureAlgorithm("SHA1WithDSA");
+ } else if (pubKeyAlgorithm.equals("RSA")) {
+ certGenerator.setSignatureAlgorithm("SHA1WithRSAEncryption");
+ } else {
+ RuntimeException re = new RuntimeException("Algorithm not recognised: "
+ + pubKeyAlgorithm);
+ Log.e(Constants.TAG, re.getMessage(), re);
+ throw re;
+ }
+
+ /*
+ * Adds the Basic Constraint (CA: true) extension.
+ */
+ certGenerator.addExtension(X509Extensions.BasicConstraints, true,
+ new BasicConstraints(true));
+
+ /*
+ * Adds the subject key identifier extension.
+ */
+ SubjectKeyIdentifier subjectKeyIdentifier = new SubjectKeyIdentifierStructure(pubKey);
+ certGenerator
+ .addExtension(X509Extensions.SubjectKeyIdentifier, false, subjectKeyIdentifier);
+
+ /*
+ * Adds the authority key identifier extension.
+ */
+ AuthorityKeyIdentifier authorityKeyIdentifier = new AuthorityKeyIdentifierStructure(pubKey);
+ certGenerator.addExtension(X509Extensions.AuthorityKeyIdentifier, false,
+ authorityKeyIdentifier);
+
+ /*
+ * Adds the subject alternative-name extension.
+ */
+ if (subjAltNameURI != null) {
+ GeneralNames subjectAltNames = new GeneralNames(new GeneralName(
+ GeneralName.uniformResourceIdentifier, subjAltNameURI));
+ certGenerator.addExtension(X509Extensions.SubjectAlternativeName, false,
+ subjectAltNames);
+ }
+
+ /*
+ * Creates and sign this certificate with the private key corresponding to the public key of
+ * the certificate (hence the name "self-signed certificate").
+ */
+ X509Certificate cert = certGenerator.generate(privKey);
+
+ /*
+ * Checks that this certificate has indeed been correctly signed.
+ */
+ cert.verify(pubKey);
+
+ return cert;
+ }
+
+ /**
+ * Creates a self-signed certificate from a PGP Secret Key.
+ *
+ * @param pgpSecKey
+ * PGP Secret Key (from which one can extract the public and private keys and other
+ * attributes).
+ * @param pgpPrivKey
+ * PGP Private Key corresponding to the Secret Key (password callbacks should be done
+ * before calling this method)
+ * @param subjAltNameURI
+ * optional URI to embed in the subject alternative-name
+ * @return self-signed certificate
+ * @throws PGPException
+ * @throws NoSuchProviderException
+ * @throws InvalidKeyException
+ * @throws NoSuchAlgorithmException
+ * @throws SignatureException
+ * @throws CertificateException
+ *
+ * @author Bruno Harbulot
+ */
+ public static X509Certificate createSelfSignedCert(PGPSecretKey pgpSecKey,
+ PGPPrivateKey pgpPrivKey, String subjAltNameURI) throws PGPException,
+ NoSuchProviderException, InvalidKeyException, NoSuchAlgorithmException,
+ SignatureException, CertificateException {
+ // get public key from secret key
+ PGPPublicKey pgpPubKey = pgpSecKey.getPublicKey();
+
+ // LOGGER.info("Key ID: " + Long.toHexString(pgpPubKey.getKeyID() & 0xffffffffL));
+
+ /*
+ * The X.509 Name to be the subject DN is prepared. The CN is extracted from the Secret Key
+ * user ID.
+ */
+ Vector x509NameOids = new Vector();
+ Vector x509NameValues = new Vector();
+
+ x509NameOids.add(X509Name.O);
+ x509NameValues.add(DN_COMMON_PART_O);
+
+ x509NameOids.add(X509Name.OU);
+ x509NameValues.add(DN_COMMON_PART_OU);
+
+ for (@SuppressWarnings("unchecked")
+ Iterator