📄 certtools.java
字号:
/************************************************************************* * * * EJBCA: The OpenSource Certificate Authority * * * * This software is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or any later version. * * * * See terms of license at gnu.org. * * * *************************************************************************/ package se.anatom.ejbca.util;import java.io.BufferedReader;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintStream;import java.net.URL;import java.security.InvalidKeyException;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.security.NoSuchProviderException;import java.security.PrivateKey;import java.security.PublicKey;import java.security.SecureRandom;import java.security.Security;import java.security.SignatureException;import java.security.cert.CRLException;import java.security.cert.CertificateEncodingException;import java.security.cert.CertificateException;import java.security.cert.CertificateFactory;import java.security.cert.CertificateParsingException;import java.security.cert.X509CRL;import java.security.cert.X509Certificate;import java.util.ArrayList;import java.util.Collection;import java.util.Date;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Vector;import org.apache.commons.lang.StringUtils;import org.apache.log4j.Logger;import org.bouncycastle.asn1.ASN1InputStream;import org.bouncycastle.asn1.ASN1OctetString;import org.bouncycastle.asn1.ASN1Sequence;import org.bouncycastle.asn1.ASN1TaggedObject;import org.bouncycastle.asn1.DERObject;import org.bouncycastle.asn1.DERObjectIdentifier;import org.bouncycastle.asn1.DEROctetString;import org.bouncycastle.asn1.DERSequence;import org.bouncycastle.asn1.DERTaggedObject;import org.bouncycastle.asn1.DERUTF8String;import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;import org.bouncycastle.asn1.x509.BasicConstraints;import org.bouncycastle.asn1.x509.PolicyInformation;import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;import org.bouncycastle.asn1.x509.X509Extensions;import org.bouncycastle.asn1.x509.X509Name;import org.bouncycastle.asn1.x509.X509NameTokenizer;import org.bouncycastle.jce.X509KeyUsage;import org.bouncycastle.jce.provider.BouncyCastleProvider;import org.bouncycastle.x509.X509V3CertificateGenerator;/** * Tools to handle common certificate operations. * * @version $Id: CertTools.java,v 1.76.2.4 2005/11/17 20:42:01 herrvendil Exp $ */public class CertTools { private static Logger log = Logger.getLogger(CertTools.class); public static final String EMAIL = "rfc822name"; public static final String EMAIL1 = "email"; public static final String EMAIL2 = "EmailAddress"; public static final String EMAIL3 = "E"; public static final String DNS = "dNSName"; public static final String URI = "uniformResourceIdentifier"; public static final String URI1 = "uri"; public static final String IPADDR = "iPAddress"; /** Microsoft altName for windows smart card logon */ public static final String UPN = "upn"; /** ObjectID for upn altName for windows smart card logon */ public static final String UPN_OBJECTID = "1.3.6.1.4.1.311.20.2.3"; /** Microsoft altName for windows domain controller guid */ public static final String GUID = "guid"; /** ObjectID for upn altName for windows domain controller guid */ public static final String GUID_OBJECTID = "1.3.6.1.4.1.311.25.1"; private static final String[] EMAILIDS = { EMAIL, EMAIL1, EMAIL2, EMAIL3 }; /** ObjectID for unstructuredName DN attribute */ //public static final DERObjectIdentifier unstructuredName = new DERObjectIdentifier("1.2.840.113549.1.9.2"); /** ObjectID for unstructuredAddress DN attribute */ //public static final DERObjectIdentifier unstructuredAddress = new DERObjectIdentifier("1.2.840.113549.1.9.8"); /** * inhibits creation of new CertTools */ private CertTools() { } /** BC X509Name contains some lookup tables that could maybe be used here. */ private static final HashMap oids = new HashMap(); static { oids.put("c", X509Name.C); oids.put("dc", X509Name.DC); oids.put("st", X509Name.ST); oids.put("l", X509Name.L); oids.put("o", X509Name.O); oids.put("ou", X509Name.OU); oids.put("t", X509Name.T); oids.put("surname", X509Name.SURNAME); oids.put("initials", X509Name.INITIALS); oids.put("givenname", X509Name.GIVENNAME); oids.put("gn", X509Name.GIVENNAME); oids.put("sn", X509Name.SN); oids.put("serialnumber", X509Name.SN); oids.put("cn", X509Name.CN); oids.put("uid", X509Name.UID); oids.put("emailaddress", X509Name.EmailAddress); oids.put("e", X509Name.EmailAddress); oids.put("email", X509Name.EmailAddress); oids.put("unstructuredname", X509Name.UnstructuredName); //unstructuredName oids.put("unstructuredaddress", X509Name.UnstructuredAddress); //unstructuredAddress } private static final String[] dNObjectsForward = { "unstructuredaddress", "unstructuredname", "emailaddress", "e", "email", "uid", "cn", "sn", "serialnumber", "gn", "givenname", "initials", "surname", "t", "ou", "o", "l", "st", "dc", "c" }; /* private static final String[] dNObjectsReverse = { "c", "dc", "st", "l", "o", "ou", "t", "surname", "initials", "givenname", "gn", "serialnumber", "sn", "cn", "uid", "email", "e", "emailaddress", "unstructuredname", "unstructuredaddress" }; */ /** Uncomment above and change this if you want reverse order */ private static final String[] dNObjects = dNObjectsForward; private static DERObjectIdentifier getOid(String o) { return (DERObjectIdentifier) oids.get(o.toLowerCase()); } // getOid /** * Creates a (Bouncycastle) X509Name object from a string with a DN. Known OID (with order) * are: <code> EmailAddress, UID, CN, SN (SerialNumber), GivenName, Initials, SurName, T, OU, * O, L, ST, DC, C </code> * To change order edit 'dnObjects' in this source file. * Important NOT to mess with the ordering within this class, since cert vierification * on some clients (IE :-() might depend on order. * * @param dn String containing DN that will be transformed into X509Name, The DN string has the * format "CN=zz,OU=yy,O=foo,C=SE". Unknown OIDs in the string will be silently * dropped. * * @return X509Name or null if input is null */ public static X509Name stringToBcX509Name(String dn) { //log.debug(">stringToBcX509Name: " + dn); if (dn == null) return null; // first make two vectors, one with all the C, O, OU etc specifying // the order and one holding the actual values ArrayList oldordering = new ArrayList(); ArrayList oldvalues = new ArrayList(); X509NameTokenizer xt = new X509NameTokenizer(dn); while (xt.hasMoreTokens()) { // This is a pair (CN=xx) String pair = xt.nextToken(); int ix = pair.indexOf("="); if (ix != -1) { // make lower case so we can easily compare later oldordering.add(pair.substring(0, ix).toLowerCase()); oldvalues.add(pair.substring(ix + 1)); } else { // Huh, what's this? } } // Now in the specified order, move from oldordering to newordering, // reshuffling as we go along Vector ordering = new Vector(); Vector values = new Vector(); int index = -1; for (int i = 0; i < dNObjects.length; i++) { //log.debug("Looking for "+dNObjects[i]); String object = dNObjects[i]; while ((index = oldordering.indexOf(object)) != -1) { //log.debug("Found 1 "+object+" at index " + index); DERObjectIdentifier oid = getOid(object); if (oid != null) { //log.debug("Added "+object+", "+oldvalues.elementAt(index)); ordering.add(oid); // remove from the old vectors, so we start clean the next round values.add(oldvalues.remove(index)); oldordering.remove(index); index = -1; } } } /* if (log.isDebugEnabled()) { Iterator i1 = ordering.iterator(); Iterator i2 = values.iterator(); log.debug("Order: "); while (i1.hasNext()) { log.debug(((DERObjectIdentifier)i1.next()).getId()); } log.debug("Values: "); while (i2.hasNext()) { log.debug((String)i2.next()); } } */ //log.debug("<stringToBcX509Name"); return new X509Name(ordering, values); } // stringToBcX509Name /** * Every DN-string should look the same. Creates a name string ordered and looking like we want * it... * * @param dn String containing DN * * @return String containing DN */ public static String stringToBCDNString(String dn) { //log.debug(">stringToBcDNString: "+dn); if (isDNReversed(dn)) { dn = reverseDN(dn); } String ret = stringToBcX509Name(dn).toString(); //log.debug("<stringToBcDNString: "+ret); return ret; } /** * Search for e-mail address, first in SubjectAltName (as in PKIX * recomandation) then in subject DN. * Marco Ferrante, (c) 2005 CSITA - University of Genoa (Italy) * * @param certificate * @return subject email or null if not present in certificate * @throws java.lang.Exception */ public static String getEMailAddress(X509Certificate certificate) throws Exception { log.debug("Searching for EMail Address in SubjectAltName"); if (certificate.getSubjectAlternativeNames() != null) { java.util.Collection altNames = certificate.getSubjectAlternativeNames(); Iterator iter = altNames.iterator(); while (iter.hasNext()) { java.util.List item = (java.util.List)iter.next(); Integer type = (Integer)item.get(0); if (type.intValue() == 1) { return (String)item.get(1); } } } log.debug("Searching for EMail Address in Subject DN"); return CertTools.getEmailFromDN(certificate.getSubjectDN().getName()); } /** * Convenience method for getting an email address from a DN. Uses {@link * getPartFromDN(String,String)} internally, and searches for {@link EMAIL}, {@link EMAIL1}, * {@link EMAIL2}, {@link EMAIL3} and returns the first one found. * * @param dn the DN * * @return the found email address, or <code>null</code> if none is found */ public static String getEmailFromDN(String dn) { log.debug(">getEmailFromDN(" + dn + ")"); String email = null; for (int i = 0; (i < EMAILIDS.length) && (email == null); i++) { email = getPartFromDN(dn, EMAILIDS[i]); } log.debug("<getEmailFromDN(" + dn + "): " + email); return email; } /** * Takes a DN and reverses it completely so the first attribute ends up last. * C=SE,O=Foo,CN=Bar becomes CN=Bar,O=Foo,C=SE. * * @param dn String containing DN to be reversed, The DN string has the format "C=SE, O=xx, OU=yy, CN=zz". * * @return String containing reversed DN */ public static String reverseDN(String dn) { log.debug(">reverseDN: dn: " + dn); String ret = null; if (dn != null) { String o; BasicX509NameTokenizer xt = new BasicX509NameTokenizer(dn); StringBuffer buf = new StringBuffer(); boolean first = true; while (xt.hasMoreTokens()) { o = xt.nextToken(); //log.debug("token: "+o); if (!first) { buf.insert(0,","); } else { first = false; } buf.insert(0,o); } if (buf.length() > 0) { ret = buf.toString(); } } log.debug("<reverseDN: resulting DN=" + ret); return ret; } //reverseDN /**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -