package com.bao.examples.security;
import java.io.*;
import java.security.*;
import java.security.cert.*;
import sun.security.x509.X509CertInfo;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X500Name;
import sun.security.x509.CertificateIssuerName;
/**
* http://silo.cs.indiana.edu:8346/horstmann/v2ch09/CertificateSigner/CertificateSigner.java
* 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
{
private static boolean sign(String ksname, String alias, String inname, String outname,
char[] storepass, char[] keypass, StringBuilder sb) throws Exception
{
if(ksname == null || alias == null || inname == null || outname == null
|| storepass == null || keypass == null)
{
setErrorMsg(sb, usage());
return false;
}
// load key store
KeyStore store = KeyStore.getInstance("JKS", "SUN");
InputStream in = new FileInputStream(ksname);
store.load(in, storepass);
in.close();
// get private key of the alias
PrivateKey issuerPrivateKey = (PrivateKey) store.getKey(alias, keypass);
if(issuerPrivateKey == null)
{
setErrorMsg(sb, "No such private key");
return false;
}
// load the public cert file
CertificateFactory factory = CertificateFactory.getInstance("X.509");
InputStream inCertFile = new FileInputStream(inname);
X509Certificate inCert = (X509Certificate) factory.generateCertificate(inCertFile);
inCertFile.close();
// Gets the DER-encoded certificate information
byte[] inCertBytes = inCert.getTBSCertificate();
// Get the issuer cert - private key
X509Certificate issuerCert = (X509Certificate) store.getCertificate(alias);
Principal issuer = issuerCert.getSubjectDN();
String issuerSigAlg = issuerCert.getSigAlgName();
// Generate the public cert info - X509
X509CertInfo info = new X509CertInfo(inCertBytes);
// replace the issuer by the current signer
info.set(X509CertInfo.ISSUER, new CertificateIssuerName((X500Name) issuer));
X509CertImpl outCert = new X509CertImpl(info);
// sign it
outCert.sign(issuerPrivateKey, issuerSigAlg);
// Out put to file
FileOutputStream out = new FileOutputStream(outname);
outCert.derEncode(out);
out.close();
return true;
}
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
char[] storepass = null;
char[] keypass = null;
for(int i = 0; i < args.length - 1; 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 if(args[i].equals("-storepass"))
storepass = args[i + 1].toCharArray();
else if(args[i].equals("-keypass"))
keypass = args[i + 1].toCharArray();
else
exit(usage());
}
StringBuilder sb = new StringBuilder();
try
{
if(!sign(ksname, alias, inname, outname, storepass, keypass, sb))
{
exit(sb.toString());
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
private static String usage()
{
return "Usage: java CertificateSigner" + " -keystore keyStore -alias issuerKeyAlias"
+ " -infile inputFile -outfile outputFile -storepass password -keypass password";
}
private static void setErrorMsg(StringBuilder sb, String errorMsg)
{
sb.setLength(0);
sb.append(errorMsg);
}
/**
* Prints a usage message and exits.
*/
private static void exit(String str)
{
System.out.println(str);
System.exit(1);
}
}