diff options
author | Vitaly Takmazov | 2018-09-05 22:46:23 +0300 |
---|---|---|
committer | Vitaly Takmazov | 2018-09-05 22:46:23 +0300 |
commit | 3ad367ca8a9a11c026938459f7b852f6391bd341 (patch) | |
tree | 263f1309e83c5dc5cd9b7e5cc97459f936d6895d /juick-server/src/main/java/com/juick/server/KeystoreManager.java | |
parent | 302200828e48932dba38dc36fd41dd23fb6dfc76 (diff) |
KeystoreManager shares keystore between XMPP and ActivityPub
Diffstat (limited to 'juick-server/src/main/java/com/juick/server/KeystoreManager.java')
-rw-r--r-- | juick-server/src/main/java/com/juick/server/KeystoreManager.java | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/juick-server/src/main/java/com/juick/server/KeystoreManager.java b/juick-server/src/main/java/com/juick/server/KeystoreManager.java new file mode 100644 index 00000000..bb0de79d --- /dev/null +++ b/juick-server/src/main/java/com/juick/server/KeystoreManager.java @@ -0,0 +1,116 @@ +package com.juick.server; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.util.Base64Utils; +import sun.security.x509.*; + +import javax.annotation.PostConstruct; +import javax.net.ssl.KeyManagerFactory; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.security.*; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Date; + +@Component +public class KeystoreManager { + private static final Logger logger = LoggerFactory.getLogger("com.juick.server"); + @Value("${keystore:juick.p12}") + private String keystore; + @Value("${keystore_password:secret}") + private String keystorePassword; + + private KeyStore ks; + + private KeyManagerFactory kmf; + + @PostConstruct + public void init() throws GeneralSecurityException, IOException { + try (InputStream ksIs = new FileInputStream(keystore)) { + ks = KeyStore.getInstance("PKCS12"); + ks.load(ksIs, keystorePassword.toCharArray()); + kmf = KeyManagerFactory.getInstance(KeyManagerFactory + .getDefaultAlgorithm()); + kmf.init(ks, keystorePassword.toCharArray()); + } catch (IOException | KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException | CertificateException e) { + logger.warn("Keystore error, creating self-signed", e); + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + keyPairGenerator.initialize(4096); + KeyPair keyPair = keyPairGenerator.generateKeyPair(); + + Certificate[] chain = {generateCertificate("cn=localhost", keyPair, 365, "SHA256withRSA")}; + + ks = KeyStore.getInstance(KeyStore.getDefaultType()); + ks.load(null, null); + ks.setKeyEntry("1", keyPair.getPrivate(), keystorePassword.toCharArray(), chain); + kmf = KeyManagerFactory.getInstance(KeyManagerFactory + .getDefaultAlgorithm()); + kmf.init(ks, keystorePassword.toCharArray()); + } + } + + public KeyStore getKeystore() { + return ks; + } + + public KeyManagerFactory getKeymanagerFactory() { + return kmf; + } + + private KeyPair getKeyPair() { + Key privateKey = null; + try { + privateKey = ks.getKey("1", keystorePassword.toCharArray()); + Certificate certificate = ks.getCertificate("1"); + return new KeyPair(certificate.getPublicKey(), (PrivateKey) privateKey); + } catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException e) { + e.printStackTrace(); + } + return null; + } + public String getPublicKey() { + return String.format("-----BEGIN RSA PUBLIC KEY-----\n%s\\n-----END RSA PUBLIC KEY-----\\n", + new String(Base64Utils.encode(getKeyPair().getPublic().getEncoded()))); + } + private X509Certificate generateCertificate(String dn, KeyPair keyPair, int validity, String sigAlgName) throws GeneralSecurityException, IOException { + PrivateKey privateKey = keyPair.getPrivate(); + + X509CertInfo info = new X509CertInfo(); + + Date from = new Date(); + Date to = new Date(from.getTime() + validity * 1000L * 24L * 60L * 60L); + + CertificateValidity interval = new CertificateValidity(from, to); + BigInteger serialNumber = new BigInteger(64, new SecureRandom()); + X500Name owner = new X500Name(dn); + AlgorithmId sigAlgId = new AlgorithmId(AlgorithmId.sha256WithRSAEncryption_oid); + + info.set(X509CertInfo.VALIDITY, interval); + info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(serialNumber)); + info.set(X509CertInfo.SUBJECT, owner); + info.set(X509CertInfo.ISSUER, owner); + info.set(X509CertInfo.KEY, new CertificateX509Key(keyPair.getPublic())); + info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3)); + info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(sigAlgId)); + + // Sign the cert to identify the algorithm that's used. + X509CertImpl certificate = new X509CertImpl(info); + certificate.sign(privateKey, sigAlgName); + + // Update the algorith, and resign. + sigAlgId = (AlgorithmId) certificate.get(X509CertImpl.SIG_ALG); + info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, sigAlgId); + certificate = new X509CertImpl(info); + certificate.sign(privateKey, sigAlgName); + + return certificate; + } +} |