// --- BEGIN COPYRIGHT BLOCK ---
// 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; version 2 of the License.
//
// 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, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package com.netscape.cmstools;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URLEncoder;
import java.security.KeyPair;
import java.security.MessageDigest;
import java.security.PublicKey;
import netscape.security.x509.X500Name;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.PosixParser;
import org.apache.commons.io.FileUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.mozilla.jss.CryptoManager;
import org.mozilla.jss.asn1.ASN1Util;
import org.mozilla.jss.asn1.BIT_STRING;
import org.mozilla.jss.asn1.BMPString;
import org.mozilla.jss.asn1.INTEGER;
import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
import org.mozilla.jss.asn1.OCTET_STRING;
import org.mozilla.jss.asn1.PrintableString;
import org.mozilla.jss.asn1.SEQUENCE;
import org.mozilla.jss.asn1.TeletexString;
import org.mozilla.jss.asn1.UTF8String;
import org.mozilla.jss.asn1.UniversalString;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.IVParameterSpec;
import org.mozilla.jss.crypto.KeyGenAlgorithm;
import org.mozilla.jss.crypto.KeyGenerator;
import org.mozilla.jss.crypto.KeyPairAlgorithm;
import org.mozilla.jss.crypto.KeyPairGenerator;
import org.mozilla.jss.crypto.KeyWrapAlgorithm;
import org.mozilla.jss.crypto.KeyWrapper;
import org.mozilla.jss.crypto.Signature;
import org.mozilla.jss.crypto.SignatureAlgorithm;
import org.mozilla.jss.crypto.SymmetricKey;
import org.mozilla.jss.crypto.X509Certificate;
import org.mozilla.jss.pkix.crmf.CertReqMsg;
import org.mozilla.jss.pkix.crmf.CertRequest;
import org.mozilla.jss.pkix.crmf.CertTemplate;
import org.mozilla.jss.pkix.crmf.EncryptedKey;
import org.mozilla.jss.pkix.crmf.EncryptedValue;
import org.mozilla.jss.pkix.crmf.PKIArchiveOptions;
import org.mozilla.jss.pkix.crmf.POPOSigningKey;
import org.mozilla.jss.pkix.crmf.ProofOfPossession;
import org.mozilla.jss.pkix.primitive.AVA;
import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier;
import org.mozilla.jss.pkix.primitive.Name;
import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo;
import org.mozilla.jss.util.Password;
import com.netscape.cmsutil.crypto.CryptoUtil;
import com.netscape.cmsutil.util.Cert;
import com.netscape.cmsutil.util.HMACDigest;
import com.netscape.cmsutil.util.Utils;
/**
* A command-line utility used to generate a Certificate Request Message
* Format (CRMF) request with proof of possesion (POP).
*
*
* IMPORTANT: The transport certificate file needs to be created to contain the
* transport certificate in its base64 encoded format.
*
*
*
* @version $Revision$, $Date$
*/
public class CRMFPopClient {
public boolean verbose;
public static Options createOptions() {
Options options = new Options();
Option option = new Option("d", true, "Security database location");
option.setArgName("database");
options.addOption(option);
option = new Option("p", true, "Security token password");
option.setArgName("password");
options.addOption(option);
option = new Option("h", true, "Security token name");
option.setArgName("token");
options.addOption(option);
option = new Option("o", true, "Output file to store base-64 CRMF request");
option.setArgName("output");
options.addOption(option);
option = new Option("n", true, "Subject DN");
option.setArgName("subject DN");
options.addOption(option);
option = new Option("a", true, "Key algorithm");
option.setArgName("algorithm");
options.addOption(option);
option = new Option("l", true, "Key length");
option.setArgName("length");
options.addOption(option);
option = new Option("c", true, "ECC curve name");
option.setArgName("curve");
options.addOption(option);
option = new Option("m", true, "CA server hostname and port");
option.setArgName("hostname:port");
options.addOption(option);
option = new Option("f", true, "Certificate profile");
option.setArgName("profile");
options.addOption(option);
option = new Option("u", true, "Username");
option.setArgName("username");
options.addOption(option);
option = new Option("r", true, "Requestor");
option.setArgName("requestor");
options.addOption(option);
option = new Option("q", true, "POP option");
option.setArgName("POP option");
options.addOption(option);
option = new Option("b", true, "PEM transport certificate");
option.setArgName("transport cert");
options.addOption(option);
option = new Option("k", true, "Attribute encoding");
option.setArgName("boolean");
options.addOption(option);
option = new Option("x", true, "SSL certificate with ECDH ECDSA");
option.setArgName("boolean");
options.addOption(option);
option = new Option("t", true, "Temporary");
option.setArgName("boolean");
options.addOption(option);
option = new Option("s", true, "Sensitive");
option.setArgName("sensitive");
options.addOption(option);
option = new Option("e", true, "Extractable");
option.setArgName("extractable");
options.addOption(option);
options.addOption("v", "verbose", false, "Run in verbose mode.");
options.addOption(null, "help", false, "Show help message.");
return options;
}
public static void printHelp() {
System.out.println("Usage: CRMFPopClient [OPTIONS]");
System.out.println();
System.out.println("Options:");
System.out.println(" -d Security database location (default: current directory)");
System.out.println(" -h Security token name (default: internal)");
System.out.println(" -p Security token password");
System.out.println(" -n Certificate subject DN");
System.out.println(" -k Attribute value encoding in subject DN (default: false)");
System.out.println(" - true: enabled");
System.out.println(" - false: disabled");
System.out.println(" -a Key algorithm (default: rsa)");
System.out.println(" - rsa: RSA");
System.out.println(" - ec: ECC");
System.out.println(" -f Certificate profile");
System.out.println(" - RSA default: caEncUserCert");
System.out.println(" - ECC default: caEncECUserCert");
System.out.println(" -q POP option (default: POP_SUCCESS)");
System.out.println(" - POP_NONE: without POP");
System.out.println(" - POP_SUCCESS: with valid POP");
System.out.println(" - POP_FAIL: with invalid POP (for testing)");
System.out.println(" -b PEM transport certificate (default: transport.txt)");
System.out.println(" -v, --verbose Run in verbose mode.");
System.out.println(" --help Show help message.");
System.out.println();
System.out.println("With RSA algorithm the following options can be specified:");
System.out.println(" -l Key length (default: 2048)");
System.out.println();
System.out.println("With ECC algorithm the following options can be specified:");
System.out.println(" -c ECC curve name (default: nistp256)");
System.out.println(" -t Temporary (default: true)");
System.out.println(" - true: temporary (session)");
System.out.println(" - false: permanent (token)");
System.out.println(" -s <-1|0|1> Sensitive (default: -1)");
System.out.println(" - -1: temporaryPairMode dependent");
System.out.println(" - 0: non-sensitive");
System.out.println(" - 1: sensitive");
System.out.println(" -e <-1|0|1> Extractable (default: -1)");
System.out.println(" - -1: token dependent");
System.out.println(" - 0: non-extractable");
System.out.println(" - 1: extractable");
System.out.println(" -x Certificate type (default: false)");
System.out.println(" - true: SSL certificate with ECDH ECDSA (reqires POP_NONE)");
System.out.println(" - false: otherwise");
System.out.println();
System.out.println("To store the CRMF request the following options are required:");
System.out.println(" -o