Example usage for org.bouncycastle.asn1 DERBitString DERBitString

List of usage examples for org.bouncycastle.asn1 DERBitString DERBitString

Introduction

In this page you can find the example usage for org.bouncycastle.asn1 DERBitString DERBitString.

Prototype

public DERBitString(byte[] data, int padBits) 

Source Link

Usage

From source file:net.ripe.rpki.commons.crypto.util.Asn1Util.java

License:BSD License

public static DERBitString resourceToBitString(UniqueIpResource resource, int bitCount) {
    int resourceTypeByteSize = resource.getType().getBitSize() / Byte.SIZE;

    byte[] value = resource.getValue().toByteArray();
    byte[] padded;
    if (value.length > resourceTypeByteSize) {
        // Skip extra sign byte added by BigInteger.
        padded = Arrays.copyOfRange(value, 1, value.length);
    } else if (value.length < resourceTypeByteSize) {
        // Pad with leading zero bytes (e.g. 0.12.0.0)
        padded = new byte[resourceTypeByteSize];
        System.arraycopy(value, 0, padded, resourceTypeByteSize - value.length, value.length);
    } else {//w  w w  .ja va2 s .  c o  m
        padded = value;
    }

    assert padded.length == resourceTypeByteSize : "incorrect padded length";

    int byteCount = (bitCount + Byte.SIZE - 1) / Byte.SIZE;
    int unusedBits = Byte.SIZE - 1 - ((bitCount + Byte.SIZE - 1) % Byte.SIZE);
    return new DERBitString(ArrayUtils.subarray(padded, 0, byteCount), unusedBits);
}

From source file:net.sourceforge.javacardsign.iso7816_15.AlgorithmInfo.java

License:Open Source License

public DERSequence getDERObject() {
    DERInteger reference = new DERInteger(this.reference);
    DERInteger internalIdentifier = new DERInteger(this.internalIdentifier);
    DERBitString operations = new DERBitString(CommonObjectAttributes.encodeBits(this.operations),
            CommonObjectAttributes.getPad(this.operations));
    DERObjectIdentifier objectId = new DERObjectIdentifier(this.objectId);
    DERInteger algId = new DERInteger(this.algId);
    return new DERSequence(
            new ASN1Encodable[] { reference, internalIdentifier, new DERNull(), operations, objectId, algId });
}

From source file:net.sourceforge.javacardsign.iso7816_15.CommonKeyAttributes.java

License:Open Source License

public DERObject getDERObject() {
    DERBitString usage = new DERBitString(CommonObjectAttributes.encodeBits(this.usage),
            CommonObjectAttributes.getPad(this.usage));
    DEROctetString id = new DEROctetString(this.id);
    return new DERSequence(new ASN1Encodable[] { id, usage });
}

From source file:net.sourceforge.javacardsign.iso7816_15.CommonObjectAttributes.java

License:Open Source License

public DERObject getDERObject() {
    DERUTF8String label = new DERUTF8String(this.label);
    DERBitString flags = new DERBitString(encodeBits(this.flags), getPad(this.flags));
    if (authId != -1) {
        DEROctetString authId = new DEROctetString(new byte[] { this.authId });
        return new DERSequence(new ASN1Encodable[] { label, flags, authId });
    } else {/*  w  w  w .ja v  a 2  s .c  o m*/
        return new DERSequence(new ASN1Encodable[] { label, flags });
    }
}

From source file:net.sourceforge.javacardsign.iso7816_15.ElementaryFileCIAInfo.java

License:Open Source License

public DERObject getDERObject() {
    DERInteger version = new DERInteger(this.version);
    DERUTF8String manufacturerId = new DERUTF8String(this.manufacturerId);
    DERBitString cardFlags = new DERBitString(CommonObjectAttributes.encodeBits(this.cardFlags),
            CommonObjectAttributes.getPad(this.cardFlags));
    ASN1Encodable[] algs = new ASN1Encodable[algorithmInfos.length];
    for (int i = 0; i < algs.length; i++) {
        algs[i] = this.algorithmInfos[i].getDERObject();
    }//w  w w  . jav a 2  s .  c  om
    DERSequence algorithmInfos = new DERSequence(algs);
    return new DERSequence(new ASN1Encodable[] { version, manufacturerId, cardFlags, new DERSequence(),
            new DERSequence(algorithmInfos) });
}

