|
Play Framework/Scala example source code file (FakeKeyStore.scala)
The FakeKeyStore.scala Play Framework example source code
/*
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
*/
package play.core.server.ssl
import play.api.{ Play, Logger, Application }
import java.security.{ KeyStore, SecureRandom, KeyPairGenerator, KeyPair }
import sun.security.x509._
import java.util.Date
import java.math.BigInteger
import java.security.cert.{ CertPathValidatorException, X509Certificate }
import java.io.{ File, FileInputStream, FileOutputStream }
import javax.net.ssl.KeyManagerFactory
import scala.util.control.NonFatal
import scala.util.Properties.isJavaAtLeast
import scala.util.{ Failure, Success, Try }
import play.utils.PlayIO
import java.security.interfaces.RSAPublicKey
/**
* A fake key store
*/
object FakeKeyStore {
val GeneratedKeyStore = "conf/generated.keystore"
val DnName = "CN=localhost, OU=Unit Testing, O=Mavericks, L=Moon Base 1, ST=Cyberspace, C=CY"
def shouldGenerate(keyStoreFile: File): Boolean = {
import scala.collection.JavaConverters._
if (!keyStoreFile.exists()) {
return true
}
// Should regenerate if we find an unacceptably weak key in there.
val store = KeyStore.getInstance("JKS")
val in = new FileInputStream(keyStoreFile)
try {
store.load(in, "".toCharArray)
} finally {
PlayIO.closeQuietly(in)
}
store.aliases().asScala.foreach {
alias =>
Option(store.getCertificate(alias)).map {
c =>
val key: RSAPublicKey = c.getPublicKey.asInstanceOf[RSAPublicKey]
if (key.getModulus.bitLength < 2048) {
return true
}
}
}
false
}
def keyManagerFactory(appPath: File): Try[KeyManagerFactory] = {
try {
val keyStore = KeyStore.getInstance("JKS")
val keyStoreFile = new File(appPath, GeneratedKeyStore)
if (shouldGenerate(keyStoreFile)) {
Play.logger.info("Generating HTTPS key pair in " + keyStoreFile.getAbsolutePath + " - this may take some time. If nothing happens, try moving the mouse/typing on the keyboard to generate some entropy.")
// Generate the key pair
val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
keyPairGenerator.initialize(2048) // 2048 is the NIST acceptable key length until 2030
val keyPair = keyPairGenerator.generateKeyPair()
// Generate a self signed certificate
val cert = createSelfSignedCertificate(keyPair)
// Create the key store, first set the store pass
keyStore.load(null, "".toCharArray)
keyStore.setKeyEntry("playgenerated", keyPair.getPrivate, "".toCharArray, Array(cert))
keyStore.setCertificateEntry("playgeneratedtrusted", cert)
val out = new FileOutputStream(keyStoreFile)
try {
keyStore.store(out, "".toCharArray)
} finally {
PlayIO.closeQuietly(out)
}
} else {
val in = new FileInputStream(keyStoreFile)
try {
keyStore.load(in, "".toCharArray)
} finally {
PlayIO.closeQuietly(in)
}
}
// Load the key and certificate into a key manager factory
val kmf = KeyManagerFactory.getInstance("SunX509")
kmf.init(keyStore, "".toCharArray)
Success(kmf)
} catch {
case NonFatal(e) => {
Failure(new Exception("Error loading fake key store", e))
}
}
}
def createSelfSignedCertificate(keyPair: KeyPair): X509Certificate = {
val certInfo = new X509CertInfo()
// Serial number and version
certInfo.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(new BigInteger(64, new SecureRandom())))
certInfo.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3))
// Validity
val validFrom = new Date()
val validTo = new Date(validFrom.getTime + 50l * 365l * 24l * 60l * 60l * 1000l)
val validity = new CertificateValidity(validFrom, validTo)
certInfo.set(X509CertInfo.VALIDITY, validity)
// Subject and issuer
// Note: CertificateSubjectName and CertificateIssuerName are removed in Java 8
// and when setting the subject or issuer just the X500Name should be used.
val owner = new X500Name(DnName)
val justName = isJavaAtLeast("1.8")
certInfo.set(X509CertInfo.SUBJECT, if (justName) owner else new CertificateSubjectName(owner))
certInfo.set(X509CertInfo.ISSUER, if (justName) owner else new CertificateIssuerName(owner))
// Key and algorithm
certInfo.set(X509CertInfo.KEY, new CertificateX509Key(keyPair.getPublic))
val algorithm = new AlgorithmId(AlgorithmId.sha1WithRSAEncryption_oid)
certInfo.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algorithm))
// Create a new certificate and sign it
val cert = new X509CertImpl(certInfo)
cert.sign(keyPair.getPrivate, "SHA1withRSA")
// Since the SHA1withRSA provider may have a different algorithm ID to what we think it should be,
// we need to reset the algorithm ID, and resign the certificate
val actualAlgorithm = cert.get(X509CertImpl.SIG_ALG).asInstanceOf[AlgorithmId]
certInfo.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, actualAlgorithm)
val newCert = new X509CertImpl(certInfo)
newCert.sign(keyPair.getPrivate, "SHA1withRSA")
newCert
}
}
Other Play Framework source code examplesHere is a short list of links related to this Play Framework FakeKeyStore.scala source code file: |
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.