I would like to save a X509Certificate and its private key into the Android KeyStore, I tought I should 'merge' the X509Certificate (containing the public key) and its private key. The private key is used to create a CSR and then a server party sign the certificate and return to the application, can I merge the cert and the private key into one unique cert? Also I'm using spongycastle (aka bouncycastle's android wrapper).
I have no idea about Android KeyStore, but maybe you can try something like:
PrivateKey privateKey = ... //this is what you already have
X509Certificate certificate = ... //this is what you already have
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
Certificate[] certChain = new Certificate[1];
certChain[0] = certificate;
char[] myKeyPassword = "myKeyPassword".toCharArray();
keyStore.setKeyEntry("mykeyalias", (Key)privateKey, myKeyPassword, certChain);
See https://docs.oracle.com/javase/9/docs/api/java/security/KeyStore.html#setKeyEntry-java.lang.String-java.security.Key-char:A-java.security.cert.Certificate:A- for more information about KeyStore.setKeyEntry
I have file cert.pfx exported on Windows. This file contains my certificate. On Ubuntu i can open it with password and I see the certificate. But when I loaded this file:
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = ks = KeyStore.getInstance("pkcs12", provider.getName());
ks.load(new FileInputStream("/home/test/.cert.pfx", "xxxxxx".toCharArray());
String alias = ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, pts.getRandom());
Certificate[] chain = ks.getCertificateChain(alias);
After this operations I have null in pk and chain.
Also I have registered BC provider in java.security
I changed BouncyCastleProvider to SunJSSE. Now my correctly code is:
String providerName = "SunJSSE";
KeyStore ks = ks = KeyStore.getInstance("pkcs12", providerName);
ks.load(new FileInputStream("/home/test/.cert.pfx", "xxxxxx".toCharArray());
String alias = ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, pts.getRandom());
Certificate[] chain = ks.getCertificateChain(alias);
Now in pk is my privarte key, and in chain is certificate chain.
I don't know why in BC doesn't work. I have other certificate and BC provider work correctly.
Hello all
I want to generate a certificate using keystore than add this to my sevrer and browse my sever using IE. I need the steps for generating the certificate in plain english as all what i read in the internet is hard to be understod. The server socket is:
SSLServerSocketFactory ssf = (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
SSLServerSocket Server = (SSLServerSocket)ssf.createServerSocket(1234);
String[] cipher = {"SSL_DH_anon_WITH_RC4_128_MD5"};
Server.setEnabledCipherSuites(cipher);
The certificate code is this but not sure where to pu it in my server:
InputStream infil = new FileInputStream("server.cer");
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)cf.generateCertificate(infil);
infil.close();
KeyStore ks = null;
ks = KeyStore.getInstance("JKS", "SUN");
InputStream is = null;
is = new FileInputStream(new File("./keystore"));
ks.load(is,"rootroot".toCharArray());
See the Javadoc/Security/JSSE Reference.
I have a pkcs12 file. I need to use this to connect to a webpage using https protocol. I came across some code where in order to connect to a secure web page i need to set the following system properties:
System.setProperty("javax.net.ssl.trustStore", "myTrustStore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
System.setProperty("javax.net.ssl.keyStoreType", "pkcs12");
System.setProperty("javax.net.ssl.keyStore", "new_cert.p12");
System.setProperty("javax.net.ssl.keyStorePassword", "newpass");
I have the p12(pkcs12) file. All I need is a truststore file.
I extracted the certificates using:
openssl.exe pkcs12 -in c:/mykey.p12 -out c:/cert.txt -nokeys -clcerts
Now converted the cert PEM file to der
openssl.exe x509 -in c:/cert.txt -outform DER -out c:/CAcert.der
Now adding the der file to a keystore
keytool -import -file C:/Cacert.der -keystore mytruststore
Now I have the truststore, but when I use it, I get the following error
Exception in thread "main" java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl)
Update:
After removing certain properties and setting only the "trustStore", "trustStorePassword" and "trustStoreType" property, I got the following exception
java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
Please Help.
For anyone encountering a similar situation I was able to solve the issue above as follows:
Regenerate your pkcs12 file as follows:
openssl pkcs12 -in oldpkcs.p12 -out keys -passout pass:tmp
openssl pkcs12 -in keys -export -out new.p12 -passin pass:tmp -passout pass:newpasswd
Import the CA certificate from server into a TrustStore ( either your own, or the java keystore in $JAVA_HOME/jre/lib/security/cacerts, password: changeit).
Set the following system properties:
System.setProperty("javax.net.ssl.trustStore", "myTrustStore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
System.setProperty("javax.net.ssl.keyStoreType", "pkcs12");
System.setProperty("javax.net.ssl.keyStore", "new.p12");
System.setProperty("javax.net.ssl.keyStorePassword", "newpasswd");
Test ur url.
Courtesy# http://forums.sun.com/thread.jspa?threadID=5296333
I cannot comment because of the 50pts threshhold, but I don't think that the answer provided in https://stackoverflow.com/a/537344/1341220 is correct.
What you are actually describing is how you insert server certificates into the systems default truststore:
$JAVA_HOME/jre/lib/security/cacerts, password: changeit)
This works, indeed, but it means that you did not really specify a trust store local to your project, but rather accepted the certificate universially in your system.
You actually never use your own truststore that you defined here:
System.setProperty("javax.net.ssl.trustStore", "myTrustStore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
It appears that you are extracting you certificate from the PKCS #12 key store and creating a new Java key store (with type "JKS"). You don't strictly have to provide a trust store password (although using one allows you to test the integrity of your root certificates).
So, try your program with only the following SSL properties set. The list shown in your question is over-specified and may be causing problems.
System.setProperty("javax.net.ssl.trustStore", "myTrustStore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
Also, using the PKCS #12 file directly as the trust store should work, as long as the CA certificate is detected as a "trusted" entry. But in that case, you'll have to specify the javax.net.ssl.trustStoreType property as "PKCS12" too.
Try with these properties only. If you get the same error, I suspect your problem is not the key store. If it still occurs, post more of the stack trace in your question to narrow the problem down.
The new error, "the trustAnchors parameter must be non-empty," could be due to setting the javax.net.ssl.trustStore property to a file that doesn't exist; if the file cannot be opened, an empty key store created, which would lead to this error.
This is an example to use ONLY p12 file it's not optimazed but it work.
The pkcs12 file where generated by OpenSSL by me.
Example how to load p12 file and build Trust zone from it...
It outputs certificates from p12 file and add good certs to TrustStore
KeyStore ks=KeyStore.getInstance("pkcs12");
ks.load(new FileInputStream("client_t_c1.p12"),"c1".toCharArray());
KeyStore jks=KeyStore.getInstance("JKS");
jks.load(null);
for (Enumeration<String>t=ks.aliases();t.hasMoreElements();)
{
String alias = t.nextElement();
System.out.println("#:" + alias);
if (ks.isKeyEntry(alias)){
Certificate[] a = ks.getCertificateChain(alias);
for (int i=0;i<a.length;i++)
{
X509Certificate x509 = (X509Certificate)a[i];
System.out.println(x509.getSubjectDN().toString());
if (i>0)
jks.setCertificateEntry(x509.getSubjectDN().toString(), x509);
System.out.println(ks.getCertificateAlias(x509));
System.out.println("ok");
}
}
}
System.out.println("init Stores...");
KeyManagerFactory kmf=KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, "c1".toCharArray());
TrustManagerFactory tmf=TrustManagerFactory.getInstance("SunX509");
tmf.init(jks);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
URL url = new URL("https://test.domain:443");
String keyStore = "server.p12"
String keyStorePassword = "changeit";
String keyPassword = "changeit";
String KeyStoreType= "PKCS12";
String KeyManagerAlgorithm = "SunX509";
String SSLVersion = "SSLv3";
public HttpURLConnection getHttpsURLConnection(URL url, String keystore,
String keyStorePass,String keyPassword, String KeyStoreType
,String KeyManagerAlgorithm, String SSLVersion)
throws NoSuchAlgorithmException, KeyStoreException,
CertificateException, FileNotFoundException, IOException,
UnrecoverableKeyException, KeyManagementException {
System.setProperty("javax.net.debug","ssl,handshake,record");
SSLContext sslcontext = SSLContext.getInstance(SSLVersion);
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerAlgorithm);
KeyStore ks = KeyStore.getInstance(KeyStoreType);
ks.load(new FileInputStream(keystore), keyStorePass.toCharArray());
kmf.init(ks, keyPassword.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
TrustManager[] tm = tmf.getTrustManagers();
sslcontext.init(kmf.getKeyManagers(), tm, null);
SSLSocketFactory sslSocketFactory = sslcontext.getSocketFactory();
HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory);
HttpsURLConnection httpsURLConnection = ( HttpsURLConnection)uRL.openConnection();
return httpsURLConnection;
}
This example shows how you can layer SSL on top of an existing socket, obtaining the client cert from a PKCS#12 file. It is appropriate when you need to connect to an upstream server via a proxy, and you want to handle the full protocol by yourself.
Essentially, however, once you have the SSL Context, you can apply it to an HttpsURLConnection, etc, etc.
KeyStore ks = KeyStore.getInstance("PKCS12");
InputStream is = ...;
char[] ksp = storePassword.toCharArray();
ks.load(is, ksp);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
char[] kp = keyPassword.toCharArray();
kmf.init(ks, kp);
sslContext = SSLContext.getInstance("SSLv3");
sslContext.init(kmf.getKeyManagers(), null, null);
SSLSocketFactory factory = sslContext.getSocketFactory();
SSLSocket sslsocket = (SSLSocket) factory.createSocket(socket, socket
.getInetAddress().getHostName(), socket.getPort(), true);
sslsocket.setUseClientMode(true);
sslsocket.setSoTimeout(soTimeout);
sslsocket.startHandshake();
The following steps will help you to sort your problem out.
Steps:
developer_identity.cer <= download from Apple
mykey.p12 <= Your private key
Commands to follow:
openssl x509 -in developer_identity.cer -inform DER -out developer_identity.pem -outform PEM
openssl pkcs12 -nocerts -in mykey.p12 -out mykey.pem
openssl pkcs12 -export -inkey mykey.pem -in developer_identity.pem -out iphone_dev.p12
Final p12 that we will require is iphone_dev.p12 file and the passphrase.
use this file as your p12 and then try. This indeed is the solution.:)
I realise that this article may be outdated but still I would like to ask smithsv to correct his source code, it contains many mistakes, I managed to correct most of them but still don't know what kind of object x509 could be.Here is the source code as I think is should be:
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.util.Enumeration;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
public class Connection2 {
public void connect() {
/*
* This is an example to use ONLY p12 file it's not optimazed but it
* work. The pkcs12 file where generated by OpenSSL by me. Example how
* to load p12 file and build Trust zone from it... It outputs
* certificates from p12 file and add good certs to TrustStore
*/
KeyStore ks = KeyStore.getInstance( "pkcs12" );
ks.load( new FileInputStream( cert.pfx ), "passwrd".toCharArray() );
KeyStore jks = KeyStore.getInstance( "JKS" );
jks.load( null );
for( Enumeration t = ks.aliases(); t.hasMoreElements(); ) {
String alias = (String )t.nextElement();
System.out.println( "#:" + alias );
if( ks.isKeyEntry( alias ) ) {
Certificate[] a = ks.getCertificateChain( alias );
for( int i = 0; i == 0; )
jks.setCertificateEntry( x509Cert.getSubjectDN().toString(), x509 );
System.out.println( ks.getCertificateAlias( x509 ) );
System.out.println( "ok" );
}
}
System.out.println( "init Stores..." );
KeyManagerFactory kmf = KeyManagerFactory.getInstance( "SunX509" );
kmf.init( ks, "c1".toCharArray() );
TrustManagerFactory tmf = TrustManagerFactory.getInstance( "SunX509" );
tmf.init( jks );
SSLContext ctx = SSLContext.getInstance( "TLS" );
ctx.init( kmf.getKeyManagers(), tmf.getTrustManagers(), null );
}
}
I have the following code to export certificates and keys from a keystore, that I created with keytool in Windows:
final KeyStore keystore = KeyUtil.loadKeystore("keystore.jks", "pass");
UserInfo userinfo = new UserInfo(WSusername, WSpassword);
X509Certificate clientcert = KeyUtil.getCertificate(CLIENT_KEY_ALIAS, keystore);
X509Certificate servercert = KeyUtil.getCertificate(SERVER_KEY_ALIAS, keystore);
PrivateKey clientprivate = KeyUtil.getPrivateKey(CLIENT_KEY_ALIAS, CLIENT_KEY_PASSWORD, keystore);
Yet it fails at the last line with "unable to retrieve private key for signing"
It can retrieve the clientcert, but when it tries clientprivate, it fails.
My problem was that when I generated the keystore with keytool, it did not create the PrivateKey as a key entry. To fix this, I imported the .p12 keystore as the private key, which worked. My original code above then worked.