I need to verify a signed xml document. As a part of the verification I need to check whether the certificate passed with the signed certificate is a trusted certificate.
All the trusted certificates are added to a keystore called trusted.keystore.
How can I check whether the certificate passed is a valid certificate?
I've wrote the following KeySelector, but it is not working
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.Iterator;
import javax.xml.crypto.AlgorithmMethod;
import javax.xml.crypto.KeySelector;
import javax.xml.crypto.KeySelectorException;
import javax.xml.crypto.KeySelectorResult;
import javax.xml.crypto.XMLCryptoContext;
import javax.xml.crypto.XMLStructure;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class X509KeySelector extends KeySelector {
private static Log log = LogFactory.getLog(X509KeySelector.class);
private KeyStore trustedStore;
public void setTrustedStore(KeyStore trustedStore) {
this.trustedStore = trustedStore;
}
#SuppressWarnings("rawtypes")
public KeySelectorResult select(KeyInfo keyInfo,
KeySelector.Purpose purpose, AlgorithmMethod method,
XMLCryptoContext context) throws KeySelectorException {
if (log.isDebugEnabled()) {
log.debug("Selecting key for algorithm: " + method.getAlgorithm());
}
Iterator ki = keyInfo.getContent().iterator();
while (ki.hasNext()) {
XMLStructure info = (XMLStructure) ki.next();
if (log.isDebugEnabled()) {
log.debug("Found xml structure: " + info.toString());
}
if (!(info instanceof X509Data)) {
if (log.isTraceEnabled()) {
log.trace("Ignoring xml structure since it is not a X509Data.");
}
continue;
}
X509Data x509Data = (X509Data) info;
Iterator xi = x509Data.getContent().iterator();
if (log.isDebugEnabled()) {
log.debug("Iterating X509Data: Size: "
+ x509Data.getContent().size());
}
while (xi.hasNext()) {
Object o = xi.next();
if (log.isDebugEnabled()) {
log.debug("Found object: " + o);
}
if (!(o instanceof X509Certificate)) {
if (log.isTraceEnabled()) {
log.trace("Ignoring object since it is not a X509Certificate");
}
continue;
}
X509Certificate cert = (X509Certificate) o;
if (!isTrustedCertificate(cert)) {
log.warn("Ignoring certificate since it is not a valid certificate. Certificate: "
+ cert);
continue;
}
final PublicKey key = cert.getPublicKey();
// Make sure the algorithm is compatible
// with the method.
if (algEquals(method.getAlgorithm(), key.getAlgorithm())) {
KeySelectorResult keySelectorResult = new KeySelectorResult() {
public Key getKey() {
return key;
}
};
return keySelectorResult;
} else {
log.warn("Ignoring certificate since the algorithms "
+ method.getAlgorithm() + " and "
+ key.getAlgorithm() + " does not match.");
}
}
}
log.error("Unable to find a valid certificate.");
throw new KeySelectorException("No key found!");
}
private boolean isTrustedCertificate(X509Certificate cert) {
if (trustedStore == null) {
return true;
}
boolean trusted = false;
try {
Enumeration<String> aliases = trustedStore.aliases();
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
Certificate[] certificates = this.trustedStore
.getCertificateChain(alias);
if (certificates == null) {
Certificate certificate = this.trustedStore
.getCertificate(alias);
if (certificate != null) {
certificates = new Certificate[] { certificate };
}
}
if (certificates != null) {
for (Certificate certificate : certificates) {
if (!(certificate instanceof X509Certificate)) {
continue;
}
if (cert.getSignature().equals(
((X509Certificate) certificate).getSignature())) {
trusted = true;
break;
}
}
if (trusted) {
break;
}
}
}
} catch (KeyStoreException e) {
log.error(e.toString(), e);
}
return trusted;
}
static boolean algEquals(String algURI, String algName) {
if ((algName.equalsIgnoreCase("DSA") && algURI
.equalsIgnoreCase(SignatureMethod.DSA_SHA1))
|| (algName.equalsIgnoreCase("RSA") && algURI
.equalsIgnoreCase(SignatureMethod.RSA_SHA1))) {
return true;
} else {
return false;
}
}
}
The problem lies in the method isTrustedCertificate. Where I'm iterating through all the aliases in the keystore and check where it is the same as the passed certificate.
As the class name suggests it deals with only X509 type certificates.
Thank you
There is a simpler way to check this using a method that might not be obvious to use at first. The KeyStore class has a method called getCertificateAlias(Certificate cert). If you pass in the certificate you are trying to check for and you do not get a null return, then that certificate is in the KeyStore.
Try something like this:
private boolean isTrustedCertificate(X509Certificate cert) {
if (trustedStore == null) {
return true;
}
boolean trusted = false;
try {
if (cert != null) {
// Only returns null if cert is NOT in keystore.
String alias = trustedStore.getCertificateAlias(cert);
if (alias != null) {
trusted = true;
}
}
} catch (KeyStoreException e) {
log.error(e.toString(), e);
}
return trusted;
}
I think I was going the wrong way,
I found the verify(PublicKey) method in Certificate object, which will java.security.SignatureException: Signature does not match. exception if the certificates does not match.
Related
I implemented a custom key manager, in order to choose which alias use when i need a ssl handshake.
The problem is that none of the methods of my custom key manager gets called, although it's correctly instantiated.
With a keystore containing just ONE alias, communication is fine and the code works, but the aim here is to have the possibility to change aliases during runtime.
Here is the full code of my implementation. Any Help is appreciated.
package ssl;
import java.net.Socket;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.X509ExtendedKeyManager;
import javax.net.ssl.X509KeyManager;
public class AliasSelectorKeyManager extends X509ExtendedKeyManager {
private X509KeyManager sourceKeyManager = null;
private String alias;
public AliasSelectorKeyManager(X509KeyManager keyManager, String alias) {
this.sourceKeyManager = keyManager;
this.alias = alias;
}
#Override
public String chooseEngineClientAlias(String[] paramArrayOfString, Principal[] paramArrayOfPrincipal, SSLEngine paramSSLEngine) {
return chooseClientAlias(paramArrayOfString, paramArrayOfPrincipal, null);
}
#Override
public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
boolean aliasFound = false;
//Get all aliases from the key manager. If any matches with the managed alias,
//then return it.
//If the alias has not been found, return null (and let the API to handle it,
//causing the handshake to fail).
for (int i = 0; i < keyType.length && !aliasFound; i++) {
String[] validAliases = sourceKeyManager.getClientAliases(keyType[i], issuers);
if (validAliases != null) {
for (int j = 0; j < validAliases.length && !aliasFound; j++) {
if (validAliases[j].equals(alias)) {
aliasFound = true;
}
}
}
}
if (aliasFound) {
return alias;
} else {
return null;
}
}
}
All this does is simply override each method calling the specific sourceKeyManager implementation. The customization comes into the two methods:
chooseEngineClientAlias;
chooseClientAlias
This is my SSL client main:
package ssl;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509KeyManager;
import javax.net.ssl.X509TrustManager;
public class SSLClientV2 {
public static void main(String[] args) {
String keyStoreType = "PKCS12";
String keyManagementAlgorithm = "SunX509";
String keyStorePassword = "password";
String keyStoreFileName = "C:/keystore.p12";
String protocolVersion = "TLSv1.2";
System.out.println("Key store File name.......: " + keyStoreFileName);
System.out.println("Key store type............: " + keyStoreType);
System.out.println("Key store Password........: " + keyStorePassword);
System.out.println("SSL Protocol..............: " + protocolVersion);
System.out.println("Key Management Algorithm..: " + keyManagementAlgorithm);
System.out.println(System.lineSeparator());
KeyStore keyStore = null;
KeyManagerFactory keyManagerFactory = null;
SSLContext sslContext = null;
try (FileInputStream keyStoreFile = new FileInputStream(keyStoreFileName)) {
System.out.println("Loading keystore...");
keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(keyStoreFile, keyStorePassword.toCharArray());
System.out.println("Keystore loaded successfully.");
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) {
System.out.println("ERROR: Could not load keystore.");
e.printStackTrace();
}
System.out.print(System.lineSeparator());
if (keyStore != null) {
try {
System.out.println("Initializing Key Manager Factory...");
keyManagerFactory = KeyManagerFactory.getInstance(keyManagementAlgorithm);
keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
System.out.println("Key Manager Factory initialized successfully.");
} catch (NoSuchAlgorithmException | UnrecoverableKeyException | KeyStoreException e) {
System.out.println("ERROR: Could not initialize Key Manager Factory.");
e.printStackTrace();
}
}
System.out.print(System.lineSeparator());
if (keyManagerFactory != null) {
try {
System.out.println("Initializing SSL Context...");
KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
TrustManager[] trustManagers = new TrustManager[] {
new X509TrustManager() {
#Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
#Override
public void checkServerTrusted(X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException {
}
#Override
public void checkClientTrusted(X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException {
}
}
};
for (int i = 0; i < keyManagers.length; i++) {
if (keyManagers[i] instanceof X509KeyManager) {
keyManagers[i] = new AliasSelectorKeyManager((X509KeyManager) keyManagers[i], "my.custom.alias");
System.out.println("Custom Key Manager loaded (#" + (i + 1) + ", class: " + keyManagers[i].getClass().getName() + ")");
}
}
sslContext = SSLContext.getInstance(protocolVersion);
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextInt();
sslContext.init(keyManagers, trustManagers, secureRandom);
System.out.println("SSL Context initialized successfully.");
} catch (KeyManagementException | NoSuchAlgorithmException e) {
System.out.println("ERROR: Could not initialize SSL Context.");
e.printStackTrace();
}
}
System.out.print(System.lineSeparator());
if (sslContext != null) {
try (SSLSocket socket = (SSLSocket) sslContext.getSocketFactory().createSocket("192.168.10.10", 1443)) {
System.out.println("Communication initialized, starting handshake...");
socket.startHandshake();
System.out.println("Handshake completed successfully.");
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
BufferedReader r = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String m = null;
System.out.print(System.lineSeparator());
String content = "Hello World";
System.out.println("Sending: " + content);
w.write(content);
w.flush();
System.out.println("Message received: ");
while ((m = r.readLine()) != null) {
System.out.println(m);
}
w.close();
r.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
please override also this method:
X509KeyManager::getClientAliases(String keyType, Principal[] issuers)
Has the needClientAuth flag been turned on the server side?
https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLEngine.html#setNeedClientAuth(boolean)
The server asks the client’s authentication during the handshake only if the flag is turned on.
In my java application I need to send POST requests to a server sitting behind https. On the machine where my java application is running there is a java trust store in: /usr/local/comp.jks that contains the certificate for the server I need to interact with (its already imported).
The problem is that I cannot control how the JVM is started that will run my java application - e.g. by adding:
-Djavax.net.ssl.trustStore=/usr/local/comp.jks to the VM arguments.
Is it possible to load the trust store in the above path at runtime from my application after the JVM has started so I can authenticate against the https site?
I have only found guides on how to import certificates at runtime but that I cannot use - also since I don't have the password for /usr/local/comp.jks
Below my current implementation (in groovy):
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException
import java.security.cert.X509Certificate
import java.util.Base64;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class HttpsClientImpl extends AbstractHttpClient {
private String username = null;
private String password = null;
public HttpsClientImpl (String username, String password) {
this.username=username;
this.password=password;
}
#Override
public String sendRequest(String request, String method) {
System.setProperty( "javax.net.ssl.trustStore", "/usr/local/comp.jks" );
URL url = new URL(request);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection()
// Set auth
byte[] name = (username + ":" + password).getBytes();
String authStr = Base64.getEncoder().encodeToString(name);
con.setRequestProperty("Authorization", "Basic " + authStr)
con.setRequestMethod(method);
writeResult(con);
return con.getResponseCode();
}
private void writeResult(HttpsURLConnection con) throws IOException {
if(con!=null){
BufferedReader br = null;
if (200 <= con.getResponseCode() && con.getResponseCode() <= 299) {
br = new BufferedReader(new InputStreamReader(con.getInputStream()));
} else {
br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
}
try {
String input;
while ((input = br.readLine()) != null){
System.out.println(input);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
When I run that I get:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
Caused: sun.security.validator.ValidatorException: PKIX path building failed
Assuming you haven't instantiated any SSL connections yet, you can simply call
System.setProperty( "javax.net.ssl.trustStore", "/usr/local/comp.jks" );
You'll probably also need to set javax.net.ssl.trustStorePassword and maybe javax.net.ssl.trustStoreType.
If the default SSL infrastructure has alredy been instantiated, you'll probably have to create your own SSLContext and SSLSocketFactory using your keystore.
You can load the truststore in you class. What I would suggest is to use both your truststore and load the JDK truststore and use both.
Here I am giving and example regarding how you can do it.
public class TrustManagerComposite implements X509TrustManager {
private final List<X509TrustManager> compositeTrustmanager;
public TrustManagerComposite() {
List<X509TrustManager> trustManagers = new ArrayList<>();
try (InputStream truststoreInput = PATH_TO_YOUR_TRUSTSTORE) {
trustManagers.add(getCustomTrustmanager(truststoreInput));
trustManagers.add(getDefaultTrustmanager());
} catch (Exception e) {
//log it
}
compositeTrustmanager = trustManagers;
}
private static X509TrustManager getCustomTrustmanager(InputStream trustStream) throws Exception {
return createTrustManager(trustStream);
}
private static X509TrustManager getDefaultTrustmanager() throws Exception {
return createTrustManager(null);
}
private static X509TrustManager createTrustManager(InputStream trustStream) throws Exception {
// Now get trustStore
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
// load the stream to your store
trustStore.load(trustStream, null);
// initialize a trust manager factory with the trusted store
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(trustStore);
// get the trust managers from the factory
TrustManager[] trustManagers = trustFactory.getTrustManagers();
for (TrustManager trustManager : trustManagers) {
if (trustManager instanceof X509TrustManager) {
return (X509TrustManager) trustManager;
}
}
return null;
}
#Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
for (X509TrustManager trustManager : compositeTrustmanager) {
try {
trustManager.checkClientTrusted(chain, authType);
return;
} catch (CertificateException e) {
// maybe the next trust manager will trust it, don't break the loop
}
}
throw new CertificateException("None of the TrustManagers trust this certificate chain");
}
#Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
for (X509TrustManager trustManager : compositeTrustmanager) {
try {
trustManager.checkServerTrusted(chain, authType);
return;
} catch (CertificateException e) {
// maybe the next trust manager will trust it, don't break the loop
}
}
throw new CertificateException("None of the TrustManagers trust this certificate chain");
}
#Override
public X509Certificate[] getAcceptedIssuers() {
List<X509Certificate> certs = new ArrayList<>();
for (X509TrustManager trustManager : compositeTrustmanager) {
for (X509Certificate cert : trustManager.getAcceptedIssuers()) {
certs.add(cert);
}
}
return certs.toArray(new X509Certificate[0]);
}
}
My problem is linked to this topic Calling Java from PLSQL causing oracle.aurora.vm.ReadOnlyObjectException
All of a sudden since today we are getting an error in our Production when a Java code is being executed from PLSQL, note that we have this error sometimes and don't know why, in past by deleting all classes and reloads them solved the issue but this time not :
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
java.version = 1.6.0_71
sonic_Client = 8.6.0
PROCEDURE LOG_AND_SEND_TO_QUEUE_PR(
msg VARCHAR2,
clientID VARCHAR2,
typeMessage VARCHAR2,
providerUrl VARCHAR2,
destination VARCHAR2,
usr VARCHAR2,
pwd VARCHAR2,
isTopic VARCHAR2,
ENABLED_HTTPS_ALGORITHM VARCHAR2 )
AS
LANGUAGE JAVA NAME 'jms.cxmessenger.SonicSender.doSend(java.lang.String, java.lang.String,java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)';
jms.cxmessenger.SecureTrustManager is set by System property used by SonicMQ client.
package jms.cxmessenger;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;
import java.util.NoSuchElementException;
import javax.naming.InvalidNameException;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
public class SecureTrustManager implements X509TrustManager {
private static final X509Certificate[] EMPTY_X509CERTIFICATE_ARRAY = new X509Certificate[0];
private CustomDefaultHostnameVerifier verifier = new CustomDefaultHostnameVerifier();
private TrustManager[] trustManagers;
{
try {
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
trustManagers = trustManagerFactory.getTrustManagers();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void check(X509Certificate[] chain, String authType) throws CertificateException {
boolean trusted = false;
if (chain.length > 0) {
for (TrustManager trustManager : trustManagers) {
try {
if (trustManager instanceof X509TrustManager) {
/* line 43 */ ((X509TrustManager) trustManager).checkServerTrusted(chain, authType);//line 43
trusted = true;
}
} catch (CertificateException e) {
}
}
}
if (!trusted && !Boolean.getBoolean("DEACTIVATE_HOSTNAME_VALIDATION")) {
checkCN(chain);
}
}
public X509Certificate[] getValidCertificates(X509Certificate[] chain, String peerHost) {
return verifier.getValidCertificates(chain, peerHost);
}
private void checkCN(X509Certificate[] chains) throws CertificateException {
if (Boolean.getBoolean("DEBUG")) {
System.out.println("checkCN(X509Certificate[] chains) : " + Arrays.toString(chains));
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < chains.length; i++) {
String cn = extractCN(chains[i].getIssuerX500Principal().getName());
if (cn == null) {
sb.append("\n\tFailed to authenticate Server CA : Name = "
+ chains[i].getIssuerX500Principal().getName());
} else {
return;
}
}
if (Boolean.getBoolean("DEBUG")) {
System.out.println("sb.toString : " + sb.toString());
}
throw new CertificateException(sb.toString());
}
private String extractCN(final String subjectPrincipal) {
if (subjectPrincipal == null) {
return null;
}
try {
final LdapName subjectDN = new LdapName(subjectPrincipal);
final List<Rdn> rdns = subjectDN.getRdns();
for (int i = rdns.size() - 1; i >= 0; i--) {
final Rdn rds = rdns.get(i);
final Attributes attributes = rds.toAttributes();
final Attribute cn = attributes.get("cn");
if (cn != null) {
try {
final Object value = cn.get();
if (value != null) {
return value.toString();
}
} catch (final NoSuchElementException ignore) {
} catch (final NamingException ignore) {
}
}
}
} catch (final InvalidNameException e) {
}
return null;
}
#Override
public void checkClientTrusted(X509Certificate[] certificates, String paramString) throws CertificateException {
for (X509Certificate certificate : certificates) {
certificate.checkValidity();
}
check(certificates, paramString);
}
#Override
public void checkServerTrusted(X509Certificate[] certificates, String paramString) throws CertificateException {
for (X509Certificate certificate : certificates) {
certificate.checkValidity();
}
check(certificates, paramString);
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return trustManagers != null && trustManagers.length > 0 && trustManagers[0] instanceof X509TrustManager
? ((X509TrustManager) trustManagers[0]).getAcceptedIssuers() : EMPTY_X509CERTIFICATE_ARRAY;
}
}
javax.net.ssl.SSLException: oracle.aurora.vm.ReadOnlyObjectException
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java) at
com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java)
at
com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java)
at
com.sun.net.ssl.internal.ssl.SSLSocketImpl.handleException(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 jms.cxmessenger.JSSESSLImpl.createSSLSocket(JSSESSLImpl.java) at
jms.cxmessenger.JSSESSLImpl.createSSLSocket(JSSESSLImpl.java:69) at
progress.message.net.ssl.ProgressSslSocket.(ProgressSslSocket.java)
at
progress.message.net.ssl.ProgressSslSocket.(ProgressSslSocket.java:163)
at
progress.message.net.ssl.ProgressSslSocketFactory.createProgressSocket(ProgressSslSocketFactory.java:172)
at
progress.message.net.ProgressSocketFactory.createProgressSocket(ProgressSocketFactory.java:180)
at
progress.message.zclient.Connection.openSocket(Connection.java:3660)
at
progress.message.zclient.Connection.connectWithRecoveryOpt(Connection.java)
at
progress.message.zclient.ReconnectHelper.connectAndChaseSingleFailoverRedirect(ReconnectHelper.java:534)
at
progress.message.zclient.ReconnectHelper.connect(ReconnectHelper.java)
at progress.message.zclient.Connection.connect(Connection.java:1585)
at progress.message.jimpl.Connection.(Connection.java:886) at
progress.message.jclient.ConnectionFactory.createConnection(ConnectionFactory.java:2316)
at jms.cxmessenger.SonicSender.doSend(SonicSender.java:73)
Caused by:
oracle.aurora.vm.ReadOnlyObjectException at
jms.cxmessenger.SecureTrustManager.check(SecureTrustManager.java:43)
at
jms.cxmessenger.SecureTrustManager.checkServerTrusted(SecureTrustManager.java)
at
com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java)
at
com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java)
at
com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java)
at
com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java)
at
com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java)
at
com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java)
... 16 more
Can some one help
Are you sure you got the right jar version?
I wouldn't expect jms.cxmessenger.* until cx messenger or sonic 2015(not sure).
cxmessenger is the latest version.
the problem was that there is some SYS Java classes missing !!
the public synonyms was there but there is no classes behind.
The solution was to reinstall the SYS Java classes and everything goes well!
I have a X509Certificate in java and I want to get the value of the Policy Identifier which there exists in the Certificate Policies field, as depicted in the following picture:
Also, I want to get the value of the Subject Type in Basic Constraints field, as depicted in the following picture:
My code:
public static void main(String[] args) throws Exception {
CertificateFactory cf = CertificateFactory.getInstance("X509");
InputStream in = new FileInputStream(new File("E:\\myCert.crt"));
X509Certificate cert = (X509Certificate) cf.generateCertificate(in);
int length = cert.getCertificateExtensionOIDs().size();
String oid;
for(int i = 0; i < length; i++){
oid = cert.getCertificateExtensionOIDs().iterator().next();
byte[] UID = cert.getExtensionValue(oid);
DERObject derObject = toDERObject(UID);
if(derObject instanceof DEROctetString){
DEROctetString derOctetString = (DEROctetString) derObject;
derObject = toDERObject(derOctetString.getOctets());
}
// here I think, I should use derObject to retrieve cert info but I don't know how!?
}
public static DERObject toDERObject(byte[] data) throws IOException {
ByteArrayInputStream inStream = new ByteArrayInputStream(data);
ASN1InputStream DIS = new ASN1InputStream(inStream);
return DIS.readObject();
}
Look at that code. A little more data validation code may be needed and you have to be careful checking basic constraints, because the condition below may not be enough in some cases.
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.x509.CertificatePolicies;
import org.bouncycastle.asn1.x509.PolicyInformation;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
/**
* 2016 krzysiek
*/
public class App {
private static final String CERTIFICATE_POLICY_OID = "2.5.29.32";
private static final String FILENAME = "/test.cer";
public static void main(String[] args) {
try {
X509Certificate cert = loadCertificate();
String policyIdentifier = getCertificatePolicyId(cert, 0, 0);
System.out.println("Policy Identifier: " + policyIdentifier);
String subjectType = getSubjectType(cert);
System.out.println("Subject Type: " + subjectType);
} catch (Exception e) {
System.out.println("Problem with certificate: " + e.getMessage());
}
}
private static String getSubjectType(X509Certificate cert) {
int pathLen = cert.getBasicConstraints();
if (pathLen == -1) {
if (cert.getKeyUsage()[5] || cert.getKeyUsage()[6]) { //simple check, there my be needed more key usage and extended key usage verification
return "Service";
} else {
return "EndEntity";
}
} else {
try {
cert.verify(cert.getPublicKey());
return "RootCA";
} catch (SignatureException | InvalidKeyException e) {
return "SubCA";
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
private static X509Certificate loadCertificate() {
try (InputStream in = new FileInputStream(App.class.getResource(FILENAME).getFile())) {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate certificate = cf.generateCertificate(in);
X509Certificate cert = (X509Certificate) certificate;
return cert;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static String getCertificatePolicyId(X509Certificate cert, int certificatePolicyPos, int policyIdentifierPos)
throws IOException {
byte[] extPolicyBytes = cert.getExtensionValue(CERTIFICATE_POLICY_OID);
if (extPolicyBytes == null) {
return null;
}
DEROctetString oct = (DEROctetString) (new ASN1InputStream(new ByteArrayInputStream(extPolicyBytes)).readObject());
ASN1Sequence seq = (ASN1Sequence) new ASN1InputStream(new ByteArrayInputStream(oct.getOctets())).readObject();
if (seq.size() <= (certificatePolicyPos)) {
return null;
}
CertificatePolicies certificatePolicies = new CertificatePolicies(PolicyInformation.getInstance(seq.getObjectAt(certificatePolicyPos)));
if (certificatePolicies.getPolicyInformation().length <= policyIdentifierPos) {
return null;
}
PolicyInformation[] policyInformation = certificatePolicies.getPolicyInformation();
return policyInformation[policyIdentifierPos].getPolicyIdentifier().getId();
}
}
pom.xml:
<properties>
<bouncycastle.version>1.54</bouncycastle.version>
</properties>
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>${bouncycastle.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcmail-jdk15on</artifactId>
<version>${bouncycastle.version}</version>
</dependency>
</dependencies>
I'm trying to access the private key of my certificate using the keystore.
Here's my code :
package test.java.com;
import java.security.Key;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
public class Main {
/**
* #param args
*/
public static void main(String[] args) {
KeyStore ks;
try {
ks = KeyStore.getInstance("Windows-MY");
ks.load(null, null);
Enumeration<String> en = ks.aliases();
while (en.hasMoreElements()) {
String aliasKey = (String) en.nextElement();
Certificate c = ks.getCertificate(aliasKey);
Key key = ks.getKey(aliasKey, "1753".toCharArray()); // Here I try to access the private key of my hardware certificate
byte[] bt = key.getEncoded();
if(bt != null) {
System.out.println("private key correctly accessed");
} else {
System.out.println("Can't access private key");
}
System.out.println("---> alias : " + aliasKey);
if (ks.isKeyEntry(aliasKey)) {
Certificate[] chain = ks.getCertificateChain(aliasKey);
System.out.println("---> chain length: " + chain.length);
X509Certificate Cert = null;
for (Certificate cert : chain) {
System.out.println(cert);
}
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
But when I try to get the private key (in order to sign data with it), the private key is null.
Am I doing it wrong ? How to sign data with that certificate using its private key ?
Note : I must use the keystore (I can't use the DLL of the hardware token driver because I could have many differents drivers coming to the server).
I finally got the answer from this post : Java security - MSCAPI provider: How to use without password popup?
String alias = "Alias to my PK";
char[] pass = "MyPassword".toCharArray();
KeyStore ks = KeyStore.getInstance("Windows-MY");
ks.load(null, pass);
Provider p = ks.getProvider();
Signature sig = Signature.getInstance("SHA1withRSA",p);
PrivateKey key = (PrivateKey) ks.getKey(alias, pass)
sig.initSign(key);
sig.update("Testing".getBytes());
sig.sign();
The private key is null unless it's a KeyEntry. You tried to get the private key out of a CertificateEntry, so you got an NPE. Just test the type of entry before you try for the private key: or, just test it for null, and if so, keep enumerating.