This repository has been archived by the owner on Feb 25, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2a6f5e8
commit 1af4e08
Showing
18 changed files
with
1,021 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
/* | ||
* Copyright 2020 Stefan Zobel | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package net.mercurius.ks; | ||
|
||
import java.io.FileOutputStream; | ||
import java.io.IOException; | ||
import java.security.InvalidKeyException; | ||
import java.security.KeyStore; | ||
import java.security.KeyStoreException; | ||
import java.security.NoSuchAlgorithmException; | ||
import java.security.NoSuchProviderException; | ||
import java.security.SignatureException; | ||
import java.security.cert.CertificateException; | ||
import java.security.cert.X509Certificate; | ||
import java.util.Date; | ||
|
||
import sun.security.tools.keytool.CertAndKeyGen; | ||
import sun.security.x509.CertificateExtensions; | ||
import sun.security.x509.KeyIdentifier; | ||
import sun.security.x509.SubjectKeyIdentifierExtension; | ||
import sun.security.x509.X500Name; | ||
|
||
public final class CertGen { | ||
|
||
private static final int RSA_KEY_BITS_DEFAULT = 5120; | ||
private static final int ECDSA_KEY_BITS_DEFAULT = 521; | ||
// 15 years validity | ||
private static final long VALIDITY = 15L * 365L * 24L * 60L * 60L; | ||
private static final String DUMMY_DN = "CN=GeoTrust Primary Certification Authority - G2, OU=(c) 2007 GeoTrust Inc. - For authorized use only, O=GeoTrust Inc., C=US"; | ||
private static final String DEFAULT_ALIAS = "localhost"; | ||
|
||
public static void main(String[] args) { | ||
String password = (args != null && args.length > 0) ? args[0] : ""; | ||
String ksFileName = (args != null && args.length > 1) ? args[1] : "ks.p12"; | ||
String dn = (args != null && args.length > 2) ? args[2] : DUMMY_DN; | ||
String alias = (args != null && args.length > 3) ? args[3] : DEFAULT_ALIAS; | ||
char[] passwd = PBKDF2.getKey(password); | ||
System.out.println(passwd); | ||
System.out.println(passwd.length); | ||
|
||
long start = System.currentTimeMillis(); | ||
|
||
Date startDate = new Date(); | ||
KeyStore ks = generateKeyStore(dn, alias, passwd, startDate); | ||
|
||
long end = System.currentTimeMillis(); | ||
System.out.println("took: " + (end - start) + " ms"); | ||
|
||
try (FileOutputStream fos = new FileOutputStream(ksFileName)) { | ||
ks.store(fos, passwd); | ||
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
private static KeyStore generateKeyStore(String certificateDN, String keyEntryAlias, char[] passwd, | ||
Date startDate) { | ||
try { | ||
KeyStore keyStore = KeyStore.getInstance("PKCS12"); | ||
keyStore.load(null, new char[] {}); | ||
|
||
generateECDSACertificate(keyStore, certificateDN, keyEntryAlias, passwd, startDate); | ||
generateRSACertificate(keyStore, certificateDN, keyEntryAlias + "2", passwd, startDate); | ||
|
||
return keyStore; | ||
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
private static void generateECDSACertificate(KeyStore keyStore, String certificateDN, String keyEntryAlias, | ||
char[] passwd, Date startDate) { | ||
try { | ||
CertAndKeyGen certGen = new CertAndKeyGen("EC", "SHA512withECDSA", null); | ||
certGen.generate(ECDSA_KEY_BITS_DEFAULT); | ||
|
||
storeCertificate(keyStore, certificateDN, keyEntryAlias, passwd, startDate, certGen); | ||
|
||
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchProviderException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
private static void generateRSACertificate(KeyStore keyStore, String certificateDN, String keyEntryAlias, | ||
char[] passwd, Date startDate) { | ||
try { | ||
CertAndKeyGen certGen = new CertAndKeyGen("RSA", "SHA512withRSA", null); | ||
certGen.generate(RSA_KEY_BITS_DEFAULT); | ||
|
||
storeCertificate(keyStore, certificateDN, keyEntryAlias, passwd, startDate, certGen); | ||
|
||
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchProviderException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
private static void storeCertificate(KeyStore keyStore, String certificateDN, String keyEntryAlias, char[] passwd, | ||
Date startDate, CertAndKeyGen certGen) { | ||
try { | ||
CertificateExtensions ext = new CertificateExtensions(); | ||
ext.set(SubjectKeyIdentifierExtension.NAME, | ||
new SubjectKeyIdentifierExtension(new KeyIdentifier(certGen.getPublicKeyAnyway()).getIdentifier())); | ||
|
||
X509Certificate cert = certGen.getSelfCertificate(new X500Name(certificateDN), startDate, VALIDITY, ext); | ||
|
||
keyStore.setKeyEntry(keyEntryAlias, certGen.getPrivateKey(), passwd, new X509Certificate[] { cert }); | ||
} catch (InvalidKeyException | CertificateException | SignatureException | NoSuchAlgorithmException | ||
| NoSuchProviderException | KeyStoreException | IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
private CertGen() { | ||
throw new AssertionError(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/* | ||
* Copyright 2020 Stefan Zobel | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package net.mercurius.ks; | ||
|
||
import java.io.BufferedInputStream; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.UncheckedIOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.security.KeyStore; | ||
import java.security.KeyStoreException; | ||
import java.security.NoSuchAlgorithmException; | ||
import java.security.cert.CertificateException; | ||
|
||
public final class KSLoader { | ||
|
||
private static final String KS_NAME = "ks.p12"; | ||
|
||
/** | ||
* Test mode. Do not use in production! | ||
*/ | ||
public static KeyStore loadKeyStore() { | ||
try (InputStream is = KSLoader.class.getResourceAsStream(KS_NAME)) { | ||
if (is == null) { | ||
throw new IllegalStateException("KeyStore " + KS_NAME + " not found!"); | ||
} | ||
KeyStore ks = KeyStore.getInstance("PKCS12"); | ||
ks.load(is, passPhrase()); | ||
return ks; | ||
} catch (KeyStoreException | CertificateException | NoSuchAlgorithmException e) { | ||
throw new RuntimeException(e); | ||
} catch (IOException e) { | ||
throw new UncheckedIOException(e); | ||
} | ||
} | ||
|
||
public static KeyStore loadKeyStore(String password, Path file) { | ||
//@formatter:off | ||
try (InputStream is = Files.newInputStream(file); | ||
BufferedInputStream bis = new BufferedInputStream(is, 1 << 14) | ||
) | ||
{ | ||
KeyStore ks = KeyStore.getInstance("PKCS12"); | ||
ks.load(bis, passPhrase(password)); | ||
return ks; | ||
} catch (KeyStoreException | CertificateException | NoSuchAlgorithmException e) { | ||
throw new RuntimeException(e); | ||
} catch (IOException e) { | ||
throw new UncheckedIOException(e); | ||
} | ||
//@formatter:on | ||
} | ||
|
||
public static char[] passPhrase() { | ||
return "VpAovsDbxZdX+k3qed8hqEOeSqknJGT1uYanS69gZ2CBJ6oQuZSCGYky7n4WZGpWNWwR".toCharArray(); | ||
} | ||
|
||
public static char[] passPhrase(String password) { | ||
return PBKDF2.getKey(password); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/* | ||
* Copyright 2013 Stefan Zobel | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package net.mercurius.ks; | ||
|
||
import java.security.NoSuchAlgorithmException; | ||
import java.security.spec.InvalidKeySpecException; | ||
import java.security.spec.KeySpec; | ||
import java.util.Arrays; | ||
import java.util.Base64; | ||
|
||
import javax.crypto.SecretKeyFactory; | ||
import javax.crypto.spec.PBEKeySpec; | ||
|
||
public final class PBKDF2 { | ||
|
||
private static final String PRIV_1 = "@GSr:p\"[dZR6RU;B:s&;4P<3XHPl@\"|r9*Az w#:"; | ||
private static final String PRIV_2 = ",k~m:@HXE-a%%7 c](8J|Yu{d\"`./DK_f'z }^'S"; | ||
|
||
// 16384 (= 2^14) iterations | ||
private static final int ITERS = 1 << 14; | ||
|
||
private static final byte[] SALT_64 = { 59, -76, -110, 53, -98, 81, 100, 67, -90, 113, -119, -32, -5, -61, 44, -9, | ||
8, -108, 107, -86, 118, -125, -70, -94, 59, -106, -121, -18, 15, 12, 12, -77, 108, 70, 125, 23, -79, 66, 18, | ||
-51, 67, 55, 53, -28, -35, -92, -54, 37, -101, 57, 100, -128, 41, 24, 107, -25, -106, 73, -108, -110, -34, | ||
-102, -55, 74 }; | ||
|
||
private static final int KEY_LENGTH = 51; | ||
|
||
public static char[] getKey(String password) { | ||
String pwd = password; | ||
if (pwd == null || "".equals(pwd)) { | ||
pwd = PRIV_1; | ||
} | ||
pwd += PRIV_2; | ||
try { | ||
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512"); | ||
KeySpec spec = new PBEKeySpec(pwd.toCharArray(), SALT_64, ITERS, KEY_LENGTH * 8); | ||
byte[] encoded = skf.generateSecret(spec).getEncoded(); | ||
char[] ksPwd = Base64.getEncoder().encodeToString(encoded).toCharArray(); | ||
Arrays.fill(encoded, (byte) 0); | ||
return ksPwd; | ||
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
private PBKDF2() { | ||
throw new AssertionError(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/* | ||
* Copyright 2020 Stefan Zobel | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package net.mercurius.ssl; | ||
|
||
public enum Protocol { | ||
|
||
//@formatter:off | ||
TLS_12("TLSv1.2"), | ||
TLS_13("TLSv1.3"); | ||
//@formatter:on | ||
|
||
private final String name; | ||
|
||
private Protocol(String prot) { | ||
name = prot; | ||
} | ||
|
||
public String toString() { | ||
return name; | ||
} | ||
|
||
public static Protocol of(String protocolName) { | ||
switch (protocolName) { | ||
case "TLSv1.2": | ||
return TLS_12; | ||
case "TLSv1.3": | ||
return TLS_13; | ||
default: | ||
return null; | ||
} | ||
} | ||
} |
Oops, something went wrong.