Configuration problem for https Spray server with self-signed certificate?

I use Spray 1.3, Akka 2.3, and Scala 2.11 on Mac 10.9.4 to configure an HTTP server. I follow Ch. 2 in Manning Akka in action (sample code is available here: https://github.com/RayRoestenburg/akka-in-action.git ), which compiles, runs, and behaves as expected when I use http, but have I'm having trouble setting it up for use with https.

To run using https, I created a self-signed certificate as follows:

keytool -genkey -keyalg RSA -alias selfsigned -keystore myjks.jks -storepass abcdef -validity 360 -keysize 2048

Following this example, https://github.com/spray/spray/tree/v1.2-M8/examples/spray-can/simple-http-server/src/main/scala/spray/examples

I added an SSL configuration class:

 package com.goticks import java.security.{SecureRandom, KeyStore} import javax.net.ssl.{KeyManagerFactory, SSLContext, TrustManagerFactory} import spray.io._ // for SSL support (if enabled in application.conf) trait MySSLConfig { // if there is no SSLContext in scope implicitly the HttpServer uses the default SSLContext, // since we want non-default settings in this example we make a custom SSLContext available here implicit def sslContext: SSLContext = { val keyStoreResource = "myjks.jks" val password = "abcdef" val keyStore = KeyStore.getInstance("jks") keyStore.load(getClass.getResourceAsStream(keyStoreResource), password.toCharArray) val keyManagerFactory = KeyManagerFactory.getInstance("SunX509") keyManagerFactory.init(keyStore, password.toCharArray) val trustManagerFactory = TrustManagerFactory.getInstance("SunX509") trustManagerFactory.init(keyStore) val context = SSLContext.getInstance("TLS") context.init(keyManagerFactory.getKeyManagers, trustManagerFactory.getTrustManagers, new SecureRandom) context } // if there is no ServerSSLEngineProvider in scope implicitly the HttpServer uses the default one, // since we want to explicitly enable cipher suites and protocols we make a custom ServerSSLEngineProvider // available here implicit def sslEngineProvider: ServerSSLEngineProvider = { ServerSSLEngineProvider { engine => engine.setEnabledCipherSuites(Array("TLS_RSA_WITH_AES_256_CBC_SHA")) engine.setEnabledProtocols(Array("SSLv3", "TLSv1")) engine } } } 

I updated the main class to use the SSL configuration:

 package com.goticks import akka.actor._ import akka.io.IO import spray.can.Http import spray.can.server._ import com.typesafe.config.ConfigFactory object Main extends App with MySSLConfig { val config = ConfigFactory.load() val host = config.getString("http.host") val port = config.getInt("http.port") implicit val system = ActorSystem("goticks") val api = system.actorOf(Props(new RestInterface()), "httpInterface") IO(Http) ! Http.Bind(listener = api, interface = host, port = port) } 

and I updated application.conf:

 spray { can { server { server-header = "GoTicks.com REST API" ssl-encryption = on } } } 

After compiling and starting the server, I get the following error when I try to execute https GET:

 [ERROR] [09/15/2014 10:40:48.056] [goticks-akka.actor.default-dispatcher-4] [akka://goticks/user/IO-HTTP/listener-0/7] Aborting encrypted connection to localhost/0:0:0:0:0:0:0:1%0:59617 due to [SSLHandshakeException:no cipher suites in common] -> [SSLHandshakeException:no cipher suites in common] 

I am not sure if my problem is related to the generated key or to my configuration. By the way, my final goal is to use this configuration with a TCP socket (see My other question: SSL TCP socket on Scala with Akka ), but I couldn’t find the documentation for working with secure TCP, so I thought I would start with Https

Any help is appreciated.

+6
source share
2 answers

Finally, I was able to get it to work using Apache Camel as recommended here . It seems too much to bring Camel just to create an SSLContext, but this is what finally worked.

My SSLConfig looked like this:

 import javax.net.ssl.SSLContext import spray.io._ import org.apache.camel.util.jsse._ trait MySSLConfig { implicit def sslContext: SSLContext = { //val keyStoreFile = "/Users/eschow/repo/services/jks/keystore.jks" val keyStoreFile = "/Users/eschow/code/scala/akka-in-action/chapter2/myjks.jks" val ksp = new KeyStoreParameters() ksp.setResource(keyStoreFile); ksp.setPassword("abcdef") val kmp = new KeyManagersParameters() kmp.setKeyStore(ksp) kmp.setKeyPassword("abcdef") val scp = new SSLContextParameters() scp.setKeyManagers(kmp) val context= scp.createSSLContext() context } implicit def sslEngineProvider: ServerSSLEngineProvider = { ServerSSLEngineProvider { engine => engine.setEnabledCipherSuites(Array("TLS_RSA_WITH_AES_256_CBC_SHA")) engine.setEnabledProtocols(Array("SSLv3", "TLSv1")) engine } } } 

By the way, the errors recorded by Camel were much more useful. Doing something stupid, like a bad path to the cornerstone or the wrong password, gives meaningful, human-readable errors, rather than the quiet refusal I saw earlier.

+5
source

If you want to read the keystore file outside the project, you can use

 new FileInputStream("/Users/eschow/code/scala/akka-in-action/chapter2/myjks.jks") 

otherwise, you need to put the file in the project resources folder, for example. / your _project / src / main / resource and read it

 getClass.getResourceAsStream("/myjks.jks") 
+1
source

Source: https://habr.com/ru/post/975308/


All Articles