Importing existing SSL cert/key into openfire

I have an existing SSL cert/key via Comodo for my domain (tipit.to). I currently use it for my webserver and it works fine. I’d like to use SSL for openfire as well, but I’m having some problems importing the key. I’d like to reuse this cert/key for XMPP, running from the same domain. (yay for different ports!)

importing via the admin interface’s import-certificate feature: If I import the chain up to but not including my own cert, it gets imported, but, of course, this cert chain is not for ‘tipit.to’, but for Some comodo intermediate. If I append my personal cert to the chain from comodo and import that, or I just import my own cert with no chain, I get the following error: “There was an error one importing private key and signed certificate. Error message: signed overrun, bytes = 64”.

If I try a different tactic altogether, and I use the keytool KeyImporter from here: http://www.agentbob.info/agentbob/79-AB.html and re-assign the alias to ‘tipit.to’, change all passwords to the same thing, and reboot openfire, I get a fairly generic IOException on SSLInit:265, right after I log into the admin interface. No menu, nothing. The only way to get any sort of functionality back is by copying the ‘old’ keystore file back or reinstalling openfire altogether.

This is all on solaris, using the generic .tar.gz linux download of the latest official version.

If anyone could shed some light on what I’m doing wrong, I’d be very grateful.

NB: The installation procedure and admin interface, aside from this little faux pas, is -very- impressive. Excellent job!

Hey Reinier,

I found this KB document about a similar issue. Could you check out in your log files for the entire stack trace error and post it here? I would like to be able to reproduce this problem if possible to fix it.

Thanks,

– Gato

No problem. There are two distinct errors here so I’ll just post them both.

The generic IOException that occurs if I try to use the ImportKey java class I wrote about (not related to the KB issue):

2007.12.18 20:42:15 org.jivesoftware.openfire.http.HttpBindManager.createSSLConnector(HttpBindManage r.java:157) Error creating SSL connector for Http bind

java.io.IOException

at org.jivesoftware.openfire.net.SSLConfig.getKeyStore(SSLConfig.java:265)

at org.jivesoftware.openfire.http.HttpBindManager.createSSLConnector(HttpBindManag er.java:133)

at org.jivesoftware.openfire.http.HttpBindManager.configureHttpBindServer(HttpBind Manager.java:257)

at org.jivesoftware.openfire.http.HttpBindManager.start(HttpBindManager.java:89)

at org.jivesoftware.openfire.spi.ConnectionManagerImpl.startHTTPBindListeners(Conn ectionManagerImpl.java:505)

at org.jivesoftware.openfire.spi.ConnectionManagerImpl.startListeners(ConnectionMa nagerImpl.java:134)

at org.jivesoftware.openfire.spi.ConnectionManagerImpl.access$000(ConnectionManage rImpl.java:52)

at org.jivesoftware.openfire.spi.ConnectionManagerImpl$1.pluginsMonitored(Connecti onManagerImpl.java:106)

at org.jivesoftware.openfire.container.PluginManager.firePluginsMonitored(PluginMa nager.java:532)

at org.jivesoftware.openfire.container.PluginManager.access$800(PluginManager.java :46)

at org.jivesoftware.openfire.container.PluginManager$PluginMonitor.run(PluginManag er.java:1023)

at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)

at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:317)

at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:150)

at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101 (ScheduledThreadPoolExecutor.java:98)

at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPeriodi c(ScheduledThreadPoolExecutor.java:181)

at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Schedu ledThreadPoolExecutor.java:205)

at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java: 885)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)

at java.lang.Thread.run(Thread.java:619)

and this one which seems to have the same cause:

2007.12.18 20:42:14 org.jivesoftware.openfire.container.AdminConsolePlugin.startup(AdminConsolePlugi n.java:120)

java.io.IOException

at org.jivesoftware.openfire.net.SSLConfig.getKeyStore(SSLConfig.java:265)

at org.jivesoftware.openfire.container.AdminConsolePlugin.startup(AdminConsolePlug in.java:95)

