KeyStoreUtil:

- Overwrite check in createKeys()
  - New getCert(), getKey()
  SU3File:
  - Store generated keys in keystore
  - Get private key for signing from keystore
This commit is contained in:
zzz
2013-09-12 20:22:30 +00:00
parent 71c0104236
commit 7ab4dd7f4b
2 changed files with 102 additions and 44 deletions

View File

@ -6,6 +6,7 @@ import java.io.InputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateEncodingException;
@ -252,7 +253,7 @@ public class KeyStoreUtil {
* @param alias the name of the key
* @param cname e.g. randomstuff.console.i2p.net
* @param ou e.g. console
* @param keqPW the key password
* @param keyPW the key password, must be at least 6 characters
*
* @return success
* @since 0.8.3, consolidated from RouterConsoleRUnner and SSLClientListenerRunner in 0.9.9
@ -276,16 +277,26 @@ public class KeyStoreUtil {
* @param validDays e.g. 3652 (10 years)
* @param keyAlg e.g. DSA , RSA, EC
* @param keySize e.g. 1024
* @param keqPW the key password
* @param keyPW the key password, must be at least 6 characters
*
* @return success
* @since 0.8.3, consolidated from RouterConsoleRUnner and SSLClientListenerRunner in 0.9.9
*/
public static boolean createKeys(File ks, String ksPW, String alias, String cname, String ou,
int validDays, String keyAlg, int keySize, String keyPW) {
if (!ks.exists()) {
if (ks.exists()) {
try {
if (getCert(ks, ksPW, alias) != null) {
error("Not overwriting key " + alias + ", already exists in " + ks, null);
return false;
}
} catch (Exception e) {
error("Not overwriting key \"" + alias + "\", already exists in " + ks, e);
return false;
}
} else {
File dir = ks.getParentFile();
if (!dir.exists()) {
if (dir != null && !dir.exists()) {
File sdir = new SecureDirectory(dir.getAbsolutePath());
if (!sdir.mkdir()) {
error("Can't create directory " + dir, null);
@ -319,11 +330,57 @@ public class KeyStoreUtil {
for (int i = 0; i < args.length; i++) {
buf.append('"').append(args[i]).append("\" ");
}
error("Failed to create SSL keystore using command line:" + buf, null);
error("Failed to create SSL keystore using command line: " + buf, null);
}
return success;
}
/**
* Get a private key out of a keystore
*
* @param ks path to the keystore
* @param ksPW the keystore password, may be null
* @param alias the name of the key
* @param keyPW the key password, must be at least 6 characters
* @return the key or null if not found
*/
public static PrivateKey getPrivateKey(File ks, String ksPW, String alias, String keyPW)
throws GeneralSecurityException, IOException {
InputStream fis = null;
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
fis = new FileInputStream(ks);
char[] pwchars = ksPW != null ? ksPW.toCharArray() : null;
keyStore.load(fis, pwchars);
char[] keypwchars = keyPW.toCharArray();
return (PrivateKey) keyStore.getKey(alias, keypwchars);
} finally {
if (fis != null) try { fis.close(); } catch (IOException ioe) {}
}
}
/**
* Get a cert out of a keystore
*
* @param ks path to the keystore
* @param ksPW the keystore password, may be null
* @param alias the name of the key
* @return the certificate or null if not found
*/
public static Certificate getCert(File ks, String ksPW, String alias)
throws GeneralSecurityException, IOException {
InputStream fis = null;
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
fis = new FileInputStream(ks);
char[] pwchars = ksPW != null ? ksPW.toCharArray() : null;
keyStore.load(fis, pwchars);
return keyStore.getCertificate(alias);
} finally {
if (fis != null) try { fis.close(); } catch (IOException ioe) {}
}
}
/**
* Pull the cert back OUT of the keystore and save it as ascii
* so the clients can get to it.
@ -338,19 +395,13 @@ public class KeyStoreUtil {
public static boolean exportCert(File ks, String ksPW, String alias, File certFile) {
InputStream fis = null;
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
fis = new FileInputStream(ks);
char[] pwchars = ksPW != null ? ksPW.toCharArray() : null;
keyStore.load(fis, pwchars);
Certificate cert = keyStore.getCertificate(alias);
Certificate cert = getCert(ks, ksPW, alias);
if (cert != null)
return CertUtil.saveCert(cert, certFile);
} catch (GeneralSecurityException gse) {
error("Error saving ASCII SSL keys", gse);
} catch (IOException ioe) {
error("Error saving ASCII SSL keys", ioe);
} finally {
if (fis != null) try { fis.close(); } catch (IOException ioe) {}
}
return false;
}

View File

@ -503,8 +503,15 @@ public class SU3File {
private static final boolean signCLI(SigType type, String inputFile, String signedFile,
String privateKeyFile, String version, String signerName) {
try {
String keypw = "";
while (keypw.length() < 6) {
System.out.print("Enter password for key \"" + signerName + "\": ");
keypw = DataHelper.readLine(System.in).trim();
if (keypw.length() > 0 && keypw.length() < 6)
System.out.println("Key password must be at least 6 characters");
}
File pkfile = new File(privateKeyFile);
PrivateKey pk = SigUtil.importJavaPrivateKey(pkfile, type);
PrivateKey pk = KeyStoreUtil.getPrivateKey(pkfile,KeyStoreUtil.DEFAULT_KEYSTORE_PASSWORD, signerName, keypw);
SigningPrivateKey spk = SigUtil.fromJavaKey(pk, type);
SU3File file = new SU3File(signedFile);
file.write(new File(inputFile), CONTENT_ROUTER, version, signerName, spk);
@ -568,45 +575,45 @@ public class SU3File {
*/
private static final boolean genKeysCLI(SigType type, String publicKeyFile, String privateKeyFile) {
File pubFile = new File(publicKeyFile);
File privFile = new File(privateKeyFile);
if (pubFile.exists()) {
System.out.println("Error: Not overwriting file " + publicKeyFile);
return false;
}
if (privFile.exists()) {
System.out.println("Error: Not overwriting file " + privateKeyFile);
File ksFile = new File(privateKeyFile);
String alias = "";
String keypw = "";
try {
while (alias.length() == 0) {
System.out.print("Enter key name (example@mail.i2p): ");
alias = DataHelper.readLine(System.in).trim();
}
while (keypw.length() < 6) {
System.out.print("Enter new key password: ");
keypw = DataHelper.readLine(System.in).trim();
if (keypw.length() > 0 && keypw.length() < 6)
System.out.println("Key password must be at least 6 characters");
}
} catch (IOException ioe) {
return false;
}
FileOutputStream fileOutputStream = null;
I2PAppContext context = I2PAppContext.getGlobalContext();
try {
// inefficiently go from Java to I2P to Java formats
SimpleDataStructure signingKeypair[] = context.keyGenerator().generateSigningKeys(type);
SigningPublicKey signingPublicKey = (SigningPublicKey) signingKeypair[0];
SigningPrivateKey signingPrivateKey = (SigningPrivateKey) signingKeypair[1];
PublicKey pubkey = SigUtil.toJavaKey(signingPublicKey);
PrivateKey privkey = SigUtil.toJavaKey(signingPrivateKey);
fileOutputStream = new SecureFileOutputStream(pubFile);
fileOutputStream.write(pubkey.getEncoded());
fileOutputStream.close();
fileOutputStream = null;
fileOutputStream = new SecureFileOutputStream(privFile);
fileOutputStream.write(privkey.getEncoded());
System.out.println("\r\n" + type + " Private key written to: " + privateKeyFile);
System.out.println(type + " Public key written to: " + publicKeyFile);
System.out.println("\r\nPublic key: " + signingPublicKey.toBase64() + "\r\n");
} catch (Exception e) {
int keylen = type.getPubkeyLen() * 8;
if (type.getBaseAlgorithm() == SigAlgo.EC) {
keylen /= 2;
if (keylen == 528)
keylen = 521;
}
boolean success = KeyStoreUtil.createKeys(ksFile, KeyStoreUtil.DEFAULT_KEYSTORE_PASSWORD, alias,
"cn", "ou", 3652, type.getBaseAlgorithm().getName(),
keylen, keypw);
if (!success) {
System.err.println("Error writing keys:");
return false;
}
File outfile = new File(publicKeyFile);
success = KeyStoreUtil.exportCert(ksFile, KeyStoreUtil.DEFAULT_KEYSTORE_PASSWORD, alias, outfile);
if (!success) {
System.err.println("Error writing keys:");
e.printStackTrace();
return false;
} finally {
if (fileOutputStream != null)
try {
fileOutputStream.close();
} catch (IOException ioe) {}
}
return true;
}