Skip to main content

JAXWS - WS-Security and keytool

15 replies [Last post]
marlor
Offline
Joined: 2006-02-15
Points: 0

Hello,

I am trying to get my certificates to work with WS-Security. (it works with Sun's example certificates)

I get the following error:
----------------------------------------------------
javax.xml.ws.WebServiceException: java.lang.RuntimeException: javax.xml.ws.WebServiceException: com.sun.xml.wss.XWSSecurityException: com.sun.org.apache.xml.internal.security.encryption.XMLEncryptionException: No installed provider supports this key: sun.security.provider.DSAPublicKeyImpl
----------------------------------------------------

First i created the keystores srv-keystore srv-truststore. Same for the client clt-keystore clt-truststore.
Just for my server certificate i made a CSR request and got a certificate from cacert.org. (not for client).
I exported the keys from the keystore's and imported it to the others truststore.
I left the encryption algorithm option etc default.

Any idea's what i could be doing wrong?

thanks

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
gunzothegreat
Offline
Joined: 2006-05-25
Points: 0

It would be better to be able to compile the code. If you want someone to have a look you should provide the dependencies such as imported code:
import com.cardinal.util.CertConfig;
import com.cardinal.util.X509V3CertificateGenerator;

kumarjayanti
Offline
Joined: 2003-12-10
Points: 0

Please post all WS-Security questions to users@xwss.dev.java.net. Also please register yourself as an observer at the XWSS project at xwss.dev.java.net

From your code, it appears you only changed the server-keystore and client-truststore or have you actually changed all the keys in all the stores ?.

Here is the code that is used in WS-Security to compute the Subject Key Identifiers. (If you open any of the SecurityEnvironmentHandler.java file from /xws-security/samples dir, you will see this code).

private static byte[] getSubjectKeyIdentifier(X509Certificate cert) {
String SUBJECT_KEY_IDENTIFIER_OID = "2.5.29.14";
byte[] subjectKeyIdentifier =
cert.getExtensionValue(SUBJECT_KEY_IDENTIFIER_OID);
if (subjectKeyIdentifier == null)
return null;

try {
sun.security.x509.KeyIdentifier keyId = null;

sun.security.util.DerValue derVal = new sun.security.util.DerValue(
new sun.security.util.DerInputStream(subjectKeyIdentifier).getOctetString());

keyId = new sun.security.x509.KeyIdentifier(derVal.getOctetString());
return keyId.getIdentifier();
} catch (NoClassDefFoundError ncde) {
if (subjectKeyIdentifier == null)
return null;
byte[] dest = new byte[subjectKeyIdentifier.length - 4];
System.arraycopy(
subjectKeyIdentifier, 4, dest, 0, subjectKeyIdentifier.length - 4);
return dest;
} catch ( java.io.IOException ex) {
//ignore
return null;
}
}

Can you write a small peice of code where you compute the SKI for the client cert (from the client-keystore) using the above method and try to find the corresponding SKI in your server-truststore.

And repeat the same thing, compute the SKI for your server cert (from client-truststore) and try to find the corresponding SKI in your server-keystore

The method for finding the corresponding SKI in the store is below. Once you are able to run your program successfully you can be sure that there is no issue with your modified keystores and truststores. Once that is done , it will either point to some kind of setup issue or a bug with XWSS. We will then take it from there :

private X509Certificate getCertificateUsingSKI(KeyStore trustStore, byte[] ski)
throws IOException {

try {
Enumeration aliases = trustStore.aliases();
while (aliases.hasMoreElements()) {
String alias = (String) aliases.nextElement();
Certificate cert = trustStore.getCertificate(alias);
if (cert == null || !"X.509".equals(cert.getType())) {
continue;
}
X509Certificate x509Cert = (X509Certificate) cert;
byte[] keyId = getSubjectKeyIdentifier(x509Cert);
if (keyId == null) {
// Cert does not contain a key identifier
continue;
}
if (Arrays.equals(ski, keyId)) {
return x509Cert;
}
}
} catch (Exception e) {
throw new IOException(e.getMessage());
}
return null;
}

Thanks.

barnaby33
Offline
Joined: 2006-04-27
Points: 0

I have created the certificates, and written them to the corresponding truststores. The problem seems to be that the Subject Key Identifier isn't correct. Did you have any problems with that?

Did you generate your keys programatically? I am so far using keys generated in Keytool.

marlor
Offline
Joined: 2006-02-15
Points: 0

That's the problem with keytool. It will generate X509 version 1 certificate instead of the latest version 3.

The version 1 certificate keytool generates does not include the "Subject Key Identifier" certificate extension which is needed by the SecurityEnvironmentHandler classes in the xws-security examples.

>> Did you generate your keys programatically? I am so far using keys generated in Keytool.

Yes, I wrote util classes to generate/manage keystores and certificates.
I think an alternative would be to use the openssl tool which generates version 3 certificates with "Subject Key Identifier" extension. But no guarantees, i haven't tried openssl tool.

kumarjayanti
Offline
Joined: 2003-12-10
Points: 0

openssl does work. Have you tried using the tool CA.sh which is normally available with openssl installation. It makes things easier than directly having to use openssl commands.

Please post questions realting to WS-Security to
users@xwss.dev.java.net

Thanks

barnaby33
Offline
Joined: 2006-04-27
Points: 0

Can't say I have this has gotten quite frustrating. I am usuing the bouncy castle API to generate an RSA keypair, and X.509 V3 Certificate and then writing them to the respective keystore and truststore for the XWSS security sample apps, when I run them though I am continuing to have the same problem. Namely that the security key identifier coming in the client request, can't seem to be matched to that value to the key pair inserted into the server keystore. Both are being created by me, I am also associating the generated certificate as the certificate chain entry when the key is inserted into the keystore. Obviously I am doing something wrong, I just don't know what.

If someone would take a look, here is the main class.

/*
* Main.java
*
* Created on April 28, 2006, 1:42 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/

package certgen;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.FileInputStream;
import java.util.Arrays;

import java.util.Date ;

import java.math.BigInteger;

import java.security.KeyStoreException;
import java.security.InvalidKeyException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.Security;
import java.security.Provider;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;

import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.KeyStore;
import java.security.KeyFactory;
import java.security.KeyPairGenerator;
import java.security.KeyPair;
import java.security.Key;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.KeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.InvalidKeySpecException;

import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.KeyUsage;

import com.cardinal.util.CertConfig;
import com.cardinal.util.X509V3CertificateGenerator;

/**
*
* @author jgelb
*/
public class Main
{
//Bouncy Castle crypto provider.
public static final String PROVIDER = "BC";
//algorithm used to sign the certs
public static final String SIGNATURE_ALG = "MD5WITHRSA";
public static final String KEY_ALG = "RSA";
public static final int KEY_LEN = 1024;

//cert validity from start date in days.
public static final int VALIDITY= 365;

//parameters passed in on the command line
public static String INPUT_KEYSTORE = "server-keystore.jks";
public static String OUTPUT_KEYSTORE = "client-truststore.jks";
public static String KEYSTORE_PASS = "changeit";
public static String ALIAS = "s1as";
public static String DISTINGUISHED_NAME = "Server";
/** Creates a new instance of Main */
public Main()
{
}

/**
* @param args the command line arguments
*

* input keystore path ../somedir/inputkeystore.jks
* output keystore path ../somedir/outputkeystore.jks
* keystore password
* keypair alias
* Certificate Distinguished Name IE "Server" or "Client"
*

*/
public static void main(String[] args)
{
try
{
if(args.length != 5)
System.out.println("5 arguments are required, only :" + args.length + " are supplied.");
INPUT_KEYSTORE = args[0];
OUTPUT_KEYSTORE = args[1];
KEYSTORE_PASS = args[2];
ALIAS = args[3];
DISTINGUISHED_NAME = args[4];

System.out.println("Preparing to generate key(s) for alg: " + KEY_ALG + " of length: " + KEY_LEN);
KeyPairGenerator keyGen = KeyPairGenerator.getInstance(KEY_ALG);
keyGen.initialize(KEY_LEN);
KeyPair keypair = keyGen.generateKeyPair();
System.out.println("Keys generated.");
PrivateKey privKey = keypair.getPrivate();
PublicKey pubKey = keypair.getPublic();

System.out.println("Setting up certificate for keypair.");
X509V3CertificateGenerator certBuilder = new X509V3CertificateGenerator();
certBuilder.setSignatureAlgorithm(SIGNATURE_ALG);
certBuilder.setPublicKey(pubKey);
certBuilder.setSerialNumber(new BigInteger("2"));
certBuilder.setSubjectDN(CertConfig.buildX509Name(DISTINGUISHED_NAME));
certBuilder.setIssuerDN(CertConfig.buildX509Name(DISTINGUISHED_NAME));
Date validityBeginDate = new Date(System.currentTimeMillis());
Date validityEndDate = new Date(validityBeginDate.getTime() + (VALIDITY * (24 * 60 * 60 * 1000)));
certBuilder.setNotBefore(validityBeginDate);
certBuilder.setNotAfter(validityEndDate);
BasicConstraints bc = new BasicConstraints(true);
certBuilder.addExtension(X509Extensions.BasicConstraints.getId(), true, bc);
certBuilder.addExtension(X509Extensions.SubjectKeyIdentifier.getId(),
false, CertConfig.generateSubjectKeyIdentifier(pubKey));
System.out.println("Generating Certificate");
X509Certificate x509Cert = certBuilder.generateX509Certificate(privKey, PROVIDER);
System.out.println("X509 V3 Certificate generated.");

Certificate[] certChain = new Certificate[] {x509Cert};

KeyStore inKeyStore = KeyStore.getInstance("JKS");
inKeyStore.load(new FileInputStream(INPUT_KEYSTORE), KEYSTORE_PASS.toCharArray());
System.out.println("Loading keystore from file: " + INPUT_KEYSTORE + " password:" + KEYSTORE_PASS);
inKeyStore.setKeyEntry(ALIAS, privKey, KEYSTORE_PASS.toCharArray(), certChain);
System.out.println("Private key entry: " + ALIAS + " to: " + INPUT_KEYSTORE);

//write the cert out to the receiving keystore.
KeyStore outKeyStore = KeyStore.getInstance("JKS");
System.out.println("Loading out put keystore: " + OUTPUT_KEYSTORE);
outKeyStore.load(new FileInputStream(OUTPUT_KEYSTORE), KEYSTORE_PASS.toCharArray());
outKeyStore.setCertificateEntry(ALIAS, x509Cert);
System.out.println("Certificate entry: " + ALIAS + " to : " + OUTPUT_KEYSTORE);

System.out.println("Writing Keystore back to file: " + INPUT_KEYSTORE);
FileOutputStream fos = new FileOutputStream(INPUT_KEYSTORE);
inKeyStore.store(fos, KEYSTORE_PASS.toCharArray());

System.out.println("Writing Keystore back to file: " + OUTPUT_KEYSTORE);
fos = new FileOutputStream(OUTPUT_KEYSTORE);
outKeyStore.store(fos, KEYSTORE_PASS.toCharArray());

}
catch (InvalidKeyException ex)
{
ex.printStackTrace();
}
catch (NoSuchProviderException ex)
{
ex.printStackTrace();
}
catch (SignatureException ex)
{
ex.printStackTrace();
}
catch (NoSuchAlgorithmException ex)
{
ex.printStackTrace();
} catch (KeyStoreException ex)
{
ex.printStackTrace();
} catch (FileNotFoundException ex)
{
ex.printStackTrace();
} catch (CertificateException ex)
{
ex.printStackTrace();
} catch (IOException ex)
{
ex.printStackTrace();
}
}

}

marlor
Offline
Joined: 2006-02-15
Points: 0

Hi,

I don't know what: CertConfig.generateSubjectKeyIdentifier(pubKey)
does for you when you add the extension. Does it return a new org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure?

if not, try this

certBuilder.addExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(pubKey));