at org.jivesoftware.openfire.container.AdminConsolePlugin.initializePlugin(AdminCo nsolePlugin.java:169)

at org.jivesoftware.openfire.container.PluginManager.loadPlugin(PluginManager.java :447)

at org.jivesoftware.openfire.container.PluginManager.access$300(PluginManager.java :46)

at org.jivesoftware.openfire.container.PluginManager$PluginMonitor.run(PluginManag er.java:1013)

at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)

at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:317)

at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:150)

at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101 (ScheduledThreadPoolExecutor.java:98)

at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPeriodi c(ScheduledThreadPoolExecutor.java:181)

at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Schedu ledThreadPoolExecutor.java:205)

at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java: 885)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)

at java.lang.Thread.run(Thread.java:619)

The exception I fished out of the logs about the signed overrun, which is what you were talking about in regards to the thawte KB:

java.security.cert.CertificateParsingException: signed overrun, bytes = 64

at sun.security.x509.X509CertImpl.parse(X509CertImpl.java:1712)

at sun.security.x509.X509CertImpl.(X509CertImpl.java:303)

at sun.security.provider.X509Factory.parseX509orPKCS7Cert(X509Factory.java:532)

at sun.security.provider.X509Factory.engineGenerateCertificates(X509Factory.java:4 17)

at java.security.cert.CertificateFactory.generateCertificates(CertificateFactory.j ava:427)

at org.jivesoftware.util.CertificateManager.installCert(CertificateManager.java:46 8)

at org.jivesoftware.openfire.admin.import_002dcertificate_jsp._jspService(import_0 02dcertificate_jsp.java:93)

at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)

at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)

at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.ja va:1093)

at com.opensymphony.module.sitemesh.filter.PageFilter.parsePage(PageFilter.java:11 8)

at com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:52)

at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.ja va:1084)

at org.jivesoftware.util.LocaleFilter.doFilter(LocaleFilter.java:65)

at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.ja va:1084)

at org.jivesoftware.util.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingF ilter.java:41)

at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.ja va:1084)

at org.jivesoftware.admin.PluginFilter.doFilter(PluginFilter.java:69)

at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.ja va:1084)

at org.jivesoftware.admin.AuthCheckFilter.doFilter(AuthCheckFilter.java:98)

at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.ja va:1084)

at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)

at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)

at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)

at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:712)

at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)

at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollect ion.java:211)

at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)

at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:139)

at org.mortbay.jetty.Server.handle(Server.java:313)

at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:506)

at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:844 )

at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:644)

at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:205)

at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:381)

at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:396)

at org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:442)

Using the keytool -import command from the thawte article results in the usual problem that there is no private key. I had a very quick look through the sources around CertificateManager:468 and java.security.cert.CertificateFactory, but the advice from thawte to use an explicit -alias does not seem to translate easily to the CertificateFactory; I couldn’t find any way to read in the certificate with an explicit alias.

I’m not sure the thawte article is relevant though. Thawte suggests to use:

keytool -import -alias -trustcacerts -file mycert.crt -keystore keystore

Just for kicks I tried keytool -import -file mycert.crt -keystore keystore, WITHOUT an -alias parameter, the exact thing the thawte article hints will solve the problem. This works just the same, and uses the default alias of ‘mykey’. Of some concern to myself is that in this case keytool STILL says the cert is for (CN=) EssentialSSL CA and not ‘tipit.to’.

Trying something else, I run into problems that the certificate chain can’t be established. Following directions from comodo to build up the cert chain in the keystore cert by cert, I end up with the following error in the admin interface of openfire:

java.security.InvalidKeyException: Supplied key (null) is not a RSAPrivateKey instance

at org.bouncycastle.jce.provider.JDKDigestSignature.engineInitSign(Unknown Source)

at java.security.Signature.initSign(Signature.java:480)

at org.bouncycastle.jce.PKCS10CertificationRequest.(Unknown Source)

at org.bouncycastle.jce.PKCS10CertificationRequest.(Unknown Source)

at org.jivesoftware.util.CertificateManager.createSigningRequest(CertificateManage r.java:331)

