PolicyInformation pi = new PolicyInformation(new DERObjectIdentifier(certProfile.getCertificatePolicyId()));
PolicyInformation pi = getPolicyInformation(certProfile.getCertificatePolicyId(), certProfile.getCpsUrl(), certProfile.getUserNoticeText());
    public Certificate generateCertificate(UserDataVO subject,                                            PublicKey publicKey,                                            int keyusage,                                            long validity,                                           CertificateProfile certProfile) throws Exception{                                                   	    	        final String sigAlg = getCAToken().getCATokenInfo().getSignatureAlgorithm();        Date firstDate = new Date();        // Set back startdate ten minutes to avoid some problems with wrongly set clocks.        firstDate.setTime(firstDate.getTime() - 10 * 60 * 1000);        Date lastDate = new Date();        // validity in days = validity*24*60*60*1000 milliseconds        long val = validity;        if(val == -1)          val = certProfile.getValidity();                lastDate.setTime(lastDate.getTime() + ( val * 24 * 60 * 60 * 1000));        ExtendedX509V3CertificateGenerator certgen = new ExtendedX509V3CertificateGenerator();        // Serialnumber is random bits, where random generator is initialized by the        // serno generator.        BigInteger serno = SernoGenerator.instance().getSerno();        certgen.setSerialNumber(serno);        certgen.setNotBefore(firstDate);        certgen.setNotAfter(lastDate);        certgen.setSignatureAlgorithm(sigAlg);        // Make DNs        String dn = subject.getDN();                 if(certProfile.getUseSubjectDNSubSet()){          dn= certProfile.createSubjectDNSubSet(dn);	        }                if(certProfile.getUseCNPostfix()){          dn = CertTools.insertCNPostfix(dn,certProfile.getCNPostfix());	        }                        String altName = subject.getSubjectAltName();               if(certProfile.getUseSubjectAltNameSubSet()){        	altName = certProfile.createSubjectAltNameSubSet(altName);        }                certgen.setSubjectDN(CertTools.stringToBcX509Name(dn));        // We must take the issuer DN directly from the CA-certificate otherwise we risk re-ordering the DN        // which many applications do not like.        X509Certificate cacert = (X509Certificate)getCACertificate();        if (cacert == null) {        	// This will be an initial root CA, since no CA-certificate exists            X509Name caname = CertTools.stringToBcX509Name(getSubjectDN());            certgen.setIssuerDN(caname);        } else {            certgen.setIssuerDN(cacert.getSubjectX500Principal());        	        }        certgen.setPublicKey(publicKey);        // Basic constranits, all subcerts are NOT CAs        if (certProfile.getUseBasicConstraints() == true) {        	BasicConstraints bc = new BasicConstraints(false);            if ((certProfile.getType() == CertificateProfile.TYPE_SUBCA)                || (certProfile.getType() == CertificateProfile.TYPE_ROOTCA)){            	            	if(certProfile.getUsePathLengthConstraint()){            		bc = new BasicConstraints(certProfile.getPathLengthConstraint());            	}else{            		bc =  new BasicConstraints(true);            	}            	            }                                        certgen.addExtension(                X509Extensions.BasicConstraints.getId(),                certProfile.getBasicConstraintsCritical(),                bc);        }        // Key usage        int newKeyUsage = -1;        if (certProfile.getAllowKeyUsageOverride() && (keyusage >= 0)) {            newKeyUsage = keyusage;        } else {            newKeyUsage = CertTools.sunKeyUsageToBC(certProfile.getKeyUsage());        }        if ( (certProfile.getUseKeyUsage() == true) && (newKeyUsage >=0) ){            X509KeyUsage ku = new X509KeyUsage(newKeyUsage);            certgen.addExtension(                X509Extensions.KeyUsage.getId(),                certProfile.getKeyUsageCritical(),                ku);        }        // Extended Key usage        if (certProfile.getUseExtendedKeyUsage() == true) {            // Get extended key usage from certificate profile            Collection c = certProfile.getExtendedKeyUsageAsOIDStrings();            Vector usage = new Vector();            Iterator iter = c.iterator();            while (iter.hasNext()) {                usage.add(new DERObjectIdentifier((String)iter.next()));            }            ExtendedKeyUsage eku = new ExtendedKeyUsage(usage);            // Extended Key Usage may be either critical or non-critical            certgen.addExtension(                X509Extensions.ExtendedKeyUsage.getId(),                certProfile.getExtendedKeyUsageCritical(),                eku);        }        // Subject key identifier        if (certProfile.getUseSubjectKeyIdentifier() == true) {            SubjectPublicKeyInfo spki =                new SubjectPublicKeyInfo(                    (ASN1Sequence) new ASN1InputStream(new ByteArrayInputStream(publicKey.getEncoded())).readObject());            SubjectKeyIdentifier ski = new SubjectKeyIdentifier(spki);            certgen.addExtension(                X509Extensions.SubjectKeyIdentifier.getId(),                certProfile.getSubjectKeyIdentifierCritical(), ski);        }        // Authority key identifier        if (certProfile.getUseAuthorityKeyIdentifier() == true) {            SubjectPublicKeyInfo apki = null;            try{              apki =                new SubjectPublicKeyInfo(                    (ASN1Sequence) new ASN1InputStream(new ByteArrayInputStream(getCAToken().getPublicKey(SecConst.CAKEYPURPOSE_CERTSIGN).getEncoded())).readObject());             }catch(CATokenOfflineException e){                 log.debug("X509CA: CA Token Offline Exception: ", e);                                 throw e;             }            AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki);            certgen.addExtension(                X509Extensions.AuthorityKeyIdentifier.getId(),                certProfile.getAuthorityKeyIdentifierCritical(), aki);        }         // Subject Alternative name        if ( (certProfile.getUseSubjectAlternativeName() == true) && (altName != null) && (altName.length() > 0) ) {            GeneralNames san = CertTools.getGeneralNamesFromAltName(altName);                        if (san != null) {                certgen.addExtension(X509Extensions.SubjectAlternativeName.getId(), certProfile.getSubjectAlternativeNameCritical(), san);            }        }                // Certificate Policies         if (certProfile.getUseCertificatePolicies() == true) {                 PolicyInformation pi = new PolicyInformation(new DERObjectIdentifier(certProfile.getCertificatePolicyId()));                 DERSequence seq = new DERSequence(pi);                 certgen.addExtension(X509Extensions.CertificatePolicies.getId(),                         certProfile.getCertificatePoliciesCritical(), seq);         }         // CRL Distribution point URI         if (certProfile.getUseCRLDistributionPoint() == true) {        	 String crldistpoint = certProfile.getCRLDistributionPointURI();        	 if(certProfile.getUseDefaultCRLDistributionPoint()){        		 crldistpoint = getDefaultCRLDistPoint();        	 }             // Multiple CDPs are spearated with the ';' sign        	         	             StringTokenizer tokenizer = new StringTokenizer(crldistpoint, ";", false);            ArrayList distpoints = new ArrayList();            while (tokenizer.hasMoreTokens()) {                // 6 is URI                String uri = tokenizer.nextToken();                GeneralName gn = new GeneralName(6, new DERIA5String(uri));                log.debug("Added CRL distpoint: "+uri);                ASN1EncodableVector vec = new ASN1EncodableVector();                vec.add(gn);                GeneralNames gns = new GeneralNames(new DERSequence(vec));                DistributionPointName dpn = new DistributionPointName(0, gns);                distpoints.add(new DistributionPoint(dpn, null, null));            }            if (distpoints.size() > 0) {                CRLDistPoint ext = new CRLDistPoint((DistributionPoint[])distpoints.toArray(new DistributionPoint[0]));                certgen.addExtension(X509Extensions.CRLDistributionPoints.getId(),                    certProfile.getCRLDistributionPointCritical(), ext);            }         }         // Authority Information Access (OCSP url)         if (certProfile.getUseOCSPServiceLocator() == true) {             String ocspUrl = certProfile.getOCSPServiceLocatorURI();             if(certProfile.getUseDefaultOCSPServiceLocator()){            	 ocspUrl = getDefaultOCSPServiceLocator();             }             // OCSP access location is a URL (GeneralName no 6)             GeneralName ocspLocation = new GeneralName(6, new DERIA5String(ocspUrl));             certgen.addExtension(X509Extensions.AuthorityInfoAccess.getId(),                 false, new AuthorityInformationAccess(X509ObjectIdentifiers.ocspAccessMethod, ocspLocation));         }                  // Microsoft Template         if (certProfile.getUseMicrosoftTemplate() == true) {             String mstemplate = certProfile.getMicrosoftTemplate();                          DERObjectIdentifier oid = new DERObjectIdentifier(CertTools.OID_MSTEMPLATE);                                        certgen.addExtension(oid, false, new DERIA5String(mstemplate));                      }                  // QCStatement (rfc3739)         if (certProfile.getUseQCStatement() == true) {             String names = certProfile.getQCStatementRAName();             GeneralNames san = CertTools.getGeneralNamesFromAltName(names);             SemanticsInformation si = null;             if (san != null) {                 if (StringUtils.isNotEmpty(certProfile.getQCSemanticsId())) {                     si = new SemanticsInformation(new DERObjectIdentifier(certProfile.getQCSemanticsId()), san.getNames());                 } else {                     si = new SemanticsInformation(san.getNames());                                      }             } else if (StringUtils.isNotEmpty(certProfile.getQCSemanticsId())) {                 si = new SemanticsInformation(new DERObjectIdentifier(certProfile.getQCSemanticsId()));                              }             ArrayList qcs = new ArrayList();             QCStatement qc = null;             // First the standard rfc3739 QCStatement with an optional SematicsInformation             DERObjectIdentifier pkixQcSyntax = RFC3739QCObjectIdentifiers.id_qcs_pkixQCSyntax_v1;             if (certProfile.getUsePkixQCSyntaxV2()) {            	 pkixQcSyntax = RFC3739QCObjectIdentifiers.id_qcs_pkixQCSyntax_v2;             }             if ( (si != null)  ) {                 qc = new QCStatement(pkixQcSyntax, si);                 qcs.add(qc);             } else {            	 qc = new QCStatement(pkixQcSyntax);                 qcs.add(qc);             }             // ETSI Statement that the certificate is a Qualified Certificate             if (certProfile.getUseQCEtsiQCCompliance()) {            	 qc = new QCStatement(ETSIQCObjectIdentifiers.id_etsi_qcs_QcCompliance);                 qcs.add(qc);             }             // ETSI Statement regarding limit on the value of transactions             if (certProfile.getUseQCEtsiValueLimit()) {            	 // Both value and currency must be availabel for this extension            	 if ( (certProfile.getQCEtsiValueLimit() > 0) && (certProfile.getQCEtsiValueLimitCurrency() != null) ) {            		 int limit = certProfile.getQCEtsiValueLimit();            		 // The exponent should be default 0            		 int exponent = certProfile.getQCEtsiValueLimitExp();            		 MonetaryValue value = new MonetaryValue(new Iso4217CurrencyCode(certProfile.getQCEtsiValueLimitCurrency()), limit, exponent);            		 qc = new QCStatement(ETSIQCObjectIdentifiers.id_etsi_qcs_LimiteValue, value);            		 qcs.add(qc);            	 }             }             // ETSI Statement claiming that the private key resides in a Signature Creation Device             if (certProfile.getUseQCEtsiSignatureDevice()) {            	 qc = new QCStatement(ETSIQCObjectIdentifiers.id_etsi_qcs_QcSSCD);                 qcs.add(qc);             }             if (qcs.size() >  0) {                 DEREncodableVector vec = new DEREncodableVector();                 Iterator iter = qcs.iterator();                 while (iter.hasNext()) {                	 QCStatement q = (QCStatement)iter.next();                     vec.add(q);                 }                 certgen.addExtension(CertTools.QCSTATEMENTS_OBJECTID, certProfile.getQCStatementCritical(), new DERSequence(vec));                              }         }		                   X509Certificate cert;         try{           cert = certgen.generateX509Certificate(getCAToken().getPrivateKey(SecConst.CAKEYPURPOSE_CERTSIGN),                                             getCAToken().getProvider());         }catch(CATokenOfflineException e){             log.debug("X509CA : CA Token STATUS OFFLINE: ", e);             throw e;          }                // Verify before returning        cert.verify(getCAToken().getPublicKey(SecConst.CAKEYPURPOSE_CERTSIGN));        log.debug(">X509CA: generate certificate, CA "+ this.getCAId() + " for DN=" + subject.getDN());                  return cert;                                                                                            }