How to authenticate my own provider( only for testing purposes) - java

Now, I wrote a new provider (ESMJCE provider), and I also write a simple application to test it, but I have some exceptions like that
java.lang.SecurityException: JCE cannot authenticate the provider ESMJCE
at javax.crypto.Cipher.getInstance(DashoA13*..)
at javax.crypto.Cipher.getInstance(DashoA13*..)
at testprovider.main(testprovider.java:27)
Caused by: java.util.jar.JarException: Cannot parse file:/C:/Program%20Files/Java/jre1.6.0_02/lib/ext/abc.jar
at javax.crypto.SunJCE_c.a(DashoA13*..)
at javax.crypto.SunJCE_b.b(DashoA13*..)
at javax.crypto.SunJCE_b.a(DashoA13*..)
... 3 more
And here is my source code
import java.security.Provider;
import java.security.Security;
import javax.crypto.Cipher;
import esm.jce.provider.ESMProvider;
public class testprovider {
/
#param args
/
public static void main(String[] args) {
// TODO Auto-generated method stub
ESMProvider esmprovider = new esm.jce.provider.ESMProvider();
Security.insertProviderAt(esmprovider,2);
Provider[] temp = Security.getProviders();
for (int i= 0; i<temp.length; i++){
System.out.println("Providers: " temp[i].getName());
}
try{
Cipher cipher = Cipher.getInstance("DES", "ESMJCE");
System.out.println("Cipher: " cipher);
int blockSize= cipher.getBlockSize();
System.out.println("blockSize= " + blockSize);
}catch (Exception e){
e.printStackTrace();
}
}
}
Please help me solve this issue
Thanks

actually you can bypass the Sun-rooted certificate requirement and can sign provider by your own: Java HotSpot Cryptographic Provider signature verification issue. And of course look here before: http://download.oracle.com/javase/6/docs/technotes/guides/security/crypto/HowToImplAProvider.html#Step61

No you can't authenticate it unless you write your own JVM. Otherwise request the JVM provider(Oracle) to sign your Jars.

Related

Java Diffie hellman initialize ECDHKeyAgreement

I have a Diffie–Hellman security class like this:
public class AESSecurityCap {
private PublicKey publicKey;
KeyAgreement keyAgreement;
byte[] sharedsecret;
AESSecurityCap() {
makeKeyExchangeParams();
}
private void makeKeyExchangeParams() {
KeyPairGenerator kpg = null;
try {
kpg = KeyPairGenerator.getInstance("EC");
kpg.initialize(128);
KeyPair kp = kpg.generateKeyPair();
publicKey = kp.getPublic();
keyAgreement = KeyAgreement.getInstance("ECDH");
keyAgreement.init(kp.getPrivate());
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
e.printStackTrace();
}
}
public void setReceiverPublicKey(PublicKey publickey) {
try {
keyAgreement.doPhase(publickey, false); // <--- Error on this line
sharedsecret = keyAgreement.generateSecret();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
}
}
and implemented this class:
public class Node extends AESSecurityCap {
}
Sometimes I need to reinitialize DH keyAgreement:
public class TestMainClass {
public static void main(String[] args) {
Node server = new Node();
Node client = new Node();
server.setReceiverPublicKey(client.getPublicKey());
client.setReceiverPublicKey(server.getPublicKey());
// My problem is this line ,
// Second time result exception
server.setReceiverPublicKey(client.getPublicKey());
}
}
but receive this exception:
Exception in thread "main" java.lang.IllegalStateException: Phase already executed
at jdk.crypto.ec/sun.security.ec.ECDHKeyAgreement.engineDoPhase(ECDHKeyAgreement.java:91)
at java.base/javax.crypto.KeyAgreement.doPhase(KeyAgreement.java:579)
at ir.moke.AESSecurityCap.setReceiverPublicKey(AESSecurityCap.java:37)
at ir.moke.TestMainClass.main(TestMainClass.java:13)
Is there any way to reinitialize ECDH KeyAgreement multiple time?
This is my test case:
Client initialize DH and generate public key.
Client sent public key to server.
Server initialize DH with client key and generate own public key and generate shared secret key.
Server send public key to client.
Client generate shared secret key with server public key.
In this step client and server has public keys and shared secret.
My problem is client disconnected() and KeyAgreement initialized by singleton object and don't reinitialized second time.
Sometimes I need to do this subject.
Please guide me to fix this problem.
The IllegalStateException (Phase already executed) seems to be especially caused by the ECDH-implementation of the SunEC-provider. The exception doesn't occur if an (additional) init is executed immediately before the doPhase. However, this init-call shouldn't be necessary, since after the doPhase-call generateSecret is executed, which should reset the KeyAgreement-instance to the state after the init-call, at least according to the generateSecret-documentation:
This method resets this KeyAgreement object to the state that it was in after the most recent call to one of the init methods...
Possibly it's a bug in the SunEC-provider. If DH is used instead of ECDH (and the SunJCE-provider instead of the SunEC-provider) the behavior is as expected, i.e. repeated doPhase-calls are possible (without additional init-calls). The same applies to ECDH using the BouncyCastle-provider. Therefore, you could take the BouncyCastle-provider instead of the SunEC-provider to run ECDH with your code.
Note: The second parameter (lastPhase) in doPhase should be set to true, otherwise an IllegalStateException (Only two party agreement supported, lastPhase must be true) is generated (at least for ECDH).
EDIT:
The bug is already known and fixed in JDK 12, see JDK-8205476: KeyAgreement#generateSecret is not reset for ECDH based algorithmm.

Query a server's certificates with BouncyCastle [duplicate]

I need to create an Https connection with a remote server then retrieve and verify the certificate.
I have established the connection fine:
try {
url = new URL(this.SERVER_URL);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
HttpsURLConnection secured = (HttpsURLConnection) con;
secured.connect();
}
But it seems getServerCertificateChain() method is undefined by the type HttpsURLConnection.
So how do I retrieve the server certificate chain? My understanding is that getServerCertificateChain() should return an array of X509Certificate objects and that this class has methods I can use to interrogate the certificate.
I need to verify that:
the certificate is valid and trusted,
check the Certificate Revocation List Distribution Point against the certificate serial number
make sure it isn't expired and
check that the URL in the certificate is matches another (which I already have retrieved ).
I'm lost and would really appreciate any help!
The method you want is getServerCertificates, not getServerCertificateChain. There is some nice sample code here.
EDIT
Added some sample code of my own. Good starting point for you. Don't forget to look at the Javadocs for HttpsURLConnection and X509Certificate.
import java.net.URL;
import java.security.cert.Certificate;
import java.security.cert.CertificateExpiredException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HttpsURLConnection;
public class TestSecuredConnection {
/**
* #param args
*/
public static void main(String[] args) {
TestSecuredConnection tester = new TestSecuredConnection();
try {
tester.testConnectionTo("https://www.google.com");
} catch (Exception e) {
e.printStackTrace();
}
}
public TestSecuredConnection() {
super();
}
public void testConnectionTo(String aURL) throws Exception {
URL destinationURL = new URL(aURL);
HttpsURLConnection conn = (HttpsURLConnection) destinationURL
.openConnection();
conn.connect();
Certificate[] certs = conn.getServerCertificates();
for (Certificate cert : certs) {
System.out.println("Certificate is: " + cert);
if(cert instanceof X509Certificate) {
try {
( (X509Certificate) cert).checkValidity();
System.out.println("Certificate is active for current date");
} catch(CertificateExpiredException cee) {
System.out.println("Certificate is expired");
}
}
}
}
}
Quick googling brought me to this example using BouncyCastle. I think it better answers the question.
http://www.nakov.com/blog/2009/12/01/x509-certificate-validation-in-java-build-and-verify-chain-and-verify-clr-with-bouncy-castle/
This sample code mentioned by Kirby and arulraj.net has been removed from Apache CXF in 2011 and did not support OCSP. The Apache PDFBox project "resurrected" this code and added OCSP support and more features that were missing in the original code, e.g. CRL signature check. Since release 2.0.13 the improved source code is available in the examples subproject, in the CertificateVerifier class. It is also available online with small improvements.
The code is not claiming to be perfect, and does not yet check whether the root is trusted. Development is tracked in JIRA issue PDFBOX-3017.

Java denying access to property permissions

new to parallel/distributed computing and having issues with a client-server program I'm trying to write. What's supposed to happen is the server receives an integer from the client and sends back the sum all the numbers leading up to it (ex, user enters 5, server calculates 1+2+3+4+5, server sends back 15). I'm still trying to figure it out, so I've hard coded the input on the client side.
This is what I have on the server side:
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;
import java.net.*;
import java.util.*;
public class Server {
public static void main(String[]args) {
try{
int port = 16790;
String host = "localhost";
CalculateSumServerImpl export = new CalculateSumServerImpl();
LocateRegistry.createRegistry(port);
String registryURL = "rmi://" + host + ":" + port + "/sum";
Naming.rebind(registryURL, export);
System.out.println("Server ready");
} catch (Exception e) {
e.printStackTrace();
}
} }
//to calculate the sum
import java.rmi.*;
import java.rmi.server.*;
public class CalculateSumServerImpl extends UnicastRemoteObject implements CalServerInterface {
public int n; //value entered
public int sum; //sum
protected CalculateSumServerImpl() throws RemoteException {
super();
}
#Override
public int calculateSum(int n) throws RemoteException {
n = (n*(n+1))/2; //sum of 1 + 2 + 3 + .. + n
sum = n;
return sum;
} }
//interface
import java.rmi.Remote;
public interface CalServerInterface extends Remote {
public int calculateSum(int n ) throws java.rmi.RemoteException;
}
And on the client side:
import java.rmi.*;
import java.util.PropertyPermission;
public class Client {
public static void main(String[]args) {
System.setSecurityManager(new java.rmi.RMISecurityManager());
System.setProperty("java.net.preferIPv4Stack" , "true");
try {
int port = 16790;
String host = "localhost";
String registryURL = "rmi://" + host + ":" + port + "/sum";
Project4ServerInterface obj = (Project4ServerInterface)Naming.lookup(registryURL);
System.out.println("Lookup completed.");
int output = obj.calculateSum(3);
System.out.println("Sum is: " + output);
} catch (Exception e) {
e.printStackTrace();
}
System.setProperty("java.net.preferIPv4Stack","true");
} }
And I've implemented the Interface on the client side as well.
The error that I've been getting on the client side is:
Exception in thread "main" java.security.AccessControlException: access denied ("java.util.PropertyPermission" "java.net.preferIPv4Stack" "write")
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
at java.security.AccessController.checkPermission(AccessController.java:884)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
at java.lang.System.setProperty(System.java:792)
at project04client.Client.main(Client.java:10)
with the error pointing to the line with this code:
System.setProperty("java.net.preferIPv4Stack" , "true");
Anyone have any experience trouble shooting this error?
Thanks!
The problem is that you have set a security manager for the entire (client) application that won't let you modify system properties.
The simple fix is to set the system properties you need to set before you set the RMI security manager.
Alternatively, you may be able to get rid of the System.setSecurityManager(...) call entirely. You (probably) only need it if you want the client to be able to download classes from your RMI service.
I tried setting the system property before the security manager and got an AccessControlException, denying socket permissions.
That doesn't make much sense. You would only get an AccessControlException if there was a security manager in place at that point. There shouldn't be ... unless this is applet code or similar launched in a web browser. Also, I don't know why a call to set a property would be denied saying that you don't have socket permissions.
When I took the security manager out completely, I got an UnmarshalException pointing to the interface.
You also need to add the classes / interfaces for the objects that tou will be unmarshalling to the client-side classpath.
Actually, I just noticed that the javadoc for RMISecurityManager says:
"RMISecurityManager implements a policy identical to the policy implemented by SecurityManager. RMI applications should use the SecurityManager class or another appropriate SecurityManager implementation instead of this class."

junit java.security.NoSuchAlgorithmException: Cannot find any provider supporting

I'm using JUnit 4 [C:\eclipse\plugins\org.junit_4.11.0.v201303080030\junit.jar] in combination with Eclipse (MARS, Version: Mars Milestone 3 (4.5.0M3) Build id: 20141113-0320.
I have some tests that test a simple class and which work well. But now arrived at the point where I wanted to test my encryption class, which implements the following encrypt function:
public String encrypt(String data) {
try {
SecretKeySpec KS = new SecretKeySpec(mKeyData, "Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish/CBC/ZeroBytePadding"); // PKCS5Padding
cipher.init(Cipher.ENCRYPT_MODE, KS, new IvParameterSpec(mIv));
return bytesToHex(cipher.doFinal(data.getBytes()));
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return null;
}
The Crypto class is not sub classed...
public class Crypto {
So to test this Class and more the encrypt function I have designed the following unit test:
package my.junit4.example;
import static org.junit.Assert.*;
import org.junit.Test;
public class CryptoTest {
#Test
public void testEncryption() {
Crypto myCrypto = new Crypto();
String encodedString = myCrypto.encrypt("Secret");
assertTrue("The decrypted encrypted word should deliver the original string", encodedString.equals(myCrypto.decrypt(encodedString)));
}
}
This test is failing with a stack trace:
java.security.NoSuchAlgorithmException: Cannot find any provider supporting Blowfish/CBC/ZeroBytePaddingnull
at javax.crypto.Cipher.getInstance(Cipher.java:535) at
my.junit.example.encrypt(Crypto.java:35) at
my.junit.example.CryptoTest.testEncrypt(CryptoTest.java:14) at
This didn't make much sense to me. But being relatively new to JUnit I suspect the issue is with me not understanding how to formulate these tests. The code works well encryption - decryption in my debugger is giving me the desired outcome. But how can I get this to work with JUnit. What obvious mistake I have made?
The problem is with this line:
Cipher cipher = Cipher.getInstance("Blowfish/CBC/ZeroBytePadding");
The algorithm you're requesting is not supported on your system. Any particular reason you want that specific one?
The docs specify the following default implementations:
AES/CBC/NoPadding (128)
AES/CBC/PKCS5Padding (128)
AES/ECB/NoPadding (128)
AES/ECB/PKCS5Padding (128)
DES/CBC/NoPadding (56)
DES/CBC/PKCS5Padding (56)
DES/ECB/NoPadding (56)
DES/ECB/PKCS5Padding (56)
DESede/CBC/NoPadding (168)
DESede/CBC/PKCS5Padding (168)
DESede/ECB/NoPadding (168)
DESede/ECB/PKCS5Padding (168)
RSA/ECB/PKCS1Padding (1024, 2048)
RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)
RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)
You need to add the Bouncy Castle provider to the Java runtime. You can see how to install the provider by looking at the Bouncy Castle wiki page. Neither the Blowfish algorithm nor zero padding is supported out of the box by Java installations.
The following runs fine on my box:
Security.addProvider(new BouncyCastleProvider());
byte[] mKeyData = new byte[16];
byte[] mIv = new byte[8];
SecretKeySpec KS = new SecretKeySpec(mKeyData, "Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish/CBC/ZeroBytePadding");
cipher.init(Cipher.ENCRYPT_MODE, KS, new IvParameterSpec(mIv));
Make sure that the provider is also available to the test framework when it is run. You'll need to put the bcprov-jdk15on-[version].jar in the class path of the runtime before you can install the provider.

Imported certificate to Java keystore, JVM ignores the new cert

I'm trying to get an application running on top of Tomcat 6 to connect to an LDAP server over SSL.
I imported certificate of the server to keystore using:
C:\Program Files\Java\jdk1.6.0_32\jre\lib\security>keytool -importcert -trustcacerts -file mycert -alias ca_alias -keystore "c:\Program Files\Java\jdk1.6.0_32\jre\lib\security\cacerts"
When I start Tomcat with SSL debugging turned on, according to logs Tomcat is using the correct certificate file:
trustStore is: C:\Program Files\Java\jdk1.6.0_32\jre\lib\security\cacerts
However, Tomcat does not add the cert I just imported - all other certs in the cacerts file are printed to the log - and connection fails:
handling exception: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Restarting Tomcat does not help. I have verified with keytool -list command that the new cert indeed exists on the file.
Why Tomcat keeps on ignoring my new cert?
EDIT:
Seems that the issue was caused by Windows 7 VirtualStore. Keytool created a new copy of the cacert file, and Tomcat used the original file.
JVM needs restart after importing certs to the keystore.
Check to see whether there is a key with the same CN information but a different alias.
I have had similar problems before when I tried to import a newer version of a certificate but left the older version in the keystore. My Java programs would simply find the first matching CN key in the keystore (which was the old expired one) and try to use that, even though there was a newer one which also matched the CN.
Also ensure that the authenticating Root certificate (and Intermediate certificate if applicable) exist in the keystore. If you're authenticating against one of the major security providers such as Verisign or Globalsign, they will usually provide you with the root and intermediate certificates. If these certificates exist in the keystore already, ensure they are still in validity. You need to have all the certificates from your personal certificate all the way down the authentication chain to the root, existing in your keystore, so that it understands how to validate your credentials.
What you described is exactly what I´ve been getting when using cmd.exe and a regular user although member of administrative group on a Windows Server. You have to start cmd.exe in administration mode to apply the changes in to cacerts files. At least on the Win2k8 OS´s.
If you do not do this carets will show you in the keytool.exe -list view the newly added certs but Tomcat won´t see them. Not sure why so. But when you do add it with cmd.exe started as Administrator Tomcat is fine with the newly added certs.
You can also use Djavax.net.debug="ssl,handshake" to see what Tomcat reads from cacerts file.
In my case I looked through so many things before I figured out what was wrong... I added the certificate to different keystores, I added all certificates in the chain (which is pointless btw), I downloaded the cert again for my own sanity and checked the serial number, and even inspected the downloaded cert to make sure it had all the correct information.
I ended up writing a TLS verifying client app in order to debug the issue. Not only did the remote server I was connecting to support only TLS 1.2 (disabled by default in my version of Java 7), the server also supported none of the ciphers that were enabled in my client. It turns out Java 7 had fewer than half of its supported ciphers enabled, many of them being really insecure and some of the most secure ones were disabled.
After some cross-checking, I came up with the following ordered list of TLS 1.2-supported secure ciphers:
new String[] {
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
"TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
"TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
"TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256",
"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_PSK_WITH_AES_256_GCM_SHA384",
"TLS_DHE_PSK_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256",
"TLS_DHE_RSA_WITH_AES_256_CCM",
"TLS_DHE_RSA_WITH_AES_128_CCM",
"TLS_DHE_PSK_WITH_AES_256_CCM",
"TLS_DHE_PSK_WITH_AES_128_CCM",
"TLS_CHACHA20_POLY1305_SHA256",
"TLS_AES_256_GCM_SHA384",
"TLS_AES_128_GCM_SHA256",
"TLS_AES_128_CCM_SHA256"
}
If there are any crypto experts around, feel free to update this list. I used Qualys SSL Labs, this Information Security SE answer, and IANA as my sources.
For those who want a sample of the source code I used, see below. I was using Apache Commons HttpClient 3.0, so you'll probably need to download the following binaries:
https://archive.apache.org/dist/httpcomponents/commons-httpclient/3.0/binary/commons-httpclient-3.0.1.zip
https://archive.apache.org/dist/commons/logging/binaries/commons-logging-1.0.4.zip
https://archive.apache.org/dist/commons/codec/binaries/commons-codec-1.3.zip
https://archive.apache.org/dist/commons/lang/binaries/commons-lang-2.6-bin.zip
TLS12SocketFactory.java
import java.io.*;
import java.net.*;
import java.util.*;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.*;
import org.apache.commons.lang.StringUtils;
public class TLS12SocketFactory implements SecureProtocolSocketFactory {
private final SecureProtocolSocketFactory base;
public TLS12SocketFactory()
{
this.base = (SecureProtocolSocketFactory)Protocol.getProtocol("https").getSocketFactory();
}
private Socket acceptOnlyTLS12(Socket socket)
{
if(socket instanceof javax.net.ssl.SSLSocket) {
final javax.net.ssl.SSLSocket s = (javax.net.ssl.SSLSocket)socket;
// Set TLS 1.2
s.setEnabledProtocols(new String[]{ "TLSv1.2" });
// Using recommended ciphers from https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#table-tls-parameters-4
List<String> recommended = new ArrayList(Arrays.asList(new String[]{ "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256", "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256", "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384", "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256", "TLS_DHE_RSA_WITH_AES_256_CCM", "TLS_DHE_RSA_WITH_AES_128_CCM", "TLS_DHE_PSK_WITH_AES_256_CCM", "TLS_DHE_PSK_WITH_AES_128_CCM", "TLS_CHACHA20_POLY1305_SHA256", "TLS_AES_256_GCM_SHA384", "TLS_AES_128_GCM_SHA256", "TLS_AES_128_CCM_SHA256" }));
recommended.retainAll(Arrays.asList(s.getSupportedCipherSuites()));
if(recommended.size() == 0) {
System.err.println("No supported modern ciphers. Update crypto policy or install JCE Unlimited Strength Jurisdiction Policy files." + System.lineSeparator());
} else if(recommended.size() < 3) {
System.out.println("Few supported modern ciphers. It's recommended to update crypto policy or install JCE Unlimited Strength Jurisdiction Policy files." + System.lineSeparator());
}
s.setEnabledCipherSuites(recommended.toArray(new String[0]));
// Log matched cipher and cert
s.addHandshakeCompletedListener(new javax.net.ssl.HandshakeCompletedListener() {
#Override
public void handshakeCompleted(javax.net.ssl.HandshakeCompletedEvent hce) {
String print = s.getInetAddress().getHostName() + System.lineSeparator() + hce.getCipherSuite() + System.lineSeparator();
try {
for(java.security.cert.Certificate cert : hce.getPeerCertificates()) {
List<String> certStrings = Arrays.asList(cert.toString().split("\r?\n"));
for(int line = 0; line < certStrings.size(); line++) {
if(certStrings.get(line).startsWith("Certificate Extensions:")) {
print += System.lineSeparator() + StringUtils.join(certStrings.subList(2, line-1), System.lineSeparator()) + System.lineSeparator();
break;
}
}
}
} catch (javax.net.ssl.SSLPeerUnverifiedException ex) {
print += "Non-certificate based cipher used" + System.lineSeparator();
}
System.out.println(print);
}
});
}
return socket;
}
#Override
public Socket createSocket(String host, int port) throws IOException
{
return acceptOnlyTLS12(base.createSocket(host, port));
}
#Override
public Socket createSocket(String host, int port, InetAddress localAddress, int localPort) throws IOException
{
return acceptOnlyTLS12(base.createSocket(host, port, localAddress, localPort));
}
#Override
public Socket createSocket(String host, int port, InetAddress localAddress, int localPort, HttpConnectionParams params) throws IOException
{
return acceptOnlyTLS12(base.createSocket(host, port, localAddress, localPort, params));
}
#Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException
{
return acceptOnlyTLS12(base.createSocket(socket, host, port, autoClose));
}
}
Main.java
import java.io.*;
import java.security.*;
import java.security.cert.*;
import java.util.*;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.*;
import org.apache.commons.httpclient.params.HttpClientParams;
public class Main {
public static void main(String[] args) {
List<java.net.URI> locations = new ArrayList<>();
for(String arg : args) {
java.net.URI location = java.net.URI.create(arg);
if(location.isAbsolute() && location.getScheme().equals("https")) {
locations.add(location);
} else {
System.out.println("Skipping invalid URL: " + arg);
}
}
System.out.println("Connecting to URL's");
System.out.println();
System.out.println("-------------------------");
TLS12SocketFactory tls12factory = new TLS12SocketFactory();
Protocol.registerProtocol("httpss", new Protocol("httpss", tls12factory, 443));
for(java.net.URI location : locations) {
System.out.println();
try {
// Form request
String tls12url = location.toString().replaceFirst("^https:", "httpss:");
HttpMethod method = new HeadMethod(tls12url);
// Send request
HttpClientParams params = new HttpClientParams();
params.setParameter(HttpClientParams.COOKIE_POLICY, CookiePolicy.IGNORE_COOKIES);
new HttpClient(params).executeMethod(method);
method.setFollowRedirects(true);
// Print response
System.out.println(location.toString());
System.out.println(method.getStatusLine().toString());
} catch (javax.net.ssl.SSLHandshakeException ex) {
System.out.println("There was an error making a secure connection to " + location.getHost());
ex.printStackTrace(System.out);
} catch (HttpException ex) {
System.out.println("There was an error with the external webpage");
ex.printStackTrace(System.out);
} catch (Exception ex) {
System.out.println("Could not complete request");
ex.printStackTrace(System.out);
}
}
System.out.println();
System.out.println("-------------------------");
System.out.println();
try {
// Load supported SSL Ciphers
System.out.println("Supported ciphers");
System.out.println();
System.out.println("-------------------------");
System.out.println();
javax.net.ssl.SSLSocket socket = (javax.net.ssl.SSLSocket)tls12factory.createSocket("www.google.com", 443);
for(String cipher : socket.getSupportedCipherSuites()) {
System.out.println(cipher);
}
System.out.println();
System.out.println("-------------------------");
System.out.println();
// Load enabled SSL Ciphers
System.out.println("Enabled ciphers");
System.out.println();
System.out.println("-------------------------");
System.out.println();
for(String cipher : socket.getEnabledCipherSuites()) {
System.out.println(cipher);
}
System.out.println();
System.out.println("-------------------------");
System.out.println();
// Load the JDK's cacerts keystore file
String filename = System.getProperty("java.home") + "/lib/security/cacerts".replace('/', File.separatorChar);
System.out.println("Loading keystore");
System.out.println(filename);
System.out.println();
System.out.println("-------------------------");
System.out.println();
FileInputStream is = new FileInputStream(filename);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
String password = "changeit";
keystore.load(is, password.toCharArray());
// This class retrieves the most-trusted CAs from the keystore
PKIXParameters params = new PKIXParameters(keystore);
// Get the set of trust anchors, which contain the most-trusted CA certificates
for (TrustAnchor ta : params.getTrustAnchors()) {
// Print certificate
System.out.println(ta.getTrustedCert());
}
} catch (CertificateException | KeyStoreException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | IOException ex) {
System.out.println("Could not load keystore");
ex.printStackTrace(System.out);
}
}
}

Categories