barnaby33
Offline
Joined: 2006-04-27
Points: 0

Ok downloaded and installed bouncy castle provider, then found a UI tool, an associated project (Key Tool IUI Plus), but it didn't seem to work either. How exactly were you able to create and sign keypairs that the examples would accept? Thanks in advance
Josh

marlor
Offline
Joined: 2006-02-15
Points: 0

I have this book "Beginning Cryptography with Java". From that book and some google searching I learned the basics of it. And I wrote my own util classes to manage certificates and keystores to make it easier for myself to use in different applications.

I made the util classes more specific to our needs. For example: acting as a Certificate Authoriry I wouldn't want to generate anything more or less than RSA 1024 for the keypair.

regards

barnaby33
Offline
Joined: 2006-04-27
Points: 0

I figured you were going to say something like that. I spent most of friday trying to do the same. I am trying to code a class which will take a generated keypair create the cert self sign it with the Subject Key Identifier that the xwss configuration seems to want and write that cert back to the keystore. If you know of any hidden caveats or gotchas, that would be much appreciated.

Josh

kumarjayanti
Offline
Joined: 2003-12-10
Points: 0

Hi,

From the exception it appears that you have DSA Keys inside your keystores. The Default algorithms configured in XWS-Security is RSA. So what you need to do is change the security config file Sign elements to have the SignatureMethod specifed as dsa-sha1.



