From 621d9e5c413e561293d7484b93882d985b3fe15f Mon Sep 17 00:00:00 2001 From: Endi Sukma Dewata Date: Sat, 24 Mar 2012 02:27:47 -0500 Subject: Removed unnecessary pki folder. Previously the source code was located inside a pki folder. This folder was created during svn migration and is no longer needed. This folder has now been removed and the contents have been moved up one level. Ticket #131 --- .../src/com/netscape/cmstools/CRMFPopClient.java | 620 +++++++++++++++++++++ 1 file changed, 620 insertions(+) create mode 100644 base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java (limited to 'base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java') diff --git a/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java b/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java new file mode 100644 index 000000000..c1d463cdb --- /dev/null +++ b/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java @@ -0,0 +1,620 @@ +// --- 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.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.security.KeyPair; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import netscape.security.x509.X500Name; + +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.asn1.ASN1Util; +import org.mozilla.jss.asn1.BIT_STRING; +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.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.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). + * + * Usage: + * + *
+ *     CRMFPopClient  TOKEN_PWD
+ *                    PROFILE_NAME HOST PORT USER_NAME REQUESTOR_NAME
+ *                    POP_OPTION
+ *                    SUBJECT_DN [OUTPUT_CERT_REQ]
+ * 
+ *                    ---  or  ---
+ * 
+ *     CRMFPopClient  TOKEN_PWD
+ *                    POP_OPTION
+ *                    OUTPUT_CERT_REQ SUBJECT_DN
+ * 
+ * 
+ *     where POP_OPTION can be [POP_SUCCESS or POP_FAIL or POP_NONE]
+ * 
+ *

+ * Examples: + * + *

+ *     CRMFPopClient  password123
+ *                    caEncUserCert host.example.com 1026 MyUid MyUid
+ *                    [POP_SUCCESS or POP_FAIL or POP_NONE]
+ *                    CN=MyTest,C=US,UID=MyUid
+ * 
+ *                    ---  or  ---
+ * 
+ *     CRMFPopClient  password123
+ *                    caEncUserCert host.example.com 1026 joe joe
+ *                    [POP_SUCCESS or POP_FAIL or POP_NONE]
+ *                    CN=MyTest,C=US,UID=MyUid OUTPUT_CERT_REQ 
+ * 
+ *                    ---  or  ---
+ * 
+ *     CRMFPopClient  password123
+ *                    [POP_SUCCESS or POP_FAIL or POP_NONE]
+ *                    OUTPUT_CERT_REQ CN=MyTest,C=US,UID=MyUid
+ * 
+ *

+ * + *

+ * IMPORTANT:  The file "transport.txt" needs to be created to contain the
+ *             transport certificate in its base64 encoded format.  This
+ *             file should consist of one line containing a single certificate
+ *             in base64 encoded format with the header and footer removed.
+ * 
+ *