From source file:net.sourceforge.javacardsign.iso7816_15.PasswordAttributes.java

License:Open Source License

public DERObject getDERObject() {
    DERBitString flags = new DERBitString(CommonObjectAttributes.encodeBits(this.flags),
            CommonObjectAttributes.getPad(this.flags));
    DEREnumerated type = new DEREnumerated(this.type);
    DERInteger minLength = new DERInteger(this.minLength);
    DERInteger storedLength = new DERInteger(this.storedLength);
    return new DERSequence(new ASN1Encodable[] { flags, type, minLength, storedLength });
}

From source file:org.cagrid.gaards.pki.BouncyCastleCertProcessingFactory.java

License:Open Source License

/**
 * Creates a proxy certificate. A set of X.509 extensions can be optionally
 * included in the new proxy certificate. <BR>
 * If a GSI-2 proxy is created, the serial number of the proxy certificate
 * will be the same as of the issuing certificate. Also, none of the
 * extensions in the issuing certificate will be copied into the proxy
 * certificate.<BR>/* w w w.  j a  v  a2s.co m*/
 * If a GSI-3 proxy is created, the serial number of the proxy certificate
 * will be picked randomly. If the issuing certificate contains a
 * <i>KeyUsage</i> extension, the extension will be copied into the proxy
 * certificate with <i>keyCertSign</i> and <i>nonRepudiation</i> bits
 * turned off. No other extensions are currently copied.
 * 
 * @param issuerCert
 *            the issuing certificate
 * @param issuerKey
 *            private key matching the public key of issuer certificate. The
 *            new proxy certificate will be signed by that key.
 * @param publicKey
 *            the public key of the new certificate
 * @param lifetime
 *            lifetime of the new certificate in seconds. If 0 (or less
 *            then) the new certificate will have the same lifetime as the
 *            issuing certificate.
 * @param proxyType
 *            can be one of {@link GSIConstants#DELEGATION_LIMITED
 *            GSIConstants.DELEGATION_LIMITED},
 *            {@link GSIConstants#DELEGATION_FULL
 *            GSIConstants.DELEGATION_FULL},
 *            {@link GSIConstants#GSI_2_LIMITED_PROXY
 *            GSIConstants.GSI_2_LIMITED_PROXY},
 *            {@link GSIConstants#GSI_2_PROXY GSIConstants.GSI_2_PROXY},
 *            {@link GSIConstants#GSI_3_IMPERSONATION_PROXY
 *            GSIConstants.GSI_3_IMPERSONATION_PROXY},
 *            {@link GSIConstants#GSI_3_LIMITED_PROXY
 *            GSIConstants.GSI_3_LIMITED_PROXY},
 *            {@link GSIConstants#GSI_3_INDEPENDENT_PROXY
 *            GSIConstants.GSI_3_INDEPENDENT_PROXY},
 *            {@link GSIConstants#GSI_3_RESTRICTED_PROXY
 *            GSIConstants.GSI_3_RESTRICTED_PROXY}. If
 *            {@link GSIConstants#DELEGATION_LIMITED
 *            GSIConstants.DELEGATION_LIMITED} and if
 *            {@link CertUtil#isGsi3Enabled() CertUtil.isGsi3Enabled}
 *            returns true then a GSI-3 limited proxy will be created. If
 *            not, a GSI-2 limited proxy will be created. If
 *            {@link GSIConstants#DELEGATION_FULL
 *            GSIConstants.DELEGATION_FULL} and if
 *            {@link CertUtil#isGsi3Enabled() CertUtil.isGsi3Enabled}
 *            returns true then a GSI-3 impersonation proxy will be created.
 *            If not, a GSI-2 full proxy will be created.
 * @param extSet
 *            a set of X.509 extensions to be included in the new proxy
 *            certificate. Can be null. If delegation mode is
 *            {@link GSIConstants#GSI_3_RESTRICTED_PROXY
 *            GSIConstants.GSI_3_RESTRICTED_PROXY} then
 *            {@link org.globus.gsi.proxy.ext.ProxyCertInfoExtension 
 *            ProxyCertInfoExtension} must be present in the extension set.
 * @param cnValue
 *            the value of the CN component of the subject of the new
 *            certificate. If null, the defaults will be used depending on
 *            the proxy certificate type created.
 * @return <code>X509Certificate</code> the new proxy certificate.
 * @exception GeneralSecurityException
 *                if a security error occurs.
 */
public X509Certificate createProxyCertificate(String provider, X509Certificate issuerCert, PrivateKey issuerKey,
        PublicKey publicKey, int lifetime, int proxyType, X509ExtensionSet extSet, String cnValue,
        String signatureAlgorithm) throws GeneralSecurityException {

    if (proxyType == GSIConstants.DELEGATION_LIMITED) {
        int type = BouncyCastleUtil.getCertificateType(issuerCert);
        if (CertUtil.isGsi4Proxy(type)) {
            proxyType = GSIConstants.GSI_4_LIMITED_PROXY;
        } else if (CertUtil.isGsi3Proxy(type)) {
            proxyType = GSIConstants.GSI_3_LIMITED_PROXY;
        } else if (CertUtil.isGsi2Proxy(type)) {
            proxyType = GSIConstants.GSI_2_LIMITED_PROXY;
        } else {
            // default to Globus OID
            proxyType = (CertUtil.isGsi3Enabled()) ? GSIConstants.GSI_3_LIMITED_PROXY
                    : GSIConstants.GSI_2_LIMITED_PROXY;
        }
    } else if (proxyType == GSIConstants.DELEGATION_FULL) {
        int type = BouncyCastleUtil.getCertificateType(issuerCert);
        if (CertUtil.isGsi4Proxy(type)) {
            proxyType = GSIConstants.GSI_4_IMPERSONATION_PROXY;
        } else if (CertUtil.isGsi3Proxy(type)) {
            proxyType = GSIConstants.GSI_3_IMPERSONATION_PROXY;
        } else if (CertUtil.isGsi2Proxy(type)) {
            proxyType = GSIConstants.GSI_2_PROXY;
        } else {
            // Default to Globus OID
            proxyType = (CertUtil.isGsi3Enabled()) ? GSIConstants.GSI_3_IMPERSONATION_PROXY
                    : GSIConstants.GSI_2_PROXY;
        }
    }

    X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();

    org.globus.gsi.X509Extension x509Ext = null;
    BigInteger serialNum = null;
    String delegDN = null;

    if (CertUtil.isGsi3Proxy(proxyType) || CertUtil.isGsi4Proxy(proxyType)) {
        Random rand = new Random();
        delegDN = String.valueOf(Math.abs(rand.nextInt()));
        serialNum = new BigInteger(20, rand);

        if (extSet != null) {
            x509Ext = extSet.get(ProxyCertInfo.OID.getId());
            if (x509Ext == null) {
                x509Ext = extSet.get(ProxyCertInfo.OLD_OID.getId());
            }
        }

        if (x509Ext == null) {
            // create ProxyCertInfo extension
            ProxyPolicy policy = null;
            if (CertUtil.isLimitedProxy(proxyType)) {
                policy = new ProxyPolicy(ProxyPolicy.LIMITED);
            } else if (CertUtil.isIndependentProxy(proxyType)) {
                policy = new ProxyPolicy(ProxyPolicy.INDEPENDENT);
            } else if (CertUtil.isImpersonationProxy(proxyType)) {
                // since limited has already been checked, this should work.
                policy = new ProxyPolicy(ProxyPolicy.IMPERSONATION);
            } else if ((proxyType == GSIConstants.GSI_3_RESTRICTED_PROXY)
                    || (proxyType == GSIConstants.GSI_4_RESTRICTED_PROXY)) {
                throw new IllegalArgumentException("Restricted proxy requires ProxyCertInfo extension");
            } else {
                throw new IllegalArgumentException("Invalid proxyType");
            }

            ProxyCertInfo proxyCertInfo = new ProxyCertInfo(policy);
            x509Ext = new ProxyCertInfoExtension(proxyCertInfo);
            if (CertUtil.isGsi4Proxy(proxyType)) {
                // RFC compliant OID
                x509Ext = new ProxyCertInfoExtension(proxyCertInfo);
            } else {
                // old OID
                x509Ext = new GlobusProxyCertInfoExtension(proxyCertInfo);
            }
        }

        try {
            // add ProxyCertInfo extension to the new cert
            certGen.addExtension(x509Ext.getOid(), x509Ext.isCritical(), x509Ext.getValue());

            // handle KeyUsage in issuer cert
            TBSCertificateStructure crt = BouncyCastleUtil.getTBSCertificateStructure(issuerCert);

            X509Extensions extensions = crt.getExtensions();
            if (extensions != null) {
                X509Extension ext;

                // handle key usage ext
                ext = extensions.getExtension(X509Extensions.KeyUsage);
                if (ext != null) {

                    // TBD: handle this better
                    if (extSet != null && (extSet.get(X509Extensions.KeyUsage.getId()) != null)) {
                        throw new GeneralSecurityException("KeyUsage extension present in X509ExtensionSet "
                                + "and in issuer certificate.");
                    }

                    DERBitString bits = (DERBitString) BouncyCastleUtil.getExtensionObject(ext);

                    byte[] bytes = bits.getBytes();

                    // make sure they are disabled
                    if ((bytes[0] & KeyUsage.nonRepudiation) != 0) {
                        bytes[0] ^= KeyUsage.nonRepudiation;
                    }

                    if ((bytes[0] & KeyUsage.keyCertSign) != 0) {
                        bytes[0] ^= KeyUsage.keyCertSign;
                    }

                    bits = new DERBitString(bytes, bits.getPadBits());

                    certGen.addExtension(X509Extensions.KeyUsage, ext.isCritical(), bits);
                }
            }

        } catch (IOException e) {
            // but this should not happen
            throw new GeneralSecurityException(e.getMessage());
        }

    } else if (proxyType == GSIConstants.GSI_2_LIMITED_PROXY) {
        delegDN = "limited proxy";
        serialNum = issuerCert.getSerialNumber();
    } else if (proxyType == GSIConstants.GSI_2_PROXY) {
        delegDN = "proxy";
        serialNum = issuerCert.getSerialNumber();
    } else {
        throw new IllegalArgumentException("Unsupported proxyType : " + proxyType);
    }

    // add specified extensions
    if (extSet != null) {
        Iterator iter = extSet.oidSet().iterator();
        while (iter.hasNext()) {
            String oid = (String) iter.next();
            // skip ProxyCertInfo extension
            if (oid.equals(ProxyCertInfo.OID.getId()) || oid.equals(ProxyCertInfo.OLD_OID.getId())) {
                continue;
            }
            x509Ext = (org.globus.gsi.X509Extension) extSet.get(oid);
            certGen.addExtension(x509Ext.getOid(), x509Ext.isCritical(), x509Ext.getValue());
        }
    }

    X509Name issuerDN = (X509Name) issuerCert.getSubjectDN();

    X509NameHelper issuer = new X509NameHelper(issuerDN);

    X509NameHelper subject = new X509NameHelper(issuerDN);
    subject.add(X509Name.CN, (cnValue == null) ? delegDN : cnValue);

    certGen.setSubjectDN(subject.getAsName());
    certGen.setIssuerDN(issuer.getAsName());

    certGen.setSerialNumber(serialNum);
    certGen.setPublicKey(publicKey);
    certGen.setSignatureAlgorithm(signatureAlgorithm);

    GregorianCalendar date = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
    /* Allow for a five minute clock skew here. */
    date.add(Calendar.MINUTE, -5);
    certGen.setNotBefore(date.getTime());

    /* If hours = 0, then cert lifetime is set to user cert */
    if (lifetime <= 0) {
        certGen.setNotAfter(issuerCert.getNotAfter());
    } else {
        date.add(Calendar.MINUTE, 5);
        date.add(Calendar.SECOND, lifetime);
        certGen.setNotAfter(date.getTime());
    }

    /**
     * FIXME: Copy appropriate cert extensions - this should NOT be done the
     * last time we talked to Doug E. This should investigated more.
     */

    return certGen.generateX509Certificate(issuerKey, provider);
}

From source file:org.cesecore.certificates.certificate.certextensions.BasicCertificateExtension.java

License:Open Source License

private ASN1Encodable parseDERBitString(String value) throws CertificateExtensionException {
    ASN1Encodable retval = null;/*  w w  w. j  a  va  2  s  . com*/
    try {
        BigInteger bigInteger = new BigInteger(value, 2);
        int padBits = value.length() - 1 - value.lastIndexOf("1");
        if (padBits == 8) {
            padBits = 0;
        }
        byte[] byteArray = bigInteger.toByteArray();
        if (byteArray[0] == 0) {
            // Remove empty extra byte
            // System.arraycopy handles creating of temporary array when destinatio is the same
            System.arraycopy(byteArray, 1, byteArray, 0, byteArray.length - 1);
        }
        retval = new DERBitString(byteArray, padBits);
    } catch (NumberFormatException e) {
        throw new CertificateExtensionException(intres.getLocalizedMessage("certext.basic.illegalvalue", value,
                Integer.valueOf(getId()), getOID()));
    }

    return retval;
}

From source file:org.ejbca.core.model.ca.certextensions.BasicCertificateExtension.java

License:Open Source License

private DEREncodable parseDERBitString(String value) throws CertificateExtentionConfigurationException {
    DEREncodable retval = null;//w  ww . j  av a 2  s. c  o  m
    try {
        BigInteger bigInteger = new BigInteger(value, 2);
        int padBits = value.length() - 1 - value.lastIndexOf("1");
        if (padBits == 8) {
            padBits = 0;
        }
        byte[] byteArray = bigInteger.toByteArray();
        if (byteArray[0] == 0) {
            // Remove empty extra byte
            byte[] shorterByteArray = new byte[byteArray.length - 1];
            for (int i = 0; i < shorterByteArray.length; i++) {
                shorterByteArray[i] = byteArray[i + 1];
            }
            byteArray = shorterByteArray;
        }
        retval = new DERBitString(byteArray, padBits);
    } catch (NumberFormatException e) {
        throw new CertificateExtentionConfigurationException(intres
                .getLocalizedMessage("certext.basic.illegalvalue", value, Integer.valueOf(getId()), getOID()));
    }

    return retval;
}

From source file:org.globus.gsi.bc.BouncyCastleCertProcessingFactory.java

License:Apache License

/**
 * Creates a proxy certificate. A set of X.509 extensions can be optionally included in the new proxy
 * certificate. <BR>//from   w ww  .  j a  v a  2  s .c om
 * If a GSI-2 proxy is created, the serial number of the proxy certificate will be the same as of the
 * issuing certificate. Also, none of the extensions in the issuing certificate will be copied into the
 * proxy certificate.<BR>
 * If a GSI-3 or GSI 4 proxy is created, the serial number of the proxy certificate will be picked
 * randomly. If the issuing certificate contains a <i>KeyUsage</i> extension, the extension will be copied
 * into the proxy certificate with <i>keyCertSign</i> and <i>nonRepudiation</i> bits turned off. No other
 * extensions are currently copied.
 *
 * The methods defaults to creating GSI 4 proxy
 *
 * @param issuerCert_
 *            the issuing certificate
 * @param issuerKey
 *            private key matching the public key of issuer certificate. The new proxy certificate will be
 *            signed by that key.
 * @param publicKey
 *            the public key of the new certificate
 * @param lifetime
 *            lifetime of the new certificate in seconds. If 0 (or less then) the new certificate will
 *            have the same lifetime as the issuing certificate.
 * @param proxyType
 *            can be one of {@link GSIConstants#DELEGATION_LIMITED GSIConstants.DELEGATION_LIMITED},
 *            {@link GSIConstants#DELEGATION_FULL GSIConstants.DELEGATION_FULL},
 *
 *            {@link GSIConstants#GSI_2_LIMITED_PROXY GSIConstants.GSI_2_LIMITED_PROXY},
 *            {@link GSIConstants#GSI_2_PROXY GSIConstants.GSI_2_PROXY},
 *            {@link GSIConstants#GSI_3_IMPERSONATION_PROXY GSIConstants.GSI_3_IMPERSONATION_PROXY},
 *            {@link GSIConstants#GSI_3_LIMITED_PROXY GSIConstants.GSI_3_LIMITED_PROXY},
 *            {@link GSIConstants#GSI_3_INDEPENDENT_PROXY GSIConstants.GSI_3_INDEPENDENT_PROXY},
 *            {@link GSIConstants#GSI_3_RESTRICTED_PROXY GSIConstants.GSI_3_RESTRICTED_PROXY}.
 *            {@link GSIConstants#GSI_4_IMPERSONATION_PROXY GSIConstants.GSI_4_IMPERSONATION_PROXY},
 *            {@link GSIConstants#GSI_4_LIMITED_PROXY GSIConstants.GSI_3_LIMITED_PROXY},
 *            {@link GSIConstants#GSI_4_INDEPENDENT_PROXY GSIConstants.GSI_4_INDEPENDENT_PROXY},
 *            {@link GSIConstants#GSI_4_RESTRICTED_PROXY GSIConstants.GSI_4_RESTRICTED_PROXY}.
 *
 *            If {@link GSIConstants#DELEGATION_LIMITED GSIConstants.DELEGATION_LIMITED} and if
 *            {@link VersionUtil#isGsi2Enabled() CertUtil.isGsi2Enabled} returns true then a GSI-2 limited
 *            proxy will be created. Else if {@link VersionUtil#isGsi3Enabled() CertUtil.isGsi3Enabled}
 *            returns true then a GSI-3 limited proxy will be created. If not, a GSI-4 limited proxy will
 *            be created.
 *
 *            If {@link GSIConstants#DELEGATION_FULL GSIConstants.DELEGATION_FULL} and if
 *            {@link VersionUtil#isGsi2Enabled() CertUtil.isGsi2Enabled} returns true then a GSI-2 full proxy
 *            will be created. Else if {@link VersionUtil#isGsi3Enabled() CertUtil.isGsi3Enabled} returns
 *            true then a GSI-3 full proxy will be created. If not, a GSI-4 full proxy will be created.
 *
 * @param extSet
 *            a set of X.509 extensions to be included in the new proxy certificate. Can be null. If
 *            delegation mode is {@link GSIConstants#GSI_3_RESTRICTED_PROXY
 *            GSIConstants.GSI_3_RESTRICTED_PROXY} or {@link GSIConstants#GSI_4_RESTRICTED_PROXY
 *            GSIConstants.GSI_4_RESTRICTED_PROXY} then
 *            {@link org.globus.gsi.proxy.ext.ProxyCertInfoExtension ProxyCertInfoExtension} must be
 *            present in the extension set.
 *
 * @param cnValue
 *            the value of the CN component of the subject of the new certificate. If null, the defaults
 *            will be used depending on the proxy certificate type created.
 * @return <code>X509Certificate</code> the new proxy certificate.
 * @exception GeneralSecurityException
 *                if a security error occurs.
 * @deprecated
 */
public X509Certificate createProxyCertificate(X509Certificate issuerCert_, PrivateKey issuerKey,
        PublicKey publicKey, int lifetime, int proxyType, X509ExtensionSet extSet, String cnValue)
        throws GeneralSecurityException {

    X509Certificate issuerCert = issuerCert_;
    if (!(issuerCert_ instanceof X509CertificateObject)) {
        issuerCert = CertificateLoadUtil.loadCertificate(new ByteArrayInputStream(issuerCert.getEncoded()));
    }

    if (proxyType == GSIConstants.DELEGATION_LIMITED) {
        GSIConstants.CertificateType type = BouncyCastleUtil.getCertificateType(issuerCert);
        if (ProxyCertificateUtil.isGsi4Proxy(type)) {
            proxyType = GSIConstants.GSI_4_LIMITED_PROXY;
        } else if (ProxyCertificateUtil.isGsi3Proxy(type)) {
            proxyType = GSIConstants.GSI_3_LIMITED_PROXY;
        } else if (ProxyCertificateUtil.isGsi2Proxy(type)) {
            proxyType = GSIConstants.GSI_2_LIMITED_PROXY;
        } else {
            // default to RFC compliant proxy
            if (VersionUtil.isGsi2Enabled()) {
                proxyType = GSIConstants.GSI_2_LIMITED_PROXY;
            } else {
                proxyType = VersionUtil.isGsi3Enabled() ? GSIConstants.GSI_3_LIMITED_PROXY
                        : GSIConstants.GSI_4_LIMITED_PROXY;
            }
        }
    } else if (proxyType == GSIConstants.DELEGATION_FULL) {
        GSIConstants.CertificateType type = BouncyCastleUtil.getCertificateType(issuerCert);
        if (ProxyCertificateUtil.isGsi4Proxy(type)) {
            proxyType = GSIConstants.GSI_4_IMPERSONATION_PROXY;
        } else if (ProxyCertificateUtil.isGsi3Proxy(type)) {
            proxyType = GSIConstants.GSI_3_IMPERSONATION_PROXY;
        } else if (ProxyCertificateUtil.isGsi2Proxy(type)) {
            proxyType = GSIConstants.GSI_2_PROXY;
        } else {
            // Default to RFC complaint proxy
            if (VersionUtil.isGsi2Enabled()) {
                proxyType = GSIConstants.GSI_2_PROXY;
            } else {
                proxyType = (VersionUtil.isGsi3Enabled()) ? GSIConstants.GSI_3_IMPERSONATION_PROXY
                        : GSIConstants.GSI_4_IMPERSONATION_PROXY;
            }
        }
    }

    X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();

    org.globus.gsi.X509Extension x509Ext = null;
    BigInteger serialNum = null;
    String delegDN = null;

    if (ProxyCertificateUtil.isGsi3Proxy(GSIConstants.CertificateType.get(proxyType))
            || ProxyCertificateUtil.isGsi4Proxy(GSIConstants.CertificateType.get(proxyType))) {
        Random rand = new Random();
        delegDN = String.valueOf(Math.abs(rand.nextInt()));
        serialNum = new BigInteger(20, rand);

        if (extSet != null) {
            x509Ext = extSet.get(ProxyCertInfo.OID.getId());
            if (x509Ext == null) {
                x509Ext = extSet.get(ProxyCertInfo.OLD_OID.getId());
            }
        }

        if (x509Ext == null) {
            // create ProxyCertInfo extension
            ProxyPolicy policy = null;
            if (ProxyCertificateUtil.isLimitedProxy(GSIConstants.CertificateType.get(proxyType))) {
                policy = new ProxyPolicy(ProxyPolicy.LIMITED);
            } else if (ProxyCertificateUtil.isIndependentProxy(GSIConstants.CertificateType.get(proxyType))) {
                policy = new ProxyPolicy(ProxyPolicy.INDEPENDENT);
            } else if (ProxyCertificateUtil.isImpersonationProxy(GSIConstants.CertificateType.get(proxyType))) {
                // since limited has already been checked, this should work.
                policy = new ProxyPolicy(ProxyPolicy.IMPERSONATION);
            } else if ((proxyType == GSIConstants.GSI_3_RESTRICTED_PROXY)
                    || (proxyType == GSIConstants.GSI_4_RESTRICTED_PROXY)) {
                String err = i18n.getMessage("restrictProxy");
                throw new IllegalArgumentException(err);
            } else {
                String err = i18n.getMessage("invalidProxyType");
                throw new IllegalArgumentException(err);
            }

            ProxyCertInfo proxyCertInfo = new ProxyCertInfo(policy);
            x509Ext = new ProxyCertInfoExtension(proxyCertInfo);
            if (ProxyCertificateUtil.isGsi4Proxy(GSIConstants.CertificateType.get(proxyType))) {
                // RFC compliant OID
                x509Ext = new ProxyCertInfoExtension(proxyCertInfo);
            } else {
                // old OID
                x509Ext = new GlobusProxyCertInfoExtension(proxyCertInfo);
            }
        }

        try {
            // add ProxyCertInfo extension to the new cert
            certGen.addExtension(x509Ext.getOid(), x509Ext.isCritical(), x509Ext.getValue());

            // handle KeyUsage in issuer cert
            TBSCertificateStructure crt = BouncyCastleUtil.getTBSCertificateStructure(issuerCert);

            X509Extensions extensions = crt.getExtensions();
            if (extensions != null) {
                X509Extension ext;

                // handle key usage ext
                ext = extensions.getExtension(X509Extension.keyUsage);
                if (ext != null) {

                    // TBD: handle this better
                    if (extSet != null && (extSet.get(X509Extension.keyUsage.getId()) != null)) {
                        String err = i18n.getMessage("keyUsageExt");
                        throw new GeneralSecurityException(err);
                    }

                    DERBitString bits = (DERBitString) BouncyCastleUtil.getExtensionObject(ext);

                    byte[] bytes = bits.getBytes();

                    // make sure they are disabled
                    if ((bytes[0] & KeyUsage.nonRepudiation) != 0) {
                        bytes[0] ^= KeyUsage.nonRepudiation;
                    }

                    if ((bytes[0] & KeyUsage.keyCertSign) != 0) {
                        bytes[0] ^= KeyUsage.keyCertSign;
                    }

                    bits = new DERBitString(bytes, bits.getPadBits());

                    certGen.addExtension(X509Extension.keyUsage, ext.isCritical(), bits);
                }
            }

        } catch (IOException e) {
            // but this should not happen
            throw new GeneralSecurityException(e.getMessage());
        }

    } else if (proxyType == GSIConstants.GSI_2_LIMITED_PROXY) {
        delegDN = "limited proxy";
        serialNum = issuerCert.getSerialNumber();
    } else if (proxyType == GSIConstants.GSI_2_PROXY) {
        delegDN = "proxy";
        serialNum = issuerCert.getSerialNumber();
    } else {
        String err = i18n.getMessage("unsupportedProxy", Integer.toString(proxyType));
        throw new IllegalArgumentException(err);
    }

    // add specified extensions
    if (extSet != null) {
        Iterator iter = extSet.oidSet().iterator();
        while (iter.hasNext()) {
            String oid = (String) iter.next();
            // skip ProxyCertInfo extension
            if (oid.equals(ProxyCertInfo.OID.getId()) || oid.equals(ProxyCertInfo.OLD_OID.getId())) {
                continue;
            }
            x509Ext = (org.globus.gsi.X509Extension) extSet.get(oid);
            certGen.addExtension(x509Ext.getOid(), x509Ext.isCritical(), x509Ext.getValue());
        }
    }

    X509Name issuerDN;
    if (issuerCert.getSubjectDN() instanceof X509Name) {
        issuerDN = (X509Name) issuerCert.getSubjectDN();
    } else {
        issuerDN = new X509Name(true, issuerCert.getSubjectX500Principal().getName());
    }

    X509NameHelper issuer = new X509NameHelper(issuerDN);

    X509NameHelper subject = new X509NameHelper(issuerDN);
    subject.add(BCStyle.CN, (cnValue == null) ? delegDN : cnValue);

    certGen.setSubjectDN(subject.getAsName());
    certGen.setIssuerDN(issuer.getAsName());

    certGen.setSerialNumber(serialNum);
    certGen.setPublicKey(publicKey);
    certGen.setSignatureAlgorithm(issuerCert.getSigAlgName());

    GregorianCalendar date = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
    /* Allow for a five minute clock skew here. */
    date.add(Calendar.MINUTE, -5);
    certGen.setNotBefore(date.getTime());

    /* If hours = 0, then cert lifetime is set to user cert */
    if (lifetime <= 0) {
        certGen.setNotAfter(issuerCert.getNotAfter());
    } else {
        date.add(Calendar.MINUTE, 5);
        date.add(Calendar.SECOND, lifetime);
        certGen.setNotAfter(date.getTime());
    }

    return certGen.generateX509Certificate(issuerKey);
}