I have a Quarkus application which implements the server side of a ProtoBuf-over-TLS communications channel and loads a PFX/P12 file at runtime to get the server certificate and private key.
The application runs fine as a when run from the built jar, but when I try running the native image, I get an error indicating that the PKCS12 algorithm cannot be found. It seems like native images expect to have the security artifact pulled-in at build time. Do I have this correct? Is there any way to work-around this?
Example code:
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import io.quarkus.runtime.QuarkusApplication;
import io.quarkus.runtime.annotations.QuarkusMain;
#QuarkusMain
public class KeystoreTest implements QuarkusApplication {
String keystoreFile = "/home/sm-dp/... server.pfx";
String keystoreSecret = "secret";
#Override
public int run(String... args) throws Exception {
KeyStore keystore = KeyStore.getInstance("PKCS12");
try (InputStream fis = new FileInputStream(new File(keystoreFile))) {
keystore.load(fis, keystoreSecret.toCharArray());
}
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("PKIX");
keyManagerFactory.init(keystore, keystoreSecret.toCharArray());
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(keyManagerFactory.getKeyManagers(), null, null);
return 0;
}
}
Stacktrace:
java.security.KeyStoreException: PKCS12 not found
at java.security.KeyStore.getInstance(KeyStore.java:851)
at com.mcleodnet.KeystoreTest.run(KeystoreTest.java:21)
at com.mcleodnet.KeystoreTest_ClientProxy.run(KeystoreTest_ClientProxy.zig:157)
at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:112)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:61)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:38)
at io.quarkus.runner.GeneratedMain.main(GeneratedMain.zig:30)
Caused by: java.security.NoSuchAlgorithmException: class configured for KeyStore (provider: SunJSSE) cannot be found.
at java.security.Provider$Service.getImplClass(Provider.java:1649)
at java.security.Provider$Service.newInstance(Provider.java:1592)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:236)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:164)
at java.security.Security.getImpl(Security.java:695)
at java.security.KeyStore.getInstance(KeyStore.java:848)
... 6 more
Caused by: java.lang.ClassNotFoundException: sun.security.pkcs12.PKCS12KeyStore
at com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:60)
at java.lang.Class.forName(DynamicHub.java:1194)
at java.security.Provider$Service.getImplClass(Provider.java:1634)
... 11 more
Try to add quarkus.native.enable-all-security-services=true to your configuration.
If it's not working, you can add a #RegisterForReflection(targets = sun.security.pkcs12.PKCS12KeyStore.class) to one of your application class.
Related
I need to connect to Snowflake using Java using Key File in format P8
class JustTheCode {
public static void main(String[] args) throws Exception {
Security.addProvider(new BouncyCastleProvider());
String path = "/<path>/app_rsa_key.p8";
String passphrase = "myKey";//System.getenv("PRIVATE_KEY_PASSPHRASE");
bcParcer(path,passphrase);
}
private static PrivateKey bcParcer(String keyFilePath, String password)
throws IOException, OperatorCreationException, PKCSException, Exception {
PEMParser pemParser = new PEMParser(new FileReader(Paths.get(keyFilePath).toFile()));
PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo) pemParser.readObject();
pemParser.close();
InputDecryptorProvider pkcs8Prov = new JceOpenSSLPKCS8DecryptorProviderBuilder().build(
password.toCharArray());
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(
BouncyCastleProvider.PROVIDER_NAME);
PrivateKeyInfo decryptedPrivateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(
pkcs8Prov);
PrivateKey privateKey = converter.getPrivateKey(decryptedPrivateKeyInfo);
System.out.println(privateKey);
return privateKey;
}
}
When I run the code, I'm getting the error:
Exception in thread "main" net.snowflake.client.jdbc.internal.org.bouncycastle.pkcs.PKCSException: unable to read encrypted data: 1.2.840.113549.1.5.3 not available: requires PBE parameters
at net.snowflake.client.jdbc.internal.org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo(Unknown Source)
at configmgmt.snowflake.reader.impl.JustTheCode.bcParcer(PrivateKeyReader.java:122)
at configmgmt.snowflake.reader.impl.JustTheCode.main(PrivateKeyReader.java:102)
Caused by: net.snowflake.client.jdbc.internal.org.bouncycastle.operator.OperatorCreationException: 1.2.840.113549.1.5.3 not available: requires PBE parameters
at net.snowflake.client.jdbc.internal.org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder$1.get(Unknown Source)
... 3 more
Caused by: java.security.InvalidKeyException: requires PBE parameters
at java.base/com.sun.crypto.provider.PBEWithMD5AndDESCipher.engineInit(PBEWithMD5AndDESCipher.java:186)
at java.base/javax.crypto.Cipher.implInit(Cipher.java:867)
at java.base/javax.crypto.Cipher.chooseProvider(Cipher.java:929)
at java.base/javax.crypto.Cipher.init(Cipher.java:1299)
at java.base/javax.crypto.Cipher.init(Cipher.java:1236)
... 4 more
Caused by: java.security.InvalidAlgorithmParameterException: Parameters missing
at java.base/com.sun.crypto.provider.PBES1Core.init(PBES1Core.java:214)
at java.base/com.sun.crypto.provider.PBEWithMD5AndDESCipher.engineInit(PBEWithMD5AndDESCipher.java:220)
at java.base/com.sun.crypto.provider.PBEWithMD5AndDESCipher.engineInit(PBEWithMD5AndDESCipher.java:184)
... 8 more
I am searching but in the documentation there is no information about this configuration: Caused by: java.security.InvalidKeyException: requires PBE parameters
I found the fix changing the imports:
Previously:
import net.snowflake.client.jdbc.internal.org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import net.snowflake.client.jdbc.internal.org.bouncycastle.jce.provider.BouncyCastleProvider;
import net.snowflake.client.jdbc.internal.org.bouncycastle.openssl.PEMParser;
import net.snowflake.client.jdbc.internal.org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import net.snowflake.client.jdbc.internal.org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
import net.snowflake.client.jdbc.internal.org.bouncycastle.operator.InputDecryptorProvider;
import net.snowflake.client.jdbc.internal.org.bouncycastle.operator.OperatorCreationException;
import net.snowflake.client.jdbc.internal.org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
import net.snowflake.client.jdbc.internal.org.bouncycastle.pkcs.PKCSException;
new:
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
import org.bouncycastle.operator.InputDecryptorProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
import org.bouncycastle.pkcs.PKCSException;
And the pom:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-ext-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.70</version>
</dependency>
Besides having correct imports as in the accepted answer, it's also worth checking if the Security provider registered from the Snowflake jdbc driver is not saved in the Java Security Providers, as it contains different parameters and amount of them - for me it was:
2727 parameters for net.snowflake.client.jdbc.internal.org.bouncycastle.jcajce.provider
2944 parameters for org.bouncycastle.jcajce.provider
Checking Bouncy Castle Security Provider:
Security.getProvider("BC"); //or Security.getProvider(BouncyCastleProvider.PROVIDER_NAME);
Removing existing and registering a new Bouncy Castle Provider from the bcprov-ext-jdk15on library:
import org.bouncycastle.jce.provider.BouncyCastleProvider;
Security.removeProvider("BC");
Security.addProvider(new BouncyCastleProvider());
I've been asked to migrate a Java 8 (spring) micro-service to a Java 11 microservice (Quarkus framework).
The microservice uses a X509 certificate to authenticate to a MongoDB 4.4 database. This works well for the Java 8 version without any error or issue.
Nevertheless the Java 11 version won't work and it displays the following Stack Trace when deployed:
com.mongodb.MongoSocketWriteException: Exception sending message
at com.mongodb.internal.connection.InternalStreamConnection.translateWriteException(InternalStreamConnection.java:619)
at com.mongodb.internal.connection.InternalStreamConnection.sendMessage(InternalStreamConnection.java:497)
at com.mongodb.internal.connection.InternalStreamConnection.sendCommandMessage(InternalStreamConnection.java:328)
at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceive(InternalStreamConnection.java:278)
at com.mongodb.internal.connection.CommandHelper.sendAndReceive(CommandHelper.java:83)
at com.mongodb.internal.connection.CommandHelper.executeCommand(CommandHelper.java:33)
at com.mongodb.internal.connection.InternalStreamConnectionInitializer.initializeConnectionDescription(InternalStreamConnectionInitializer.java:107)
at com.mongodb.internal.connection.InternalStreamConnectionInitializer.initialize(InternalStreamConnectionInitializer.java:62)
at com.mongodb.internal.connection.InternalStreamConnection.open(InternalStreamConnection.java:144)
at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.lookupServerDescription(DefaultServerMonitor.java:188)
at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:144)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path validation failed: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors
Relevant Source Code:
package everest.onecd.config;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoDatabase;
public class MongoConfiguration {
private static final String PATH = "/usr/share/easy-rsa/keys/java11/mongo.jks";
private static final Logger LOG = LoggerFactory.getLogger(MongoConfiguration.class);
private static final String IP = "XX.XX.XX.XX";
private static final String PORT = "27017";
public static MongoDatabase getDatabase() {
SSLContext context = getSSLContext();
MongoClientSettings.Builder settings = MongoClientSettings.builder();
settings.applyToSslSettings(builder -> { builder.context(context); builder.invalidHostNameAllowed(true); builder.enabled(true); });
settings.applyConnectionString(new ConnectionString("mongodb://" + IP + ":" + PORT + "/test?ssl=true&authMechanism=MONGODB-X509&connectTimeoutMS=60000&socketTimeoutMS=60000&retryWrites=true&maxIdleTimeMS=60000"));
MongoClient client = MongoClients.create(settings.build());
MongoDatabase database = client.getDatabase("test");
return database;
}
private static SSLContext getSSLContext() {
SSLContext sslContext = null;
try (FileInputStream fis = new FileInputStream(new File(PATH))) {
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(fis, ".sevenzip".toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
LOG.info("Se ejecuto SSLContext exitosamente");
} catch (CertificateException | NoSuchAlgorithmException | KeyStoreException | IOException | KeyManagementException e) {
LOG.error(e.toString(), e);
}
return sslContext;
}
}
I already tried this: Java 11 and 12 SSL sockets fail on a handshake_failure error with TLSv1.3 enabled
So, I generated the new JKS with -keyalg RSA but it didn't work either. I also changed the TLS version to 1.2 and 1.3 and got the same exception.
This is the solution, after all the struggle. In Quarkus, it is required to fully inicialize all trust stores and key stores. So, aparently, it ignores both JVM args -Djavax.net.ssl.keyStore and -Djavax.net.ssl.trustStore.
private static SSLContext getSSLContext() {
SSLContext sslContext = null;
try (FileInputStream fis = new FileInputStream(new File(TPATH))) {
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(fis, ".sevenzip".toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
FileInputStream fKS = new FileInputStream(new File(PATH));
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(fKS, ".sevenzip".toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, ".sevenzip".toCharArray());
sslContext = SSLContext.getInstance("SSL");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
LOG.info("Se ejecuto SSLContext exitosamente");
} catch (CertificateException | NoSuchAlgorithmException | KeyStoreException | IOException | KeyManagementException e) {
LOG.error(e.toString(), e);
} catch (UnrecoverableKeyException e) {
LOG.error(e.toString(), e);
}
return sslContext;
}
I have two separated servers running Oracle 11g.
The servers were patched with Oracle patch sets to upgrade JVM. After the upgrade, I'm able to communicate with external web service using HTTPS and TLSv1.2, but only on server "A". Server "B" gives me error like:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java)
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:142)
at FursTestBaza.Test(FursTestBaza:92)
We have checked patch set and both servers "have" the same patch set installed:
Server A:
Server B:
The Java stored procedure is a simple Class with one static method. This procedure loads certificates from file system and makes a HTTPS connection to specified URL (hardcoded for test purposes). In the source code I have included System.setProperty("javax.net.debug", "all") to get back some log whats happening.
The source code of Java stored procedure:
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED INIS_PROD."FursTestBaza" as
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.Enumeration;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
public class FursTestBaza {
static String napaka="";
public static void Test()
{
try
{
String URL = "https://blagajne.fu.gov.si:9003/v1/cash_registers";
System.out.println("Testiranje povezave na: " + URL);
System.setProperty("javax.net.debug", "all");
System.out.println("==================================");
System.out.println("1");
KeyStore p12 = KeyStore.getInstance("pkcs12");
String geslo = "*******"; //private key password
System.out.println("2");
p12.load(new FileInputStream(new File("/oracle/orasw/Wallet/Certifikat/Furs/privateCert/FURS-AS_davcne_blagajne.p12")), geslo.toCharArray());
Enumeration e = p12.aliases();
String alias = (String) e.nextElement();
System.out.println("alias certifikata: " + alias);
//privatni ključ
Key privateKey = p12.getKey(alias, geslo.toCharArray());
System.out.println("3");
//podpis
Signature podpis = Signature.getInstance("SHA256WithRSA");
podpis.initSign((PrivateKey) privateKey);
System.out.println("4");
//določimo svoj keystore in TLS1.2
SSLContext sslcontext = SSLContext.getInstance("TLSv1.2");
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
KeyStore ks = KeyStore.getInstance("PKCS12");
System.out.println("5");
ks.load(new FileInputStream(new File("/oracle/orasw/Wallet/Certifikat/Furs/privateCert/FURS-AS_davcne_blagajne.p12")), geslo.toCharArray());
kmf.init(ks, geslo.toCharArray());
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate ca = cf.generateCertificate(new FileInputStream(new File("/oracle/orasw/Wallet/Certifikat/Furs/privateCert/blagajne.fu.gov.si.cer")));
System.out.println("6");
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
System.out.println("7");
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
System.out.println("8");
TrustManager[] tm = tmf.getTrustManagers();
sslcontext.init(kmf.getKeyManagers(), tm, null);
System.out.println("8.1");
HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());
System.out.println("9");
URL url = new URL(URL);
HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection();
System.out.println("10");
httpsURLConnection.connect();
System.out.println("Povezan na: " + URL + ", chiper:" + httpsURLConnection.getCipherSuite());
System.out.println("Prekinjam povezavo...");
httpsURLConnection.disconnect();
System.out.println("Povezava zaprta.");
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
Then have executed this code with PL/SQL:
begin
dbms_java.set_output(500000);
p_test_furs;
end;
The connection from server A works and all works fine, but the problem is on server B.
On server "B" I got exception (above) and If comparing the javax.net.debug I noticed this exception:
The certificates on both servers are the same.
Java version on my database is the same:
Server A:
select dbms_java.get_ojvm_property(propstring=>'java.version') from dual returns: 1.6.0_191
Server B:
select dbms_java.get_ojvm_property(propstring=>'java.version') from dual returns: 1.6.0_191
What can be wrong or what else I can check on the server/database side?
I am distributing a library jar for internal clients, and the library includes a certificate which it uses to call a service that is also internal to our network.
The trust manager is set up as follows
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore keystore = KeyStore.getInstance("JKS");
InputStream keystoreStream =
clazz.getClassLoader().getResourceAsStream("certs.keystore"); // (on classpath)
keystore.load(keystoreStream, "pa55w0rd".toCharArray());
trustManagerFactory.init(keystore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
SSLContext context = SSLContext.getInstance("SSL");
context.init(null, trustManagers, null);
SSLSocketFactory socketFact = context.getSocketFactory();
connection.setSSLSocketFactory(socketFact);
All of this works fine except in cases where users need other certificates or the default certificate.
I tried this
Registering multiple keystores in JVM with no luck (I am having trouble generalizing it for my case)
How can I use my cert and still allow user libraries to use their own certs as well?
You are configuring a connection with a custom keystore acting as a truststore ( a certificate of your server that you trust). You are not overriding the default JVM behaviour, so the rest of the connection that other applications that include your library can make will not be affected.
Therefore you do not need a multiple keystore manager, in fact, your code works perfectly.
I've attached a full example below using a keystore google.jks which includes Google's root CA, and a connection using the default JVM truststore. This is the output
request("https://www.google.com/", "test/google.jks", "pa55w0rd"); //OK
request("https://www.aragon.es/", "test/google.jks", "pa55w0rd"); // FAIL sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
request("https://www.aragon.es/", null, null); //OK
The problem is not in the code you have attached, so check the following in your code:
The truststore certs.keystore is really found in your classpath
Truststore settings are not set at JVM level using -Djavax.net.ssl.trustStore
The errors found (please include it in your question) are really related to the SSL connection
package test;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyStore;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
public class HTTPSCustomTruststore {
public final static void main (String argv[]) throws Exception{
request("https://www.google.com/", "test/google.jks", "pa55w0rd"); //Expected OK
request("https://www.aragon.es/","test/google.jks","pa55w0rd"); // Expected FAIL
request("https://www.aragon.es/",null,null); //using default truststore. OK
}
public static void configureCustom(HttpsURLConnection connection, String truststore, String pwd)throws Exception{
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore keystore = KeyStore.getInstance("JKS");
InputStream keystoreStream = HTTPSCustomTruststore.class.getClassLoader().getResourceAsStream(truststore);
keystore.load(keystoreStream, pwd.toCharArray());
trustManagerFactory.init(keystore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
SSLContext context = SSLContext.getInstance("SSL");
context.init(null, trustManagers, new java.security.SecureRandom());
SSLSocketFactory socketFact = context.getSocketFactory();
connection.setSSLSocketFactory(socketFact);
}
public static void request(String urlS, String truststore, String pwd) {
try {
URL url = new URL(urlS);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
if (truststore != null) {
configureCustom((HttpsURLConnection) conn, truststore, pwd);
}
conn.connect();
int statusCode = conn.getResponseCode();
if (statusCode != 200) {
System.out.println(urlS + " FAIL");
} else {
System.out.println(urlS + " OK");
}
} catch (Exception e) {
System.out.println(urlS + " FAIL " + e.getMessage());
}
}
}
You could import the default certificates into your custom store to have a combined custom store and use that.
I am trying to bind to a very simple jar file in a xamarin android project, but I am getting the warning:
JARTOXML : warning J2X9001: Couldn't load class GetCerts : java.lang.UnsupportedClassVersionError: GetCerts : Unsupported major.minor version 52.0
BINDINGSGENERATOR : warning BG8601: No packages found.
if I add the picasso-2.5.2.jar to the same bindings project, it is accessible perfectly, just as in the documentation for binding a jar from xamarin (http://developer.xamarin.com/guides/android/advanced_topics/java_integration_overview/binding-a-java-library/binding-a-jar/)
the code in the jar is extremely simple:
package com.mgw;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
class GetCerts {
public static X509Certificate GetCert(byte[] bytes) throws Exception
{
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
InputStream in = new ByteArrayInputStream(bytes);
X509Certificate cert = (X509Certificate)certFactory.generateCertificate(in);
return cert;
}
}
Problem was that the class was not public. I changed the code to be:
package com.sage;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
public class GetCerts {
public static X509Certificate GetCert(byte[] bytes) throws Exception
{
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
InputStream in = new ByteArrayInputStream(bytes);
X509Certificate cert = (X509Certificate)certFactory.generateCertificate(in);
return cert;
}
public static boolean DoSomething()
{
return true;
}
}
change the file name to match the class name, rebuilt using JDK6 and it all worked.
Note that the JDK version used to build the library should not be higher than that used by Xamarin or you may get issues.