/*
This program is a part of the companion code for Core Java 8th ed.
(http://horstmann.com/corejava)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
import java.io.Console;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import sun.security.x509.CertificateIssuerName;
import sun.security.x509.X500Name;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CertInfo;
/**
* This program signs a certificate, using the private key of another certificate in a keystore.
* @version 1.01 2007-10-07
* @author Cay Horstmann
*/
public class CertificateSigner
{
public static void main(String[] args)
{
String ksname = null; // the keystore name
String alias = null; // the private key alias
String inname = null; // the input file name
String outname = null; // the output file name
for (int i = 0; i < args.length; i += 2)
{
if (args[i].equals("-keystore")) ksname = args[i + 1];
else if (args[i].equals("-alias")) alias = args[i + 1];
else if (args[i].equals("-infile")) inname = args[i + 1];
else if (args[i].equals("-outfile")) outname = args[i + 1];
else usage();
}
if (ksname == null || alias == null || inname == null || outname == null) usage();
try
{
Console console = System.console();
if (console == null) error("No console");
char[] password = console.readPassword("Keystore password: ");
KeyStore store = KeyStore.getInstance("JKS", "SUN");
InputStream in = new FileInputStream(ksname);
store.load(in, password);
Arrays.fill(password, ' ');
in.close();
char[] keyPassword = console.readPassword("Key password for %s: ", alias);
PrivateKey issuerPrivateKey = (PrivateKey) store.getKey(alias, keyPassword);
Arrays.fill(keyPassword, ' ');
if (issuerPrivateKey == null) error("No such private key");
in = new FileInputStream(inname);
CertificateFactory factory = CertificateFactory.getInstance("X.509");
X509Certificate inCert = (X509Certificate) factory.generateCertificate(in);
in.close();
byte[] inCertBytes = inCert.getTBSCertificate();
X509Certificate issuerCert = (X509Certificate) store.getCertificate(alias);
Principal issuer = issuerCert.getSubjectDN();
String issuerSigAlg = issuerCert.getSigAlgName();
FileOutputStream out = new FileOutputStream(outname);
X509CertInfo info = new X509CertInfo(inCertBytes);
info.set(X509CertInfo.ISSUER, new CertificateIssuerName((X500Name) issuer));
X509CertImpl outCert = new X509CertImpl(info);
outCert.sign(issuerPrivateKey, issuerSigAlg);
outCert.derEncode(out);
out.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* Prints an error message and exits.
* @param message the error message
*/
public static void error(String message)
{
System.out.println(message);
System.exit(1);
}
/**
* Prints a usage message and exits.
*/
public static void usage()
{
System.out.println("Usage: java CertificateSigner"
+ " -keystore keyStore -alias issuerKeyAlias"
+ " -infile inputFile -outfile outputFile");
System.exit(1);
}
}