Let us know if this helps. Otherwise send us your configuration files, exact stacj trace and also confirm whether your keys are RSA keys or DSA Keys.

> Hello,
>
> I am trying to get my certificates to work with
> WS-Security. (it works with Sun's example
> certificates)
>
> I get the following error:
> ----------------------------------------------------
> javax.xml.ws.WebServiceException:
> java.lang.RuntimeException:
> javax.xml.ws.WebServiceException:
> com.sun.xml.wss.XWSSecurityException:
> com.sun.org.apache.xml.internal.security.encryption.XM
> LEncryptionException: No installed provider supports
> this key: sun.security.provider.DSAPublicKeyImpl
> ----------------------------------------------------
>
> First i created the keystores srv-keystore
> srv-truststore. Same for the client clt-keystore
> clt-truststore.
> Just for my server certificate i made a CSR request
> and got a certificate from cacert.org. (not for
> client).
> I exported the keys from the keystore's and imported
> it to the others truststore.
> I left the encryption algorithm option etc default.
>
> Any idea's what i could be doing wrong?
>
> thanks

marlor
Offline
Joined: 2006-02-15
Points: 0

Hello,

Thanks for the reply.

Yes RSA does help the solution BUT.
The problem is that keytool generates version 1 X509 Certificates which doesn't seem to include "Subject Key Identifier" certificate extension. When using the XWS-Security examples with your own generated (with keytool) certificates and keystores, you will get an error saying that the certificate extension is missing.

I think it should work with openssl tool but I didn't want to bother with that.

I wrote my own certificate/keystore handler API with the help of Sun and bouncycastle API's. This way you can add any extension you need.

regards

barnaby33
Offline
Joined: 2006-04-27
Points: 0

HOw did you end up solving this problem? I am having exactly the same issue. Did you find a way to generate the cert correctly, or add the SKI?
Josh

marlor
Offline
Joined: 2006-02-15
Points: 0

hello barnaby,

I used the bouncycastle lib to manage my certificates and keystores. Works perfect till now. You can create V3 certificates, add certificate extensions, ..

barnaby33
Offline
Joined: 2006-04-27
Points: 0

Is this a programmatic API, or an app supplied by sun?
Josh