at org.jivesoftware.openfire.admin.ssl_002dcertificates_jsp._jspService(ssl_002dce rtificates_jsp.java:430)

at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)

at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)

at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.ja va:1093)

at com.opensymphony.module.sitemesh.filter.PageFilter.parsePage(PageFilter.java:11 8)

at com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:52)

at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.ja va:1084)

at org.jivesoftware.util.LocaleFilter.doFilter(LocaleFilter.java:65)

at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.ja va:1084)

at org.jivesoftware.util.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingF ilter.java:41)

at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.ja va:1084)

at org.jivesoftware.admin.PluginFilter.doFilter(PluginFilter.java:69)

at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.ja va:1084)

at org.jivesoftware.admin.AuthCheckFilter.doFilter(AuthCheckFilter.java:98)

at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.ja va:1084)

at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)

at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)

at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)

at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:712)

at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)

at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollect ion.java:211)

at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)

at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:139)

at org.mortbay.jetty.Server.handle(Server.java:313)

at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:506)

at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.j ava:830)

at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:514)

at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)

at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:381)

at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:396)

at org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:442)

which suggests that openfire wants a private key to accompany every cert, which might be overkill (but, I’m learning as I go here, by all means ignore me if I’m making stupid suggestions!)

These instructions are from: https://support.comodo.com/index.php?_m=knowledgebase&_a=viewarticle&kbarticleid =970&nav=0,1,83

But, It works now!

I copy/pasted all crt files into a single page, from specific-to-root order (starting with my own cert, then all the intermediates, ending with the root cert), which is from what I gathered more or less the wrong way around, but it imports properly. It uses a weird alias, but I renamed that with keytool.

I -still-get the following warning on the certs page: “One or more certificates are missing. Click here to generate self-signed certificates or here to import a signed certificate and its private key.”

However, https://myserver:9091/ now works without popups, so it seems to hold.

Thanks for posting all those stack traces. I will try to review them tomorrow.

which suggests that openfire wants a private key to accompany every cert, which might be overkill (but, I’m learning as I go here, by all means ignore me if I’m making stupid suggestions!)

The creator of the certificates (in this case Openfire) has to keep the private key that goes with the public key included in the certificate. That is why when you import a certificate created outside of Openfire (e.g. by a CA) you have to import the private key and the signed certificate.

But, It works now!

Good news.

I copy/pasted all crt files into a single page, from specific-to-root order (starting with my own cert, then all the intermediates, ending with the root cert), which is from what I gathered more or less the wrong way around, but it imports properly. It uses a weird alias, but I renamed that with keytool.

Certificates present in the chain can be actually stored in the truststore or the keystore. The way you imported the signed certificate pasting the other chain certificates works fine and will store all the certs in the keystore.

I -still-get the following warning on the certs page: “One or more certificates are missing. Click here to generate self-signed certificates or here to import a signed certificate and its private key.”

You can dismiss that warning message. Openfire expects to find an RSA and a DSA certificate in the keystore and if one of them is missing you get that warning message. Based on some discussion we had with StPeter in the Your Certificate Survival Kit blog it seems like Openfire should be fine with only RSA certs and not expect to have RSA and DSA certs.

However, https://myserver:9091/ now works without popups, so it seems to hold.

Yes, it will work fine and clients will work fine. Are you using RSA certs? I think that most XMPP clients will accept RSA certs so you should be fine.

Regards,

– Gato

The creator of the certificates (in this case Openfire) has to keep the private key that goes with the public key included in the certificate. That is why when you import a certificate created outside of Openfire (e.g. by a CA) you have to import the private key and the signed certificate.

Right, but, the intermediate certs, the ones that establish the chain from your cert+private key pair to some root or other, don’t need private keys. They just need to exist and match (or at least, that’s how I understand it). A private key is only needed for those certs which are going to be used as -the- certs served up by https + ssl XMPP. I think.

Yes, it will work fine and clients will work fine. Are you using RSA certs? I think that most XMPP clients will accept RSA certs so you should be fine.

Yup, RSA certs. Muchos gracias for the help!