+ * + * @version $Revision$, $Date$ + */ +public class CRMFPopClient { + + private static void usage() { + System.out.println(""); + System.out.println("Description: A command-line utility used to generate a"); + System.out.println(" Certificate Request Message Format (CRMF)"); + System.out.println(" request with proof of possesion (POP).\n\n"); + System.out.println("Usage:"); + System.out.println(""); + System.out.println(" CRMFPopClient TOKEN_PWD"); + System.out.println(" PROFILE_NAME HOST PORT USER_NAME REQUESTOR_NAME"); + System.out.println(" POP_OPTION"); + System.out.println(" SUBJECT_DN [OUTPUT_CERT_REQ] \n"); + System.out.println(" --- or ---\n"); + System.out.println(" CRMFPopClient TOKEN_PWD"); + System.out.println(" POP_OPTION"); + System.out.println(" OUTPUT_CERT_REQ SUBJECT_DN\n\n"); + System.out.println(" where POP_OPTION can be [POP_SUCCESS or POP_FAIL or POP_NONE]\n\n"); + System.out.println("Examples:"); + System.out.println(""); + System.out.println(" CRMFPopClient password123"); + System.out.println(" caEncUserCert host.example.com 1026 MyUid MyUid"); + System.out.println(" [POP_SUCCESS or POP_FAIL or POP_NONE]"); + System.out.println(" CN=MyTest,C=US,UID=MyUid\n"); + System.out.println(" --- or ---\n"); + System.out.println(" CRMFPopClient password123"); + System.out.println(" caEncUserCert host.example.com 1026 MyUid myUid"); + System.out.println(" [POP_SUCCESS or POP_FAIL or POP_NONE]"); + System.out.println(" CN=MyTest,C=US,UID=MyUid OUTPUT_CERT_REQ\n"); + System.out.println(" --- or ---\n"); + System.out.println(" CRMFPopClient password123"); + System.out.println(" [POP_SUCCESS or POP_FAIL or POP_NONE]"); + System.out.println(" OUTPUT_CERT_REQ CN=MyTest,C=US,UID=MyUid"); + System.out.println("\n"); + System.out.println("IMPORTANT: The file \"transport.txt\" needs to be created to contain the"); + System.out.println(" transport certificate in its base64 encoded format. This"); + System.out.println(" file should consist of one line containing a single certificate"); + System.out.println(" in base64 encoded format with the header and footer removed.\n"); + } + + private static int getRealArgsLength(String args[]) { + + int len = args.length; + + String curArg = ""; + int finalLen = len; + + for (int i = 0; i < len; i++) { + + curArg = args[i]; + // System.out.println("arg[" + i + "] " + curArg); + + if (curArg == null || curArg.equalsIgnoreCase("")) { + finalLen--; + } + + } + + //System.out.println("getRealArgsLength: returning " + finalLen); + + if (finalLen < 0) + finalLen = 0; + + return finalLen; + + } + + public static void main(String args[]) { + + int argsLen = getRealArgsLength(args); + + // System.out.println("args length " + argsLen); + + System.out.println("\n\nProof Of Possession Utility...."); + System.out.println(""); + + if (argsLen == 0 || (argsLen != 8 && argsLen != 9 && argsLen != 10 && argsLen != 4)) { + usage(); + return; + } + + String DB_DIR = "./"; + String TOKEN_PWD = args[0]; + int KEY_LEN = 1024; + + int PORT = 0; + String USER_NAME = null; + String REQUESTOR_NAME = null; + String PROFILE_NAME = null; + + String HOST = null; + String SUBJ_DN = null; + + if (argsLen >= 8) { + PROFILE_NAME = args[1]; + HOST = args[2]; + + PORT = Integer.parseInt(args[3]); + + USER_NAME = args[4]; + REQUESTOR_NAME = args[5]; + + SUBJ_DN = args[7]; + + } + + String POP_OPTION = null; + String OUTPUT_CERT_REQ = null; + + if (argsLen == 4) + POP_OPTION = args[1]; + else + POP_OPTION = args[6]; + + int doServerHit = 1; + + if (argsLen >= 9) { + OUTPUT_CERT_REQ = args[8]; + } + + if (argsLen == 4) { + doServerHit = 0; + OUTPUT_CERT_REQ = args[2]; + SUBJ_DN = args[3]; + } + + int dont_do_pop = 0; + + if (POP_OPTION.equals("POP_NONE")) { + dont_do_pop = 1; + } + + URL url = null; + URLConnection conn = null; + InputStream is = null; + BufferedReader reader = null; + KeyPair pair = null; + + boolean foundTransport = false; + String transportCert = null; + try { + BufferedReader br = new BufferedReader(new FileReader("./transport.txt")); + transportCert = br.readLine(); + foundTransport = true; + } catch (Exception e) { + System.out.println("ERROR: cannot find ./transport.txt, so no key archival"); + + return; + } + + try { + CryptoManager.initialize(DB_DIR); + } catch (Exception e) { + // it is ok if it is already initialized + System.out.println("INITIALIZATION ERROR: " + e.toString()); + // return; + } + + try { + CryptoManager manager = CryptoManager.getInstance(); + String token_pwd = TOKEN_PWD; + CryptoToken token = manager.getInternalKeyStorageToken(); + Password password = new Password(token_pwd.toCharArray()); + try { + token.login(password); + } catch (Exception e) { + //System.out.println("login Exception: " + e.toString()); + if (!token.isLoggedIn()) { + token.initPassword(password, password); + } + } + + System.out.println("."); //"done with cryptomanager"); + + KeyPairGenerator kg = token.getKeyPairGenerator( + KeyPairAlgorithm.RSA); + kg.initialize(KEY_LEN); + + String profileName = PROFILE_NAME; + pair = kg.genKeyPair(); + + System.out.println("."); //key pair generated"); + + // wrap private key + byte transport[] = Utils.base64decode(transportCert); + + X509Certificate tcert = manager.importCACertPackage(transport); + + byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }; + + KeyGenerator kg1 = token.getKeyGenerator(KeyGenAlgorithm.DES3); + SymmetricKey sk = kg1.generate(); + + System.out.println("."); //before KeyWrapper"); + + // wrap private key using session + KeyWrapper wrapper1 = + token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD); + + System.out.println("."); //key wrapper created"); + + wrapper1.initWrap(sk, new IVParameterSpec(iv)); + + System.out.println("."); //key wrapper inited"); + byte key_data[] = wrapper1.wrap((org.mozilla.jss.crypto.PrivateKey) pair.getPrivate()); + + System.out.println("."); //key wrapper wrapped"); + + // wrap session using transport + KeyWrapper rsaWrap = token.getKeyWrapper( + KeyWrapAlgorithm.RSA); + + System.out.println("."); //got rsaWrapper"); + + rsaWrap.initWrap(tcert.getPublicKey(), null); + + System.out.println("."); //rsaWrap inited"); + + byte session_data[] = rsaWrap.wrap(sk); + + System.out.println("."); //rsaWrapped"); + + try { + // create CRMF + CertTemplate certTemplate = new CertTemplate(); + certTemplate.setVersion(new INTEGER(2)); + + Name n1 = getJssName(SUBJ_DN); + + Name n = new Name(); + + n.addCommonName("Me"); + n.addCountryName("US"); + n.addElement(new AVA(new OBJECT_IDENTIFIER("0.9.2342.19200300.100.1.1"), new PrintableString("MyUid"))); + + if (n1 != null) + certTemplate.setSubject(n1); + else + certTemplate.setSubject(n); + + certTemplate.setPublicKey(new SubjectPublicKeyInfo(pair.getPublic())); + // set extension + AlgorithmIdentifier algS = + new AlgorithmIdentifier(new OBJECT_IDENTIFIER("1.2.840.113549.3.7"), new OCTET_STRING(iv)); + EncryptedValue encValue = + new EncryptedValue(null, algS, new BIT_STRING(session_data, 0), null, null, new BIT_STRING( + key_data, 0)); + EncryptedKey key = new EncryptedKey(encValue); + PKIArchiveOptions opt = new PKIArchiveOptions(key); + SEQUENCE seq = new SEQUENCE(); + if (foundTransport) { + seq.addElement(new AVA(new OBJECT_IDENTIFIER("1.3.6.1.5.5.7.5.1.4"), opt)); + } + + // Add idPOPLinkWitness control + String secretValue = "testing"; + byte[] key1 = null; + byte[] finalDigest = null; + try { + MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1"); + key1 = SHA1Digest.digest(secretValue.getBytes()); + } catch (NoSuchAlgorithmException ex) { + } + + /* Example of adding the POP link witness control to CRMF */ + byte[] b = + { 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 }; + + try { + MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1"); + HMACDigest hmacDigest = new HMACDigest(SHA1Digest, key1); + hmacDigest.update(b); + finalDigest = hmacDigest.digest(); + } catch (NoSuchAlgorithmException ex) { + } + + OCTET_STRING ostr = new OCTET_STRING(finalDigest); + seq.addElement(new AVA(OBJECT_IDENTIFIER.id_cmc_idPOPLinkWitness, ostr)); + CertRequest certReq = new CertRequest(new INTEGER(1), certTemplate, seq); + + System.out.println("."); //CertRequest created"); + + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + certReq.encode(bo); + byte[] toBeVerified = bo.toByteArray(); + + byte signature[]; + + System.out.println("."); //CertRequest encoded"); + + Signature signer = token.getSignatureContext( + SignatureAlgorithm.RSASignatureWithMD5Digest); + + System.out.println("."); //signer created"); + + signer.initSign((org.mozilla.jss.crypto.PrivateKey) pair.getPrivate()); + + System.out.println("."); //signer inited"); + + System.out.println("."); //FAIL_OR_SUCC " + FAIL_OR_SUCC); + + if (POP_OPTION.equals("POP_SUCCESS")) { + System.out.println("Generating Legal POP Data....."); + signer.update(toBeVerified); + } else if (POP_OPTION.equals("POP_FAIL")) { + System.out.println("Generating Illegal POP Data....."); + signer.update(iv); + } else if (dont_do_pop == 1) { + System.out.println("Generating NO POP Data....."); + } + + System.out.println("."); //signer updated"); + + CertReqMsg crmfMsg = null; + + if (dont_do_pop == 0) { + signature = signer.sign(); + + System.out.println("Signature completed..."); + System.out.println(""); + + AlgorithmIdentifier algID = + new AlgorithmIdentifier(SignatureAlgorithm.RSASignatureWithMD5Digest.toOID(), null); + POPOSigningKey popoKey = new POPOSigningKey(null, algID, new BIT_STRING(signature, 0)); + + ProofOfPossession pop = ProofOfPossession.createSignature(popoKey); + + crmfMsg = new CertReqMsg(certReq, pop, null); + + } else { + crmfMsg = new CertReqMsg(certReq, null, null); + + } + + //crmfMsg.verify(); + + SEQUENCE s1 = new SEQUENCE(); + s1.addElement(crmfMsg); + byte encoded[] = ASN1Util.encode(s1); + + String Req1 = Utils.base64encode(encoded); + + if (OUTPUT_CERT_REQ != null) { + System.out.println("Generated Cert Request: ...... "); + System.out.println(""); + + System.out.println(Req1); + System.out.println(""); + System.out.println("End Request:"); + + if (doServerHit == 0) + return; + } + + String Req = URLEncoder.encode(Req1, "UTF-8"); + + // post PKCS10 + + url = + new URL("http://" + + HOST + ":" + PORT + "/ca/ee/ca/profileSubmit?cert_request_type=crmf&cert_request=" + + Req + "&renewal=false&uid=" + USER_NAME + "&xmlOutput=false&&profileId=" + + profileName + "&sn_uid=" + USER_NAME + "&SubId=profile&requestor_name=" + + REQUESTOR_NAME); + //System.out.println("Posting " + url); + + System.out.println(""); + System.out.println("Server Response....."); + System.out.println("--------------------"); + System.out.println(""); + + conn = url.openConnection(); + is = conn.getInputStream(); + reader = new BufferedReader(new InputStreamReader(is)); + String line = null; + while ((line = reader.readLine()) != null) { + System.out.println(line); + if (line.equals("CMS Enroll Request Success")) { + System.out.println("Enrollment Successful: ......"); + System.out.println(""); + } + } /* while */ + + } catch (Exception e) { + System.out.println("WARNING: " + e.toString()); + e.printStackTrace(); + } + } catch (Exception e) { + System.out.println("ERROR: " + e.toString()); + e.printStackTrace(); + } + } + + static Name getJssName(String dn) { + + X500Name x5Name = null; + + try { + x5Name = new X500Name(dn); + + } catch (IOException e) { + + System.out.println("Illegal Subject Name: " + dn + " Error: " + e.toString()); + System.out.println("Filling in default Subject Name......"); + return null; + } + + Name ret = new Name(); + + netscape.security.x509.RDN[] names = null; + + names = x5Name.getNames(); + + int nameLen = x5Name.getNamesLength(); + + // System.out.println("x5Name len: " + nameLen); + + netscape.security.x509.RDN cur = null; + + for (int i = 0; i < nameLen; i++) { + cur = names[i]; + + String rdnStr = cur.toString(); + + String[] split = rdnStr.split("="); + + if (split.length != 2) + continue; + + try { + + if (split[0].equals("UID")) { + + ret.addElement(new AVA(new OBJECT_IDENTIFIER("0.9.2342.19200300.100.1.1"), new PrintableString( + split[1]))); + // System.out.println("UID found : " + split[1]); + + } + + if (split[0].equals("C")) { + ret.addCountryName(split[1]); + // System.out.println("C found : " + split[1]); + continue; + + } + + if (split[0].equals("CN")) { + ret.addCommonName(split[1]); + // System.out.println("CN found : " + split[1]); + continue; + } + + if (split[0].equals("L")) { + ret.addLocalityName(split[1]); + // System.out.println("L found : " + split[1]); + continue; + } + + if (split[0].equals("O")) { + ret.addOrganizationName(split[1]); + // System.out.println("O found : " + split[1]); + continue; + } + + if (split[0].equals("ST")) { + ret.addStateOrProvinceName(split[1]); + // System.out.println("ST found : " + split[1]); + continue; + } + + if (split[0].equals("OU")) { + ret.addOrganizationalUnitName(split[1]); + // System.out.println("OU found : " + split[1]); + continue; + } + } catch (Exception e) { + System.out.println("Error constructing RDN: " + rdnStr + " Error: " + e.toString()); + + continue; + } + + } + + return ret; + + } +} -- cgit