// --- 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.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.util.Date;
import java.util.StringTokenizer;
import netscape.security.pkcs.PKCS10;
import netscape.security.x509.X500Name;
import netscape.security.x509.X509CertImpl;
import org.mozilla.jss.CryptoManager;
import org.mozilla.jss.asn1.ANY;
import org.mozilla.jss.asn1.ASN1Util;
import org.mozilla.jss.asn1.BIT_STRING;
import org.mozilla.jss.asn1.ENUMERATED;
import org.mozilla.jss.asn1.GeneralizedTime;
import org.mozilla.jss.asn1.INTEGER;
import org.mozilla.jss.asn1.InvalidBERException;
import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
import org.mozilla.jss.asn1.OCTET_STRING;
import org.mozilla.jss.asn1.SEQUENCE;
import org.mozilla.jss.asn1.SET;
import org.mozilla.jss.asn1.UTF8String;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.DigestAlgorithm;
import org.mozilla.jss.crypto.ObjectNotFoundException;
import org.mozilla.jss.crypto.SignatureAlgorithm;
import org.mozilla.jss.crypto.X509Certificate;
import org.mozilla.jss.pkcs10.CertificationRequest;
import org.mozilla.jss.pkix.cmc.CMCCertId;
import org.mozilla.jss.pkix.cmc.GetCert;
import org.mozilla.jss.pkix.cmc.LraPopWitness;
import org.mozilla.jss.pkix.cmc.OtherMsg;
import org.mozilla.jss.pkix.cmc.PKIData;
import org.mozilla.jss.pkix.cmc.TaggedAttribute;
import org.mozilla.jss.pkix.cmc.TaggedCertificationRequest;
import org.mozilla.jss.pkix.cmc.TaggedRequest;
import org.mozilla.jss.pkix.cmmf.RevRequest;
import org.mozilla.jss.pkix.cms.ContentInfo;
import org.mozilla.jss.pkix.cms.EncapsulatedContentInfo;
import org.mozilla.jss.pkix.cms.IssuerAndSerialNumber;
import org.mozilla.jss.pkix.cms.SignedData;
import org.mozilla.jss.pkix.cms.SignerIdentifier;
import org.mozilla.jss.pkix.cms.SignerInfo;
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.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.util.HMACDigest;
import com.netscape.cmsutil.util.Utils;
/**
* Tool for creating CMC full request
*
*
*
* @version $Revision$, $Date$
*
*/
public class CMCRequest {
public static final String PR_REQUEST_CMC = "CMC";
public static final String PR_REQUEST_CRMF = "CRMF";
public static final int ARGC = 1;
public static final String HEADER = "-----BEGIN NEW CERTIFICATE REQUEST-----";
public static final String TRAILER = "-----END NEW CERTIFICATE REQUEST-----";
void cleanArgs(String[] s) {
}
public static X509Certificate getCertificate(String tokenname,
String nickname) throws Exception {
CryptoManager manager = CryptoManager.getInstance();
CryptoToken token = null;
if (tokenname.equals("internal")) {
token = manager.getInternalKeyStorageToken();
} else {
token = manager.getTokenByName(tokenname);
}
StringBuffer certname = new StringBuffer();
if (!token.equals(manager.getInternalKeyStorageToken())) {
certname.append(tokenname);
certname.append(":");
}
certname.append(nickname);
try {
return manager.findCertByNickname(certname.toString());
} catch (ObjectNotFoundException e) {
throw new IOException("Signing Certificate not found");
}
}
public static java.security.PrivateKey getPrivateKey(String tokenname, String nickname)
throws Exception {
X509Certificate cert = getCertificate(tokenname, nickname);
return CryptoManager.getInstance().findPrivKeyByCert(cert);
}
/**
* getCMCBlob create and return the enrollent request.
*
*
* @param signerCert the certificate of the authorized signer of the CMC revocation request.
* @param nickname the nickname of the certificate inside the token.
* @param rValue CRMF/PKCS10 request.
* @param format either crmf or pkcs10
* @return the CMC enrollment request encoded in base64
*/
static ContentInfo getCMCBlob(X509Certificate signerCert, String nickname,
String[] rValue, String format, CryptoManager manager, String transactionMgtEnable,
String transactionMgtId, String identityProofEnable, String identityProofSharedSecret,
SEQUENCE controlSeq, SEQUENCE otherMsgSeq, int bpid) {
String tokenname = "internal";
ContentInfo fullEnrollmentReq = null;
try {
java.security.PrivateKey privKey = null;
SignerIdentifier si = null;
BigInteger serialno = signerCert.getSerialNumber();
byte[] certB = signerCert.getEncoded();
X509CertImpl impl = new X509CertImpl(certB);
X500Name issuerName = (X500Name) impl.getIssuerDN();
byte[] issuerByte = issuerName.getEncoded();
ByteArrayInputStream istream = new ByteArrayInputStream(issuerByte);
Name issuer = (Name) Name.getTemplate().decode(istream);
IssuerAndSerialNumber ias = new IssuerAndSerialNumber(
issuer, new INTEGER(serialno.toString()));
si = new SignerIdentifier(
SignerIdentifier.ISSUER_AND_SERIALNUMBER, ias, null);
privKey = getPrivateKey(tokenname, nickname);
TaggedRequest trq = null;
PKCS10 pkcs = null;
CertReqMsg certReqMsg = null;
// create CMC req
SEQUENCE reqSequence = new SEQUENCE();
try {
for (int k = 0; k < rValue.length; k++) {
String asciiBASE64Blob = rValue[k];
byte[] decodedBytes = Utils.base64decode(asciiBASE64Blob);
if (format.equals("crmf")) {
ByteArrayInputStream reqBlob =
new ByteArrayInputStream(decodedBytes);
SEQUENCE crmfMsgs = null;
try {
crmfMsgs = (SEQUENCE) new SEQUENCE.OF_Template(new
CertReqMsg.Template()).decode(reqBlob);
} catch (InvalidBERException ee) {
System.out.println("This is not a crmf request. Or this request has an error.");
System.exit(1);
}
certReqMsg = (CertReqMsg) crmfMsgs.elementAt(0);
trq = new TaggedRequest(TaggedRequest.CRMF, null,
certReqMsg);
} else if (format.equals("pkcs10")) {
try {
pkcs = new PKCS10(decodedBytes);
} catch (IllegalArgumentException e) {
System.out.println("This is not a PKCS10 request.");
System.exit(1);
}
ByteArrayInputStream crInputStream = new ByteArrayInputStream(
pkcs.toByteArray());
CertificationRequest cr = (CertificationRequest)
CertificationRequest.getTemplate().decode(crInputStream);
TaggedCertificationRequest tcr = new TaggedCertificationRequest(
new INTEGER(bpid++), cr);
trq = new
TaggedRequest(TaggedRequest.PKCS10, tcr, null);
} else {
System.out.println("Unrecognized request format: " + format);
System.exit(1);
}
reqSequence.addElement(trq);
}
} catch (IOException e) {
throw new IOException("Internal Error - " + e.toString());
} catch (SignatureException e) {
throw new IOException("Internal Error - " + e.toString());
} catch (NoSuchAlgorithmException e) {
throw new IOException("Internal Error - " + e.toString());
}
if (transactionMgtEnable.equals("true"))
bpid = addTransactionAttr(bpid, controlSeq, transactionMgtId, format,
pkcs, certReqMsg);
if (identityProofEnable.equals("true"))
bpid = addIdentityProofAttr(bpid, controlSeq, reqSequence,
identityProofSharedSecret);
PKIData pkidata = new PKIData(controlSeq, reqSequence, new SEQUENCE(), otherMsgSeq);
EncapsulatedContentInfo ci = new
EncapsulatedContentInfo(OBJECT_IDENTIFIER.id_cct_PKIData, pkidata);
// SHA1 is the default digest Alg for now.
DigestAlgorithm digestAlg = null;
SignatureAlgorithm signAlg = SignatureAlgorithm.RSASignatureWithSHA1Digest;
org.mozilla.jss.crypto.PrivateKey.Type signingKeyType =
((org.mozilla.jss.crypto.PrivateKey) privKey).getType();
if (signingKeyType.equals(org.mozilla.jss.crypto.PrivateKey.Type.DSA))
signAlg = SignatureAlgorithm.DSASignatureWithSHA1Digest;
MessageDigest SHADigest = null;
byte[] digest = null;
try {
SHADigest = MessageDigest.getInstance("SHA1");
digestAlg = DigestAlgorithm.SHA1;
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
pkidata.encode(ostream);
digest = SHADigest.digest(ostream.toByteArray());
} catch (NoSuchAlgorithmException e) {
}
SignerInfo signInfo = new
SignerInfo(si, null, null, OBJECT_IDENTIFIER.id_cct_PKIData, digest, signAlg,
(org.mozilla.jss.crypto.PrivateKey) privKey);
SET signInfos = new SET();
signInfos.addElement(signInfo);
SET digestAlgs = new SET();
if (digestAlg != null) {
AlgorithmIdentifier ai = new AlgorithmIdentifier(digestAlg.toOID(), null);
digestAlgs.addElement(ai);
}
org.mozilla.jss.crypto.X509Certificate[] agentChain = manager.buildCertificateChain(signerCert);
SET certs = new SET();
for (int i = 0; i < agentChain.length; i++) {
ANY cert = new ANY(agentChain[i].getEncoded());
certs.addElement(cert);
}
SignedData req = new SignedData(digestAlgs, ci, certs, null, signInfos);
fullEnrollmentReq = new ContentInfo(req);
ByteArrayOutputStream bs = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(bs);
if (fullEnrollmentReq != null) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
fullEnrollmentReq.encode(os);
ps.print(Utils.base64encode(os.toByteArray()));
}
String asciiBASE64Blob = bs.toString();
System.out.println("");
System.out.println("The CMC enrollment request in base-64 encoded format:");
System.out.println("");
System.out.println(asciiBASE64Blob);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
return fullEnrollmentReq;
}
static void printUsage() {
System.out.println("");
System.out.println("Usage: CMCRequest ");
System.out.println("For example, CMCRequest CMCRequest.cfg");
System.out.println("");
System.out.println("The configuration file should look like as follows:");
System.out.println("");
System.out.println("#numRequests: Total number of PKCS10 requests or CRMF requests.");
System.out.println("numRequests=1");
System.out.println("");
System.out.println("#input: full path for the PKCS10 request or CRMF request,");
System.out.println("#the content must be in Base-64 encoded format");
System.out.println("#Multiple files are supported. They must be separated by space.");
System.out.println("input=crmf1");
System.out.println("");
System.out.println("#output: full path for the CMC request in binary format");
System.out.println("output=/u/doc/cmcReq");
System.out.println("");
System.out.println("#nickname: nickname for agent certificate which will be used");
System.out.println("#to sign the CMC full request.");
System.out.println("nickname=CMS Agent Certificate");
System.out.println("");
System.out.println("#dbdir: directory for cert8.db, key3.db and secmod.db");
System.out.println("dbdir=/u/smith/.netscape");
System.out.println("");
System.out.println("#password: password for cert8.db which stores the agent");
System.out.println("#certificate");
System.out.println("password=pass");
System.out.println("");
System.out.println("#format: request format, either pkcs10 or crmf");
System.out.println("format=crmf");
System.out.println("");
System.out.println("#confirmCertAcceptance.enable: if true, then the request will");
System.out.println("#contain this control. Otherwise, false.");
System.out.println("confirmCertAcceptance.enable=true");
System.out.println("");
System.out.println("#confirmCertAcceptance.serial: The serial number for");
System.out.println("#confirmCertAcceptance control");
System.out.println("confirmCertAcceptance.serial=3");
System.out.println("");
System.out.println("#confirmCertAcceptance.issuer: The issuer name for");
System.out.println("#confirmCertAcceptance control");
System.out.println("confirmCertAcceptance.issuer=cn=Certificate Manager,c=us");
System.out.println("");
System.out.println("#getCert.enable: if true, then the request will contain this");
System.out.println("#control. Otherwise, false.");
System.out.println("getCert.enable=true");
System.out.println("");
System.out.println("#getCert.serial: The serial number for getCert control");
System.out.println("getCert.serial=3");
System.out.println("");
System.out.println("#getCert.issuer: The issuer name for getCert control");
System.out.println("getCert.issuer=cn=Certificate Manager,c=us");
System.out.println("");
System.out.println("#dataReturn.enable: if true, then the request will contain");
System.out.println("#this control. Otherwise, false.");
System.out.println("dataReturn.enable=true");
System.out.println("");
System.out.println("#dataReturn.data: data contained in the control.");
System.out.println("dataReturn.data=test");
System.out.println("");
System.out.println("#transactionMgt.enable: if true, then the request will contain");
System.out.println("#this control. Otherwise, false.");
System.out.println("transactionMgt.enable=true");
System.out.println("");
System.out.println("#transactionMgt.id: transaction identifier. Verisign recommend");
System.out.println("#transactionId to be MD5 hash of publicKey.");
System.out.println("transactionMgt.id=");
System.out.println("");
System.out.println("#senderNonce.enable: if true, then the request will contain this");
System.out.println("#control. Otherwise, false.");
System.out.println("senderNonce.enable=true");
System.out.println("");
System.out.println("#senderNonce.id: sender nonce");
System.out.println("senderNonce.id=");
System.out.println("");
System.out.println("#revRequest.enable: if true, then the request will contain this");
System.out.println("#control. Otherwise, false.");
System.out.println("revRequest.enable=true");
System.out.println("");
System.out.println("#revRequest.nickname: The nickname for the revoke certificate");
System.out.println("revRequest.nickname=newuser's 102504a ID");
System.out.println("");
System.out.println("#revRequest.issuer: The issuer name for the certificate being");
System.out.println("#revoked.");
System.out.println("revRequest.issuer=cn=Certificate Manager,c=us");
System.out.println("");
System.out.println("#revRequest.serial: The serial number for the certificate being");
System.out.println("#revoked.");
System.out.println("revRequest.serial=61");
System.out.println("");
System.out.println("#revRequest.reason: The reason for revoking this certificate: ");
System.out.println("# unspecified, keyCompromise, caCompromise,");
System.out.println("# affiliationChanged, superseded, cessationOfOperation,");
System.out.println("# certificateHold, removeFromCRL");
System.out.println("revRequest.reason=unspecified");
System.out.println("");
System.out.println("#revRequest.sharedSecret: The sharedSecret");
System.out.println("revRequest.sharedSecret=");
System.out.println("");
System.out.println("#revRequest.comment: The human readable comment");
System.out.println("revRequest.comment=");
System.out.println("");
System.out.println("#revRequest.invalidityDatePresent: if true, the current time will be the");
System.out.println("# invalidityDate. If false, no invalidityDate");
System.out.println("# is present.");
System.out.println("revRequest.invalidityDatePresent=false");
System.out.println("");
System.out.println("#identityProof.enable: if true, then the request will contain");
System.out.println("#this control. Otherwise, false.");
System.out.println("identityProof.enable=true");
System.out.println("");
System.out.println("#identityProof.sharedSecret: Shared Secret");
System.out.println("identityProof.sharedSecret=testing");
System.out.println("");
System.out.println("#popLinkWitness.enable: if true, then the request will contain");
System.out.println("#this control. Otherwise, false.");
System.out.println("#If you want to test this control, make sure to use CRMFPopClient ");
System.out.println("# to generate the CRMF request which will include the ");
System.out.println("#idPOPLinkWitness attribute in the controls section of the ");
System.out.println("#CertRequest structure.");
System.out.println("popLinkWitness.enable=false");
System.out.println("");
System.out.println("#LraPopWitness.enable: if true, then the request will contain this");
System.out.println("#control. Otherwise, false.");
System.out.println("LraPopWitness.enable=true");
System.out.println("");
System.out.println("#LraPopWitness.bodyPartIDs: List of body part IDs");
System.out.println("#Each id is separated by space.");
System.out.println("LraPopWitness.bodyPartIDs=1");
System.exit(1);
}
private static int addLraPopWitnessAttr(int bpid, SEQUENCE seq, String bodyPartIDs) {
StringTokenizer tokenizer = new StringTokenizer(bodyPartIDs, " ");
SEQUENCE bodyList = new SEQUENCE();
while (tokenizer.hasMoreTokens()) {
String s = tokenizer.nextToken();
bodyList.addElement(new INTEGER(s));
}
LraPopWitness lra = new LraPopWitness(new INTEGER(0), bodyList);
TaggedAttribute cont = new TaggedAttribute(new
INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_lraPOPWitness, lra);
System.out.println("Successfully create LRA POP witness control. bpid = " + (bpid - 1));
System.out.println("");
seq.addElement(cont);
return bpid;
}
private static int addConfirmCertAttr(int bpid, SEQUENCE seq, String confirmCertIssuer,
String confirmCertSerial) {
try {
INTEGER serial = new INTEGER(confirmCertSerial);
X500Name issuername = new X500Name(confirmCertIssuer);
byte[] issuerbyte = issuername.getEncoded();
ANY issuern = new ANY(issuerbyte);
CMCCertId cmcCertId = new CMCCertId(issuern, serial, null);
TaggedAttribute cmcCertIdControl = new TaggedAttribute(new
INTEGER(bpid++),
OBJECT_IDENTIFIER.id_cmc_idConfirmCertAcceptance, cmcCertId);
System.out.println("Successfully create confirm certificate acceptance control. bpid = " + (bpid - 1));
System.out.println("");
seq.addElement(cmcCertIdControl);
} catch (Exception e) {
System.out.println("Error in creating confirm certificate acceptance control. Check the parameters.");
System.exit(1);
}
return bpid;
}
private static ENUMERATED toCRLReason(String str) {
if (str.equalsIgnoreCase("unspecified")) {
return RevRequest.unspecified;
} else if (str.equalsIgnoreCase("keyCompromise")) {
return RevRequest.keyCompromise;
} else if (str.equalsIgnoreCase("caCompromise")) {
return RevRequest.cACompromise;
} else if (str.equalsIgnoreCase("affiliationChanged")) {
return RevRequest.affiliationChanged;
} else if (str.equalsIgnoreCase("superseded")) {
return RevRequest.superseded;
} else if (str.equalsIgnoreCase("cessationOfOperation")) {
return RevRequest.cessationOfOperation;
} else if (str.equalsIgnoreCase("certificateHold")) {
return RevRequest.certificateHold;
} else if (str.equalsIgnoreCase("removeFromCRL")) {
return RevRequest.removeFromCRL;
}
System.out.println("Unrecognized CRL reason");
System.exit(1);
return RevRequest.unspecified;
}
private static int addIdentityProofAttr(int bpid, SEQUENCE seq, SEQUENCE reqSequence,
String sharedSecret) {
byte[] b = ASN1Util.encode(reqSequence);
byte[] key = null;
byte[] finalDigest = null;
try {
MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1");
key = SHA1Digest.digest(sharedSecret.getBytes());
} catch (NoSuchAlgorithmException ex) {
System.out.println("CMCRequest::addIdentityProofAttr() - "
+ "No such algorithm!");
return -1;
}
try {
MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1");
HMACDigest hmacDigest = new HMACDigest(SHA1Digest, key);
hmacDigest.update(b);
finalDigest = hmacDigest.digest();
} catch (NoSuchAlgorithmException ex) {
}
TaggedAttribute identityProof = new TaggedAttribute(new
INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_identityProof,
new OCTET_STRING(finalDigest));
seq.addElement(identityProof);
System.out.println("Identity Proof control: ");
System.out.print(" Value: ");
for (int i = 0; i < finalDigest.length; i++) {
System.out.print(finalDigest[i] + " ");
}
System.out.println("");
System.out.println("Successfully create identityProof control. bpid = " + (bpid - 1));
System.out.println("");
return bpid;
}
private static int addRevRequestAttr(int bpid, SEQUENCE seq, SEQUENCE otherMsgSeq, String nickname,
String revRequestIssuer, String revRequestSerial, String revRequestReason,
String revRequestSharedSecret, String revRequestComment, String invalidityDatePresent,
CryptoManager manager) {
try {
if (nickname.length() <= 0) {
System.out.println("The nickname for the certificate being revoked is null");
System.exit(1);
}
String nickname1 = nickname;
UTF8String comment = null;
OCTET_STRING sharedSecret = null;
GeneralizedTime d = null;
X500Name subjectname = new X500Name(revRequestIssuer);
INTEGER snumber = new INTEGER(revRequestSerial);
ENUMERATED reason = toCRLReason(revRequestReason);
if (revRequestSharedSecret.length() > 0)
sharedSecret = new OCTET_STRING(revRequestSharedSecret.getBytes());
if (revRequestComment.length() > 0)
comment = new UTF8String(revRequestComment);
if (invalidityDatePresent.equals("true"))
d = new GeneralizedTime(new Date());
RevRequest revRequest =
new RevRequest(new ANY(subjectname.getEncoded()), snumber,
reason, d, sharedSecret, comment);
int revokeBpid = bpid;
TaggedAttribute revRequestControl = new TaggedAttribute(
new INTEGER(bpid++),
OBJECT_IDENTIFIER.id_cmc_revokeRequest, revRequest);
seq.addElement(revRequestControl);
if (sharedSecret != null) {
System.out.println("Successfully create revRequest control. bpid = " + (bpid - 1));
System.out.println("");
return bpid;
}
EncapsulatedContentInfo revokeContent = new EncapsulatedContentInfo(
OBJECT_IDENTIFIER.id_cct_PKIData, revRequestControl);
DigestAlgorithm digestAlg1 = null;
SignatureAlgorithm signAlg1 = SignatureAlgorithm.RSASignatureWithSHA1Digest;
java.security.PrivateKey revokePrivKey = null;
X509Certificate revokeCert = null;
try {
revokeCert = manager.findCertByNickname(nickname1);
} catch (ObjectNotFoundException e) {
System.out.println("Certificate not found: " + nickname1);
System.exit(1);
}
revokePrivKey = manager.findPrivKeyByCert(revokeCert);
org.mozilla.jss.crypto.PrivateKey.Type signingKeyType1 =
((org.mozilla.jss.crypto.PrivateKey) revokePrivKey).getType();
if (signingKeyType1.equals(org.mozilla.jss.crypto.PrivateKey.Type.DSA))
signAlg1 = SignatureAlgorithm.DSASignatureWithSHA1Digest;
MessageDigest rSHADigest = null;
byte[] rdigest = null;
try {
rSHADigest = MessageDigest.getInstance("SHA1");
digestAlg1 = DigestAlgorithm.SHA1;
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
revRequestControl.encode(ostream);
rdigest = rSHADigest.digest(ostream.toByteArray());
} catch (NoSuchAlgorithmException e) {
}
ByteArrayInputStream bistream =
new ByteArrayInputStream(subjectname.getEncoded());
Name iname = (Name) Name.getTemplate().decode(bistream);
IssuerAndSerialNumber ias1 = new IssuerAndSerialNumber(iname, snumber);
SignerIdentifier rsi = new SignerIdentifier(
SignerIdentifier.ISSUER_AND_SERIALNUMBER, ias1, null);
SignerInfo signInfo1 = new SignerInfo(rsi, null, null,
OBJECT_IDENTIFIER.id_cct_PKIData, rdigest, signAlg1,
(org.mozilla.jss.crypto.PrivateKey) revokePrivKey);
SET signInfos1 = new SET();
signInfos1.addElement(signInfo1);
SET digestAlgs1 = new SET();
if (digestAlg1 != null) {
AlgorithmIdentifier ai1 = new AlgorithmIdentifier(digestAlg1.toOID(), null);
digestAlgs1.addElement(ai1);
}
org.mozilla.jss.crypto.X509Certificate[] revokeCertChain =
manager.buildCertificateChain(revokeCert);
SET certs1 = new SET();
for (int i = 0; i < revokeCertChain.length; i++) {
ANY cert1 = new ANY(revokeCertChain[i].getEncoded());
certs1.addElement(cert1);
}
SignedData sData = new SignedData(digestAlgs1, revokeContent, certs1, null, signInfos1);
OBJECT_IDENTIFIER signedDataOID = new OBJECT_IDENTIFIER("1.2.840.113549.1.7.2");
ByteArrayOutputStream bos1 = new ByteArrayOutputStream();
sData.encode(bos1);
OtherMsg otherMsg = new OtherMsg(new INTEGER(revokeBpid), signedDataOID, new ANY(bos1.toByteArray()));
otherMsgSeq.addElement(otherMsg);
System.out.println("Successfully create revRequest control. bpid = " + (bpid - 1));
System.out.println("");
} catch (Exception e) {
System.out.println("Error in creating revRequest control. Check the parameters.");
System.exit(1);
}
return bpid;
}
private static int addGetCertAttr(int bpid, SEQUENCE seq, String issuer, String serial) {
try {
INTEGER serialno = new INTEGER(serial);
X500Name issuername = new X500Name(issuer);
byte[] issuerbyte = issuername.getEncoded();
ANY issuern = new ANY(issuerbyte);
GetCert getCert = new GetCert(issuern, serialno);
TaggedAttribute getCertControl = new TaggedAttribute(new
INTEGER(bpid++),
OBJECT_IDENTIFIER.id_cmc_getCert, getCert);
System.out.println("Successfully create get certificate control. bpid = " + (bpid - 1));
System.out.println("");
seq.addElement(getCertControl);
} catch (Exception e) {
System.out.println("Error in creating get certificate control. Check the parameters.");
System.exit(1);
}
return bpid;
}
private static int addDataReturnAttr(int bpid, SEQUENCE seq, String str) {
try {
byte bvalue[] = str.getBytes();
System.out.println("Data Return Control: ");
String ss = " Value: ";
for (int m = 0; m < bvalue.length; m++) {
ss = ss + bvalue[m] + " ";
}
System.out.println(ss);
OCTET_STRING s = new OCTET_STRING(bvalue);
TaggedAttribute dataReturnControl = new TaggedAttribute(new
INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_dataReturn, s);
seq.addElement(dataReturnControl);
System.out.println("Successfully create data return control. bpid = " + (bpid - 1));
System.out.println("");
} catch (Exception e) {
System.out.println("Error in creating data return control. Check the parameters.");
System.exit(1);
}
return bpid;
}
private static int addTransactionAttr(int bpid, SEQUENCE seq, String id, String format,
PKCS10 pkcs, CertReqMsg certReqMsg) {
byte[] transId = null;
Date date = new Date();
String salt = "lala123" + date.toString();
if (id == null || id.equals("")) {
try {
MessageDigest MD5Digest = MessageDigest.getInstance("MD5");
if (format.equals("crmf")) {
CertRequest certreq = certReqMsg.getCertReq();
CertTemplate certTemplate = certreq.getCertTemplate();
SubjectPublicKeyInfo pkinfo = certTemplate.getPublicKey();
BIT_STRING bitString = pkinfo.getSubjectPublicKey();
byte[] b = bitString.getBits();
transId = MD5Digest.digest(b);
} else if (format.equals("pkcs10")) {
transId = MD5Digest.digest(pkcs.getSubjectPublicKeyInfo().getKey());
}
} catch (Exception ex) {
transId = salt.getBytes();
}
} else {
transId = id.getBytes();
}
if (transId == null) {
System.out.println("CMCRequest::addTransactionAttr() - "
+ "transId is null!");
return -1;
}
INTEGER ii = new INTEGER(1, transId);
TaggedAttribute transactionId = new TaggedAttribute(new
INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_transactionId, ii);
System.out.println("Transaction ID control: ");
System.out.println(" Value: " + ii.toString());
System.out.println("Successfully create transaction management control. bpid = " + (bpid - 1));
System.out.println("");
seq.addElement(transactionId);
return bpid;
}
private static int addSenderNonceAttr(int bpid, SEQUENCE seq, String nonce) {
byte[] dig;
String sn = nonce;
if (nonce == null || nonce.equals("")) {
// Verisign has transactionID,senderNonce
Date date = new Date();
String salt = "lala123" + date.toString();
try {
MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1");
dig = SHA1Digest.digest(salt.getBytes());
} catch (NoSuchAlgorithmException ex) {
dig = salt.getBytes();
}
sn = Utils.base64encode(dig);
}
byte bb[] = sn.getBytes();
System.out.println("SenderNonce control: ");
String ss = " Value: ";
for (int m = 0; m < bb.length; m++) {
ss = ss + bb[m] + " ";
}
System.out.println(ss);
TaggedAttribute senderNonce = new TaggedAttribute(new
INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_senderNonce,
new OCTET_STRING(sn.getBytes()));
System.out.println("Successfully create sender nonce control. bpid = " + (bpid - 1));
System.out.println("");
seq.addElement(senderNonce);
return bpid;
}
private static int addPopLinkWitnessAttr(int bpid, SEQUENCE controlSeq) {
byte[] seed =
{ 0x10, 0x53, 0x42, 0x24, 0x1a, 0x2a, 0x35, 0x3c,
0x7a, 0x52, 0x54, 0x56, 0x71, 0x65, 0x66, 0x4c,
0x51, 0x34, 0x35, 0x23, 0x3c, 0x42, 0x43, 0x45,
0x61, 0x4f, 0x6e, 0x43, 0x1e, 0x2a, 0x2b, 0x31,
0x32, 0x34, 0x35, 0x36, 0x55, 0x51, 0x48, 0x14,
0x16, 0x29, 0x41, 0x42, 0x43, 0x7b, 0x63, 0x44,
0x6a, 0x12, 0x6b, 0x3c, 0x4c, 0x3f, 0x00, 0x14,
0x51, 0x61, 0x15, 0x22, 0x23, 0x5f, 0x5e, 0x69 };
TaggedAttribute idPOPLinkRandom = new TaggedAttribute(new
INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_idPOPLinkRandom,
new OCTET_STRING(seed));
controlSeq.addElement(idPOPLinkRandom);
System.out.println("Successfully create PopLinkWitness control. bpid = " + (bpid - 1));
System.out.println("");
return bpid;
}
public static void main(String[] s) {
String numRequests = null;
String dbdir = null, nickname = null;
String ifilename = null, ofilename = null, password = null, format = null;
String confirmCertEnable = "false", confirmCertIssuer = null, confirmCertSerial = null;
String getCertEnable = "false", getCertIssuer = null, getCertSerial = null;
String dataReturnEnable = "false", dataReturnData = null;
String transactionMgtEnable = "false", transactionMgtId = null;
String senderNonceEnable = "false", senderNonce = null;
String revCertNickname = "";
String revRequestEnable = "false", revRequestIssuer = null, revRequestSerial = null;
String revRequestReason = null, revRequestSharedSecret = null, revRequestComment = null;
String revRequestInvalidityDatePresent = "false";
String identityProofEnable = "false", identityProofSharedSecret = null;
String popLinkWitnessEnable = "false";
String bodyPartIDs = null, lraPopWitnessEnable = "false";
System.out.println("");
// Check that the correct # of arguments were submitted to the program
if (s.length != (ARGC)) {
System.out.println("Wrong number of parameters:" + s.length);
printUsage();
}
String configFile = s[0];
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(
new BufferedInputStream(
new FileInputStream(
configFile))));
} catch (FileNotFoundException e) {
System.out.println("CMCRequest: can't find configuration file: " + configFile);
printUsage();
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
try {
String str = "";
while ((str = reader.readLine()) != null) {
str = str.trim();
if (!str.startsWith("#") && str.length() > 0) {
int index = str.indexOf("=");
String name = "";
String val = "";
if (index == -1) {
System.out.println("Error in configuration file: " + str);
System.exit(1);
}
name = str.substring(0, index);
if (index != str.length() - 1)
val = str.substring(index + 1);
if (name.equals("format")) {
format = val;
} else if (name.equals("dbdir")) {
dbdir = val;
} else if (name.equals("nickname")) {
nickname = val;
} else if (name.equals("password")) {
password = val;
} else if (name.equals("output")) {
ofilename = val;
} else if (name.equals("input")) {
ifilename = val;
} else if (name.equals("confirmCertAcceptance.serial")) {
confirmCertSerial = val;
} else if (name.equals("confirmCertAcceptance.issuer")) {
confirmCertIssuer = val;
} else if (name.equals("confirmCertAcceptance.enable")) {
confirmCertEnable = val;
} else if (name.equals("getCert.enable")) {
getCertEnable = val;
} else if (name.equals("getCert.issuer")) {
getCertIssuer = val;
} else if (name.equals("getCert.serial")) {
getCertSerial = val;
} else if (name.equals("dataReturn.enable")) {
dataReturnEnable = val;
} else if (name.equals("dataReturn.data")) {
dataReturnData = val;
} else if (name.equals("transactionMgt.enable")) {
transactionMgtEnable = val;
} else if (name.equals("transactionMgt.id")) {
transactionMgtId = val;
} else if (name.equals("senderNonce.enable")) {
senderNonceEnable = val;
} else if (name.equals("senderNonce")) {
senderNonce = val;
} else if (name.equals("revRequest.enable")) {
revRequestEnable = val;
} else if (name.equals("revRequest.issuer")) {
revRequestIssuer = val;
} else if (name.equals("revRequest.serial")) {
revRequestSerial = val;
} else if (name.equals("revRequest.reason")) {
revRequestReason = val;
} else if (name.equals("revRequest.sharedSecret")) {
revRequestSharedSecret = val;
} else if (name.equals("revRequest.comment")) {
revRequestComment = val;
} else if (name.equals("revRequest.invalidityDatePresent")) {
revRequestInvalidityDatePresent = val;
} else if (name.equals("revRequest.nickname")) {
revCertNickname = val;
} else if (name.equals("identityProof.enable")) {
identityProofEnable = val;
} else if (name.equals("identityProof.sharedSecret")) {
identityProofSharedSecret = val;
} else if (name.equals("popLinkWitness.enable")) {
popLinkWitnessEnable = val;
} else if (name.equals("LraPopWitness.enable")) {
lraPopWitnessEnable = val;
} else if (name.equals("LraPopWitness.bodyPartIDs")) {
bodyPartIDs = val;
} else if (name.equals("numRequests")) {
numRequests = val;
}
}
}
} catch (Exception e) {
e.printStackTrace();
printUsage();
}
if (ifilename == null) {
System.out.println("Missing input filename for PKCS10 or CRMF.");
printUsage();
}
int num = 0;
if (numRequests == null) {
System.out.println("Missing numRequests.");
printUsage();
} else {
try {
num = Integer.parseInt(numRequests);
} catch (Exception ee) {
System.out.println("numRequests must be integer");
System.exit(1);
}
}
StringTokenizer tokenizer = new StringTokenizer(ifilename, " ");
String[] ifiles = new String[num];
for (int i = 0; i < num; i++) {
String ss = tokenizer.nextToken();
ifiles[i] = ss;
if (ss == null) {
System.out.println("Missing input file for the request.");
System.exit(1);
}
}
if (ofilename == null) {
System.out.println("Missing output filename for the CMC request.");
printUsage();
}
if (format == null) {
System.out.println("Missing format.");
printUsage();
}
if (password == null) {
System.out.println("Missing password.");
printUsage();
}
if (nickname == null) {
System.out.println("Missing nickname.");
printUsage();
}
try {
// initialize CryptoManager
if (dbdir == null)
dbdir = ".";
String mPrefix = "";
System.out.println("cert/key prefix = " + mPrefix);
System.out.println("path = " + dbdir);
CryptoManager.InitializationValues vals =
new CryptoManager.InitializationValues(dbdir, mPrefix,
mPrefix, "secmod.db");
CryptoManager.initialize(vals);
CryptoManager cm = CryptoManager.getInstance();
CryptoToken token = cm.getInternalKeyStorageToken();
Password pass = new Password(password.toCharArray());
token.login(pass);
X509Certificate signerCert = null;
signerCert = cm.findCertByNickname(nickname);
String[] requests = new String[num];
for (int i = 0; i < num; i++) {
BufferedReader inputBlob = null;
try {
inputBlob = new BufferedReader(new InputStreamReader(
new BufferedInputStream(new FileInputStream(ifiles[i]))));
} catch (FileNotFoundException e) {
System.out.println("CMCRequest: can't find file " +
ifiles[i] + ":\n" + e);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
// (3) Read the entire contents of the specified BASE 64 encoded
// blob into a String() object throwing away any
// headers beginning with HEADER and any trailers beginning
// with TRAILER
String asciiBASE64BlobChunk = new String();
String asciiBASE64Blob = new String();
try {
while ((asciiBASE64BlobChunk = inputBlob.readLine()) != null) {
if (!(asciiBASE64BlobChunk.startsWith(HEADER)) &&
!(asciiBASE64BlobChunk.startsWith(TRAILER))) {
asciiBASE64Blob += asciiBASE64BlobChunk.trim();
}
}
requests[i] = asciiBASE64Blob;
} catch (IOException e) {
System.out.println("CMCRequest: Unexpected BASE64 " +
"encoded error encountered in readLine():\n" +
e);
}
// (4) Close the DataInputStream() object
try {
inputBlob.close();
} catch (IOException e) {
System.out.println("CMCRequest(): Unexpected BASE64 " +
"encoded error encountered in close():\n" + e);
}
}
SEQUENCE controlSeq = new SEQUENCE();
int bpid = 1;
if (confirmCertEnable.equalsIgnoreCase("true")) {
if (confirmCertIssuer.length() == 0 || confirmCertSerial.length() == 0) {
System.out.println("Illegal parameters for confirm certificate acceptance control");
printUsage();
System.exit(1);
}
bpid = addConfirmCertAttr(bpid, controlSeq, confirmCertIssuer, confirmCertSerial);
}
if (lraPopWitnessEnable.equalsIgnoreCase("true")) {
if (bodyPartIDs.length() == 0) {
System.out.println("Illegal parameters for Lra Pop Witness control");
printUsage();
System.exit(1);
}
bpid = addLraPopWitnessAttr(bpid, controlSeq, bodyPartIDs);
}
if (getCertEnable.equalsIgnoreCase("true")) {
if (getCertIssuer.length() == 0 || getCertSerial.length() == 0) {
System.out.println("Illegal parameters for get certificate control");
printUsage();
System.exit(1);
}
bpid = addGetCertAttr(bpid, controlSeq, getCertIssuer, getCertSerial);
}
if (dataReturnEnable.equalsIgnoreCase("true")) {
if (dataReturnData.length() == 0) {
System.out.println("Illegal parameters for data return control");
printUsage();
System.exit(1);
}
bpid = addDataReturnAttr(bpid, controlSeq, dataReturnData);
}
if (senderNonceEnable.equalsIgnoreCase("true"))
bpid = addSenderNonceAttr(bpid, controlSeq, senderNonce);
if (popLinkWitnessEnable.equalsIgnoreCase("true"))
bpid = addPopLinkWitnessAttr(bpid, controlSeq);
SEQUENCE otherMsgSeq = new SEQUENCE();
if (revRequestEnable.equalsIgnoreCase("true")) {
if (revRequestIssuer.length() == 0 || revRequestSerial.length() == 0 ||
revRequestReason.length() == 0) {
System.out.println("Illegal parameters for revRequest control");
printUsage();
System.exit(1);
}
bpid = addRevRequestAttr(bpid, controlSeq, otherMsgSeq, revCertNickname,
revRequestIssuer, revRequestSerial, revRequestReason, revRequestSharedSecret,
revRequestComment, revRequestInvalidityDatePresent, cm);
}
ContentInfo cmcblob = getCMCBlob(signerCert, nickname, requests, format,
cm, transactionMgtEnable, transactionMgtId, identityProofEnable,
identityProofSharedSecret, controlSeq, otherMsgSeq, bpid);
// (6) Finally, print the actual CMC blob to the
// specified output file
FileOutputStream os = null;
try {
os = new FileOutputStream(ofilename);
cmcblob.encode(os);
System.out.println("");
System.out.println("");
System.out.println("The CMC enrollment request in binary format is stored in " +
ofilename + ".");
} catch (IOException e) {
System.out.println("CMCRequest: unable to open file " + ofilename +
" for writing:\n" + e);
}
try {
os.close();
} catch (IOException e) {
System.out.println("CMCRequest: Unexpected error " +
"encountered while attempting to close() " +
"\n" + e);
}
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
}