获得证书后,如何从中生成JKS密钥存储区?
如何配置Play应用程序以使用此密钥库?
我需要做的其他事情吗?
答案 0 :(得分:13)
以下是获取(更新)letsencrypt证书的脚本:
#!/bin/bash
/path/to/your/app/stop # stop the play application; especially if it is running on port 80 otherwise the certificate generation will fail
rm -rf /etc/letsencrypt.bak
mv /etc/letsencrypt /etc/letsencrypt.bak
./letsencrypt-auto certonly --standalone -n -m email@example.com --agree-tos -d example.com -d www.example.com
cd /etc/letsencrypt/live/example.com
openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out cert_and_key.p12 -CAfile chain.pem -caname root -passout pass:your_password
keytool -importkeystore -srcstorepass your_password -destkeystore keyStore.jks -srckeystore cert_and_key.p12 -srcstoretype PKCS12 -storepass your_password
/path/to/your/app/start # start the application
您可以安排cron作业定期运行此脚本,因为letsencrypt证书目前在90天后过期。
获得证书后,您需要按如下方式修改应用程序启动脚本:
/path/to/your/app/app_name_script -Dhttps.port=443 -Dplay.server.https.keyStore.path=/etc/letsencrypt/live/example.com/keyStore.jks -Dplay.server.https.keyStore.password=your_password -Djdk.tls.ephemeralDHKeySize=2048 -Djdk.tls.rejectClientInitiatedRenegotiation=true # ... more parameters if required
几乎就在那里。当您运行该应用程序时,您会从SSL Labs获得 A - 评级。评级降级与Forward Secrecy相关。为了理清前向保密问题(并获得完整的 A 评级),您需要通过实施自定义SSLEngineProvider来指定密码套件的顺序:
package controllers
import java.nio.file._
import java.security.KeyStore
import javax.net.ssl._
import play.core.ApplicationProvider
import play.server.api._
class CustomSslEngineProvider(appProvider: ApplicationProvider) extends SSLEngineProvider {
val priorityCipherSuites = List(
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA")
def readPassword(): Array[Char] = System.getProperty("play.server.https.keyStore.password").toCharArray
def readKeyInputStream(): java.io.InputStream = {
val keyPath = FileSystems.getDefault.getPath(System.getProperty("play.server.https.keyStore.path"))
Files.newInputStream(keyPath)
}
def readKeyManagers(): Array[KeyManager] = {
val password = readPassword()
val keyInputStream = readKeyInputStream()
try {
val keyStore = KeyStore.getInstance(KeyStore.getDefaultType)
keyStore.load(keyInputStream, password)
val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm)
kmf.init(keyStore, password)
kmf.getKeyManagers
} finally {
keyInputStream.close()
}
}
def createSSLContext(): SSLContext = {
val keyManagers = readKeyManagers()
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(keyManagers, Array.empty, null)
sslContext
}
override def createSSLEngine(): SSLEngine = {
val ctx = createSSLContext()
val sslEngine = ctx.createSSLEngine
val cipherSuites = sslEngine.getEnabledCipherSuites.toList
val orderedCipherSuites =
priorityCipherSuites.filter(cipherSuites.contains) ::: cipherSuites.filterNot(priorityCipherSuites.contains)
sslEngine.setEnabledCipherSuites(orderedCipherSuites.toArray)
val params = sslEngine.getSSLParameters
params.setUseCipherSuitesOrder(true)
sslEngine.setSSLParameters(params)
sslEngine
}
}
不要忘记设置
play.server.https.engineProvider = controllers.CustomSslEngineProvider
在您的 application.conf 。
中使用Play 2.5.x进行测试
答案 1 :(得分:2)
我在各种论坛中进行了搜索,最后我想到了一个非常快速(几乎自动化)的解决方案: 首先,如他们建议在letsencrypt网站上一样,运行以下命令:
sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot
然后运行
sudo certbot certonly --standalone -d domain.name.com
(对于通配符,它有点复杂,但是此过程的其余部分应该相同)
这时它应该告诉您密钥在/etc/letsencrypt/live/domain.name.com/*.pem等目录(三个密钥:全链,私钥和链)上的位置
然后运行openssl(编辑域名和密码)
sudo openssl pkcs12
-export -in /etc/letsencrypt/live/domain.name.com/fullchain.pem
-inkey /etc/letsencrypt/live/domain.name.com/privkey.pem
-out cert_and_key.p12
-CAfile /etc/letsencrypt/live/domain.name.com/chain.pem
-caname root
-passout pass:<insert some password here>
然后使用keytool(编辑密钥库路径和密码)
sudo keytool
-importkeystore
-srcstorepass <the password you inserted above>
-destkeystore <path/key>.jks
-srckeystore cert_and_key.p12
-srcstoretype PKCS12
-storepass <the password you inserted above>
最后,您应该在上面编写的路径上找到jks键。
在application.conf中:
play.server.https.keyStore.path = "<path/key>.jks"
play.server.https.keyStore.type = "JKS"
play.server.https.keyStore.password = "<the password you inserted above>"
在Ubuntu 16和18上使用Play 2.6.15进行了测试
答案 2 :(得分:0)
我最近不得不这样做,这是我的文件:
#!/usr/bin/env bash
sudo killall java #stop the application gracefully
rm -rf /etc/letsencrypt.bak
cp -r /etc/letsencrypt /etc/letsencrypt.bak
certbot renew --standalone
cd /etc/letsencrypt/live/example.com/
openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out cert_and_key.p12 -CAfile chain.pem -caname root -passout pass:your_password
keytool -importkeystore -srcstorepass your_password -destkeystore keyStore.jks -srckeystore cert_and_key.p12 -srcstoretype PKCS12 -storepass your_password
此后,您需要在运行应用程序时使用与接受的答案相同的格式设置属性:
sudo /path/to/app -Dhttp.port=80 -Dhttps.port=443 -Dplay.server.https.keyStore.path=/etc/letsencrypt/live/api.ali.actor/keyStore.jks -Dplay.server.https.keyStore.password=your_password -Djdk.tls.ephemeralDHKeySize=2048 -Djdk.tls.rejectClientInitiatedRenegotiation=true