Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Send certificate file with Scala Dispatch

I need to be able to send a certificate file (.pem, I think), with a get request using scala and dispatch.

How do you do that?

like image 700
user1491739 Avatar asked Nov 03 '22 16:11

user1491739


1 Answers

Based on the Java code in @sbridges sample, I came up with the following Scala code using dispatch. It creates a custom SSL context containing the certificates you provide (and only those; the default store of trusted root certificates is not used by this code when verifying the remote host).



    class SslAuthenticatingHttp(certData: SslCertificateData) extends Http {
      override val client = new AsyncHttpClient(
        (new AsyncHttpClientConfig.Builder).setSSLContext(buildSslContext(certData)).build
      )

      private def buildSslContext(certData: SslCertificateData): SSLContext = {
        import certData._

        val clientCertStore = loadKeyStore(clientCertificateData, clientCertificatePassword)
        val rootCertStore = loadKeyStore(rootCertificateData, rootCertificatePassword)

        val keyManagerFactory = KeyManagerFactory.getInstance("SunX509")
        keyManagerFactory.init(clientCertStore, clientCertificatePassword.toCharArray)
        val keyManagers = keyManagerFactory.getKeyManagers()

        val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
        trustManagerFactory.init(rootCertStore)
        val trustManagers = trustManagerFactory.getTrustManagers()

        val context = SSLContext.getInstance("TLS")
        context.init(keyManagers, trustManagers, null)

        context
      }

      private def loadKeyStore(keyStoreData: Array[Byte], password: String): KeyStore = {
        val store = KeyStore.getInstance(KeyStore.getDefaultType)
        store.load(new ByteArrayInputStream(keyStoreData), password.toCharArray)
        store
      }
    }

    case class SslCertificateData (
      clientCertificateData: Array[Byte],
      clientCertificatePassword: String,
      rootCertificateData: Array[Byte],
      rootCertificatePassword: String)

which would be used as in:



    val certificateData = SslCertificateData(/* bytes from .jks file for client cert here */, "secret!",
                                             /* bytes from .jks file for root cert here */, "also secret!")
    val http = new SslAuthenticatingHttp(certificateData)
    val page = http(req OK as.String)
    println(page())

Note that this keeps the certificate data in memory, which is not the most secure way to do it and consumes memory unnecessarily. It may in many cases be more suitable to store an InputStream or a filename in the SslCertificateData case class.

like image 50
reinierl Avatar answered Nov 15 '22 05:11

reinierl