Example usage for java.security.cert X509Certificate getExtensionValue

List of usage examples for java.security.cert X509Certificate getExtensionValue

Introduction

In this page you can find the example usage for java.security.cert X509Certificate getExtensionValue.

Prototype

public byte[] getExtensionValue(String oid);

Source Link

Document

Gets the DER-encoded OCTET string for the extension value (extnValue) identified by the passed-in oid String.

Usage

From source file:org.wso2.carbon.webapp.ext.cxf.crypto.CXFServerCrypto.java

/**
 * @see org.apache.ws.security.components.crypto.Crypto#getSKIBytesFromCert(java.security.cert.X509Certificate)
 *//*from   w w w.j  a v  a2 s.  co  m*/
public byte[] getSKIBytesFromCert(X509Certificate cert) throws WSSecurityException {
    /*
     * Gets the DER-encoded OCTET string for the extension value (extnValue)
     * identified by the passed-in oid String. The oid string is represented
     * by a set of positive whole numbers separated by periods.
     */
    byte[] derEncodedValue = cert.getExtensionValue(SKI_OID);

    if (cert.getVersion() < 3 || derEncodedValue == null) {
        PublicKey key = cert.getPublicKey();
        if (!(key instanceof RSAPublicKey)) {
            throw new WSSecurityException(1, "noSKIHandling", new Object[] { "Support for RSA key only" });
        }
        byte[] encoded = key.getEncoded();
        // remove 22-byte algorithm ID and header
        byte[] value = new byte[encoded.length - 22];
        System.arraycopy(encoded, 22, value, 0, value.length);
        MessageDigest sha;
        try {
            sha = MessageDigest.getInstance("SHA-1");
        } catch (NoSuchAlgorithmException ex) {
            throw new WSSecurityException(1, "noSKIHandling",
                    new Object[] { "Wrong certificate version (<3) and no " + "SHA1 message digest availabe" });
        }
        sha.reset();
        sha.update(value);
        return sha.digest();
    }

    /**
     * Strip away first four bytes from the DerValue (tag and length of
     * ExtensionValue OCTET STRING and KeyIdentifier OCTET STRING)
     */
    byte abyte0[] = new byte[derEncodedValue.length - 4];

    System.arraycopy(derEncodedValue, 4, abyte0, 0, abyte0.length);
    return abyte0;
}

From source file:org.viafirma.nucleo.validacion.CRLUtil.java

/**
 * Se conecta a la url indicada y se descarga las crls. No se esta usando
 * *******************!!! En desarrollo, no funciona
 * /*from   w  w  w  .j  a v  a  2  s  . com*/
 * @param hostURL
 * @return
 * @throws CRLException
 *             No se ha podido recuperar el listado
 * @throws CertificateParsingException
 */
@SuppressWarnings("unchecked")
private InputStream getIoCrlFromFNMTLDAP(X509Certificate certificadoX509)
        throws CRLException, CertificateParsingException {
    // ************************
    // recupero las propiedades para realizar la busqueda en LDAP.
    // EJ :[CN=CRL1, OU=FNMT Clase 2 CA, O=FNMT, C=ES] {2.5.4.11=FNMT Clase
    // 2 CA, 2.5.4.10=FNMT, 2.5.4.6=ES, 2.5.4.3=CRL1}
    Map<String, String> propiedades = new HashMap<String, String>();
    try {
        log.debug("Recuperando puntos de distribucin CRL del certificado FNMT: "
                + certificadoX509.getIssuerDN());
        // recupero la extensin OID 2.5.29.31 ( id-ce-cRLDistributionPoinds
        // segun el RFC 3280 seccin 4.2.1.14)
        byte[] val1 = certificadoX509.getExtensionValue(OID_CRLS);
        if (val1 == null) {
            log.debug("   El certificado NO tiene punto de distribucin de CRL ");
        } else {
            ASN1InputStream oAsnInStream = new ASN1InputStream(new ByteArrayInputStream(val1));
            DERObject derObj = oAsnInStream.readObject();
            DEROctetString dos = (DEROctetString) derObj;
            byte[] val2 = dos.getOctets();
            ASN1InputStream oAsnInStream2 = new ASN1InputStream(new ByteArrayInputStream(val2));
            DERObject derObj2 = oAsnInStream2.readObject();

            X509Handler.getCurrentInstance().readPropiedadesOid(OID_CRLS, derObj2, propiedades);

        }
    } catch (Exception e) {
        e.printStackTrace();
        throw new CertificateParsingException(e.toString());
    }

    // comprobamos la configuracin
    if (isSomeFNMTValorNull()) {
        throw new CRLException(
                "Para el acceso a las CRLs de la FNMT es necesario las credenciales. Indique el parametro de configuracin :"
                        + Constantes.CONEXION_LDAP_CRL_FNMT);
    }

    String CN = "CN=" + propiedades.get(FNMT_CN_IDENTIFICADOR) + "," + certificadoX509.getIssuerDN();
    log.debug("Buscando en el LDAP " + CN);

    // **********************************************
    // Nos conectamos al LDAP para recuperar la CRLs.

    Properties env = new Properties();
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    env.put(Context.PROVIDER_URL, fnmtLDAPHostURL);
    env.put(Context.SECURITY_AUTHENTICATION, "simple");
    env.put(Context.SECURITY_PRINCIPAL, fnmtPrincipal);
    env.put(Context.SECURITY_CREDENTIALS, fnmtCredencial);
    env.put(Context.REFERRAL, "follow");

    try {
        DirContext ctx = new InitialDirContext(env);
        SearchControls searchControls = new SearchControls();
        searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
        NamingEnumeration namings = (ctx.search(CN, "(objectclass=*)", searchControls));

        log.debug("Se ha logrado conectar al LDAP");

        if (namings.hasMore()) {
            log.debug("Recuperando el contenido de la CRLs");
            // recupero el resultado
            SearchResult resultado = ((SearchResult) namings.next());

            // recupero todos los atributos del resultado
            Attributes avals = resultado.getAttributes();

            // recupero los bytes.
            byte[] bytes;
            if ((avals.get("certificateRevocationList;binary")) != null) {
                log.debug("Atributos deben estar en binario");
                Attribute atributo = (avals.get("certificateRevocationList;binary"));
                bytes = ((byte[]) atributo.get());
            } else {
                log.debug("Atributos en exadecimal En Hexadecimal");
                Attribute atributo = (avals.get("certificateRevocationList"));
                bytes = ((byte[]) atributo.get());
                log.debug("Por implementar");
            }

            if (bytes != null) {
                ByteArrayInputStream io = new ByteArrayInputStream(bytes);
                return io;
            }
        }
    } catch (NamingException e) {
        log.error("No se puede conectar al LDAP!!", e);
    }
    return null;
}

From source file:org.ejbca.core.protocol.cmp.CrmfRAPbeMultipleKeyIdRequestTest.java

@Test
public void test07ExtensionOverride() throws Exception {

    byte[] nonce = CmpMessageHelper.createSenderNonce();
    byte[] transid = CmpMessageHelper.createSenderNonce();

    // Create some crazy extensions to see that we get them when using
    // extension override.
    // We should not get our values when not using extension override
    ExtensionsGenerator extgen = new ExtensionsGenerator();
    // SubjectAltName
    GeneralNames san = CertTools.getGeneralNamesFromAltName("dnsName=foo.bar.com");
    extgen.addExtension(Extension.subjectAlternativeName, false, san);
    // KeyUsage//from   w ww  .  j  ava 2s .  co  m
    int bcku = 0;
    bcku = X509KeyUsage.decipherOnly;
    X509KeyUsage ku = new X509KeyUsage(bcku);
    extgen.addExtension(Extension.keyUsage, false, ku);
    // Extended Key Usage
    List<KeyPurposeId> usage = new ArrayList<KeyPurposeId>();
    usage.add(KeyPurposeId.id_kp_codeSigning);
    ExtendedKeyUsage eku = ExtendedKeyUsage.getInstance(usage);
    extgen.addExtension(Extension.extendedKeyUsage, false, eku);
    // OcspNoCheck
    extgen.addExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nocheck, false, DERNull.INSTANCE);
    // Netscape cert type
    extgen.addExtension(new ASN1ObjectIdentifier("2.16.840.1.113730.1.1"), false,
            new NetscapeCertType(NetscapeCertType.objectSigningCA));
    // My completely own
    extgen.addExtension(new ASN1ObjectIdentifier("1.1.1.1.1"), false, new DERIA5String("PrimeKey"));

    // Make the complete extension package
    Extensions exts = extgen.generate();

    // First test without extension override
    PKIMessage one = genCertReq(this.issuerDN2, userDN2, this.keys, this.cacert2, nonce, transid, true, exts,
            null, null, null, null, null);
    PKIMessage req = protectPKIMessage(one, false, PBEPASSWORD, "KeyId2", 567);

    CertReqMessages ir = (CertReqMessages) req.getBody().getContent();
    int reqId = ir.toCertReqMsgArray()[0].getCertReq().getCertReqId().getValue().intValue();
    assertNotNull(req);
    ByteArrayOutputStream bao = new ByteArrayOutputStream();
    DEROutputStream out = new DEROutputStream(bao);
    out.writeObject(req);
    byte[] ba = bao.toByteArray();
    // Send request and receive response
    byte[] resp = sendCmpTcp(ba, 5);
    checkCmpResponseGeneral(resp, this.issuerDN2, userDN2, this.cacert2, nonce, transid, false, PBEPASSWORD,
            PKCSObjectIdentifiers.sha1WithRSAEncryption.getId());
    X509Certificate cert = checkCmpCertRepMessage(userDN2, this.cacert2, resp, reqId);
    String altNames = CertTools.getSubjectAlternativeName(cert);
    assertTrue(altNames.indexOf("dNSName=foo.bar.com") != -1);

    // Check key usage that it is nonRepudiation for KeyId2
    boolean[] kubits = cert.getKeyUsage();
    assertFalse(kubits[0]);
    assertTrue(kubits[1]);
    assertFalse(kubits[2]);
    assertFalse(kubits[3]);
    assertFalse(kubits[4]);
    assertFalse(kubits[5]);
    assertFalse(kubits[6]);
    assertFalse(kubits[7]);
    assertFalse(kubits[8]);
    // Our own ext should not be here
    assertNull(cert.getExtensionValue("1.1.1.1.1"));
    assertNull(cert.getExtensionValue("2.16.840.1.113730.1.1"));
    assertNull(cert.getExtensionValue(OCSPObjectIdentifiers.id_pkix_ocsp_nocheck.getId()));

    // Skip confirmation message, we have tested that several times already

    //
    // Do the same with keyId4, that has full extension override
    one = genCertReq(this.issuerDN2, userDN2, this.keys, this.cacert2, nonce, transid, true, exts, null, null,
            null, null, null);
    req = protectPKIMessage(one, false, PBEPASSWORD, "KeyId4", 567);

    ir = (CertReqMessages) req.getBody().getContent();
    reqId = ir.toCertReqMsgArray()[0].getCertReq().getCertReqId().getValue().intValue();
    assertNotNull(req);
    bao = new ByteArrayOutputStream();
    out = new DEROutputStream(bao);
    out.writeObject(req);
    ba = bao.toByteArray();
    // Send request and receive response
    resp = sendCmpTcp(ba, 5);
    checkCmpResponseGeneral(resp, this.issuerDN2, userDN2, this.cacert2, nonce, transid, false, PBEPASSWORD,
            PKCSObjectIdentifiers.sha1WithRSAEncryption.getId());
    cert = checkCmpCertRepMessage(userDN2, this.cacert2, resp, reqId);
    altNames = CertTools.getSubjectAlternativeName(cert);
    assertTrue(altNames.indexOf("dNSName=foo.bar.com") != -1);

    // Check key usage that it is decipherOnly for KeyId4
    kubits = cert.getKeyUsage();
    assertFalse(kubits[0]);
    assertFalse(kubits[1]);
    assertFalse(kubits[2]);
    assertFalse(kubits[3]);
    assertFalse(kubits[4]);
    assertFalse(kubits[5]);
    assertFalse(kubits[6]);
    assertFalse(kubits[7]);
    assertTrue(kubits[8]);
    // Our own ext should not be here
    assertNotNull(cert.getExtensionValue("1.1.1.1.1"));
    assertNotNull(cert.getExtensionValue("2.16.840.1.113730.1.1"));
    assertNotNull(cert.getExtensionValue(OCSPObjectIdentifiers.id_pkix_ocsp_nocheck.getId()));
    List<String> l = cert.getExtendedKeyUsage();
    assertEquals(1, l.size());
    String s = l.get(0);
    assertEquals(KeyPurposeId.id_kp_codeSigning.getId(), s);

    // Skip confirmation message, we have tested that several times already
}

From source file:org.apache.ws.security.components.crypto.Merlin.java

/**
 * Evaluate whether a given certificate chain should be trusted.
 * Uses the CertPath API to validate a given certificate chain.
 *
 * @param certs Certificate chain to validate
 * @param enableRevocation whether to enable CRL verification or not
 * @return true if the certificate chain is valid, false otherwise
 * @throws WSSecurityException//from w w  w  .ja  v  a 2s.c om
 */
public boolean verifyTrust(X509Certificate[] certs, boolean enableRevocation) throws WSSecurityException {
    try {
        // Generate cert path
        List<X509Certificate> certList = Arrays.asList(certs);
        CertPath path = getCertificateFactory().generateCertPath(certList);

        Set<TrustAnchor> set = new HashSet<TrustAnchor>();
        if (truststore != null) {
            Enumeration<String> truststoreAliases = truststore.aliases();
            while (truststoreAliases.hasMoreElements()) {
                String alias = truststoreAliases.nextElement();
                X509Certificate cert = (X509Certificate) truststore.getCertificate(alias);
                if (cert != null) {
                    TrustAnchor anchor = new TrustAnchor(cert, cert.getExtensionValue(NAME_CONSTRAINTS_OID));
                    set.add(anchor);
                }
            }
        }

        //
        // Add certificates from the keystore - only if there is no TrustStore, apart from
        // the case that the truststore is the JDK CA certs. This behaviour is preserved
        // for backwards compatibility reasons
        //
        if (keystore != null && (truststore == null || loadCACerts)) {
            Enumeration<String> aliases = keystore.aliases();
            while (aliases.hasMoreElements()) {
                String alias = aliases.nextElement();
                X509Certificate cert = (X509Certificate) keystore.getCertificate(alias);
                if (cert != null) {
                    TrustAnchor anchor = new TrustAnchor(cert, cert.getExtensionValue(NAME_CONSTRAINTS_OID));
                    set.add(anchor);
                }
            }
        }

        PKIXParameters param = new PKIXParameters(set);
        param.setRevocationEnabled(enableRevocation);
        if (enableRevocation && crlCertStore != null) {
            param.addCertStore(crlCertStore);
        }

        // Verify the trust path using the above settings
        String provider = getCryptoProvider();
        CertPathValidator validator = null;
        if (provider == null || provider.length() == 0) {
            validator = CertPathValidator.getInstance("PKIX");
        } else {
            validator = CertPathValidator.getInstance("PKIX", provider);
        }
        validator.validate(path, param);
        return true;
    } catch (java.security.NoSuchProviderException e) {
        throw new WSSecurityException(WSSecurityException.FAILURE, "certpath", new Object[] { e.getMessage() },
                e);
    } catch (java.security.NoSuchAlgorithmException e) {
        throw new WSSecurityException(WSSecurityException.FAILURE, "certpath", new Object[] { e.getMessage() },
                e);
    } catch (java.security.cert.CertificateException e) {
        throw new WSSecurityException(WSSecurityException.FAILURE, "certpath", new Object[] { e.getMessage() },
                e);
    } catch (java.security.InvalidAlgorithmParameterException e) {
        throw new WSSecurityException(WSSecurityException.FAILURE, "certpath", new Object[] { e.getMessage() },
                e);
    } catch (java.security.cert.CertPathValidatorException e) {
        throw new WSSecurityException(WSSecurityException.FAILURE, "certpath", new Object[] { e.getMessage() },
                e);
    } catch (java.security.KeyStoreException e) {
        throw new WSSecurityException(WSSecurityException.FAILURE, "certpath", new Object[] { e.getMessage() },
                e);
    } catch (NullPointerException e) {
        // NPE thrown by JDK 1.7 for one of the test cases
        throw new WSSecurityException(WSSecurityException.FAILURE, "certpath", new Object[] { e.getMessage() },
                e);
    }
}

From source file:org.ejbca.util.CertTools.java

/**
 * Get the authority key identifier from a certificate extensions
 *
 * @param cert certificate containing the extension
 * @return byte[] containing the authority key identifier, or null if it does not exist
 * @throws IOException if extension can not be parsed
 *///from w  w  w.ja v a 2  s.  c  o m
public static byte[] getAuthorityKeyId(Certificate cert) throws IOException {
    if (cert == null) {
        return null;
    }
    if (cert instanceof X509Certificate) {
        X509Certificate x509cert = (X509Certificate) cert;
        byte[] extvalue = x509cert.getExtensionValue("2.5.29.35");
        if (extvalue == null) {
            return null;
        }
        DEROctetString oct = (DEROctetString) (new ASN1InputStream(new ByteArrayInputStream(extvalue))
                .readObject());
        AuthorityKeyIdentifier keyId = new AuthorityKeyIdentifier(
                (ASN1Sequence) new ASN1InputStream(new ByteArrayInputStream(oct.getOctets())).readObject());
        return keyId.getKeyIdentifier();
    }
    return null;
}

From source file:org.ejbca.util.CertTools.java

/**
 * Get the subject key identifier from a certificate extensions
 *
 * @param cert certificate containing the extension
 * @return byte[] containing the subject key identifier, or null if it does not exist
 * @throws IOException if extension can not be parsed
 */// ww  w .  j ava  2  s.  c  o  m
public static byte[] getSubjectKeyId(Certificate cert) throws IOException {
    if (cert == null) {
        return null;
    }
    if (cert instanceof X509Certificate) {
        X509Certificate x509cert = (X509Certificate) cert;
        byte[] extvalue = x509cert.getExtensionValue("2.5.29.14");
        if (extvalue == null) {
            return null;
        }
        ASN1OctetString str = ASN1OctetString
                .getInstance(new ASN1InputStream(new ByteArrayInputStream(extvalue)).readObject());
        SubjectKeyIdentifier keyId = SubjectKeyIdentifier
                .getInstance(new ASN1InputStream(new ByteArrayInputStream(str.getOctets())).readObject());
        return keyId.getKeyIdentifier();
    }
    return null;
}

From source file:org.ejbca.util.CertTools.java

/**
 * Get a certificate policy ID from a certificate policies extension
 *
 * @param cert certificate containing the extension
 * @param pos position of the policy id, if several exist, the first is as pos 0
 * @return String with the certificate policy OID
 * @throws IOException if extension can not be parsed
 *//* ww  w  . ja v  a2 s. c  o  m*/
public static String getCertificatePolicyId(Certificate cert, int pos) throws IOException {
    String ret = null;
    if (cert instanceof X509Certificate) {
        X509Certificate x509cert = (X509Certificate) cert;
        byte[] extvalue = x509cert.getExtensionValue(X509Extensions.CertificatePolicies.getId());
        if (extvalue == null) {
            return null;
        }
        DEROctetString oct = (DEROctetString) (new ASN1InputStream(new ByteArrayInputStream(extvalue))
                .readObject());
        ASN1Sequence seq = (ASN1Sequence) new ASN1InputStream(new ByteArrayInputStream(oct.getOctets()))
                .readObject();
        // Check the size so we don't ArrayIndexOutOfBounds
        if (seq.size() < pos + 1) {
            return null;
        }
        PolicyInformation pol = new PolicyInformation((ASN1Sequence) seq.getObjectAt(pos));
        ret = pol.getPolicyIdentifier().getId();
    }
    return ret;
}

From source file:org.ejbca.util.CertTools.java

/**
 * Return an Extension DERObject from a certificate
 *///from  www .  j  a  va 2 s  .  c  o m
protected static DERObject getExtensionValue(X509Certificate cert, String oid) throws IOException {
    if (cert == null) {
        return null;
    }
    byte[] bytes = cert.getExtensionValue(oid);
    if (bytes == null) {
        return null;
    }
    ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(bytes));
    ASN1OctetString octs = (ASN1OctetString) aIn.readObject();
    aIn = new ASN1InputStream(new ByteArrayInputStream(octs.getOctets()));
    return aIn.readObject();
}

From source file:org.hyperledger.fabric_ca.sdk.HFCAClient.java

private String revokeInternal(User revoker, Enrollment enrollment, String reason, boolean genCRL)
        throws RevocationException, InvalidArgumentException {

    if (cryptoSuite == null) {
        throw new InvalidArgumentException("Crypto primitives not set.");
    }//from w  w w  . j  a v  a 2 s.  c o  m

    if (enrollment == null) {
        throw new InvalidArgumentException("revokee enrollment is not set");
    }
    if (revoker == null) {
        throw new InvalidArgumentException("revoker is not set");
    }

    logger.debug(format("revoke revoker: %s, reason: %s, url: %s", revoker.getName(), reason, url));

    try {
        setUpSSL();

        // get cert from to-be-revoked enrollment
        BufferedInputStream pem = new BufferedInputStream(
                new ByteArrayInputStream(enrollment.getCert().getBytes()));
        CertificateFactory certFactory = CertificateFactory
                .getInstance(Config.getConfig().getCertificateFormat());
        X509Certificate certificate = (X509Certificate) certFactory.generateCertificate(pem);

        // get its serial number
        String serial = DatatypeConverter.printHexBinary(certificate.getSerialNumber().toByteArray());

        // get its aki
        // 2.5.29.35 : AuthorityKeyIdentifier
        byte[] extensionValue = certificate.getExtensionValue(Extension.authorityKeyIdentifier.getId());
        ASN1OctetString akiOc = ASN1OctetString.getInstance(extensionValue);
        String aki = DatatypeConverter
                .printHexBinary(AuthorityKeyIdentifier.getInstance(akiOc.getOctets()).getKeyIdentifier());

        // build request body
        RevocationRequest req = new RevocationRequest(caName, null, serial, aki, reason, genCRL);
        String body = req.toJson();

        // send revoke request
        JsonObject resp = httpPost(url + HFCA_REVOKE, body, revoker);
        logger.debug("revoke done");

        if (genCRL) {
            if (resp.isEmpty()) {
                throw new RevocationException("Failed to return CRL, revoke response is empty");
            }
            if (resp.isNull("CRL")) {
                throw new RevocationException("Failed to return CRL");
            }
            return resp.getString("CRL");
        }
        return null;
    } catch (CertificateException e) {
        logger.error("Cannot validate certificate. Error is: " + e.getMessage());
        throw new RevocationException("Error while revoking cert. " + e.getMessage(), e);
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
        throw new RevocationException("Error while revoking the user. " + e.getMessage(), e);

    }
}

From source file:org.ejbca.ui.cli.HSMKeyTool.java

private static boolean doIt(final String[] orgArgs) throws Exception {
    // Get and remove optional switches
    final List<String> argsList = CliTools.getAsModifyableList(orgArgs);
    final KeyStore.ProtectionParameter protectionParameter;
    final String password = CliTools.getAndRemoveParameter("-password", argsList);
    if (password != null) {
        protectionParameter = new KeyStore.PasswordProtection(password.toCharArray());
    } else {//from   w w  w  .j av a  2  s .c  om
        protectionParameter = null;
    }
    final String[] args = CliTools.getAsArgs(argsList);
    if (args[1].toLowerCase().trim().contains(GENERATE_BATCH_SWITCH)) {
        if (args.length < 4) {
            printCommandString(args, "<name of batch file> [", TOKEN_ID_PARAM, "]");
            printTokenIdDescription();
            sunConfigFileUseDescription();
            System.err.println(
                    "The batch file is a file which specifies alias and key specification for each key to be generated.");
            System.err
                    .println("Each row is starting with a key alias then the key specification is following.");
            System.err.println("The specification of the key is done like this: " + KEY_SPEC_DESC);
            tooFewArguments(args);
        }
        final String storeId;
        final Pkcs11SlotLabelType slotType;
        if (args.length > 4) {
            storeId = trimStoreId(args[4]);
            slotType = getTokenLabelType(args[4]);
        } else {
            storeId = null;
            slotType = Pkcs11SlotLabelType.SUN_FILE;
        }
        final KeyStoreTools store = KeyStoreToolsFactory.getInstance(args[2], storeId, slotType, null,
                protectionParameter, "batch-" + new Date().getTime());
        generateBatch(args[3], store);
        return true;
    }
    if (args[1].toLowerCase().trim().contains(GENERATE_SWITCH)) {
        if (args.length < 4) {
            printCommandString(args, Character.valueOf('<'), KEY_SPEC_DESC, "> <key entry name> [",
                    TOKEN_ID_PARAM, "]");
            printTokenIdDescription();
            sunConfigFileUseDescription();
            tooFewArguments(args);
        }
        final String keyEntryName = args.length > 4 ? args[4] : "myKey";
        final String storeId;
        final Pkcs11SlotLabelType slotType;
        if (args.length > 5) {
            storeId = trimStoreId(args[5]);
            slotType = getTokenLabelType(args[5]);
        } else {
            storeId = null;
            slotType = Pkcs11SlotLabelType.SUN_FILE;
        }
        System.out.println("Using Slot Reference Type: " + slotType + '.');
        final KeyStoreTools store = KeyStoreToolsFactory.getInstance(args[2], storeId, slotType, null,
                protectionParameter, "priv-" + keyEntryName);
        store.generateKeyPair(args[3], keyEntryName);
        System.out.println("Created certificate with entry " + keyEntryName + '.');
        return true;
    }
    if (args[1].toLowerCase().trim().equals(DELETE_SWITCH)) {
        if (args.length < 4) {
            printCommandString(args, TOKEN_ID_PARAM, " [<key entry name>]");
            printTokenIdDescription();
            tooFewArguments(args);
        }
        final String alias = args.length > 4 ? args[4] : null;
        System.out.println("Deleting certificate with alias " + alias + '.');
        final String storeId = trimStoreId(args[3]);
        final Pkcs11SlotLabelType slotType = getTokenLabelType(args[3]);

        KeyStoreToolsFactory.getInstance(args[2], storeId, slotType, null, protectionParameter)
                .deleteEntry(alias);
        return true;
    }
    if (args[1].toLowerCase().trim().equals(CERT_REQ)) {
        // First we check if we have a switch for "-explicitecc" for explicit ecc parameters used in ICAO epassports.
        final List<String> argsListLocal = CliTools.getAsModifyableList(args);
        final boolean explicitEccParameters = argsListLocal.remove("-explicitecc");
        final boolean forAllKeys = argsListLocal.remove("-all");
        final String modArgs[] = argsListLocal.toArray(new String[argsListLocal.size()]);
        if (modArgs.length < 4 || (modArgs.length < 5 && !forAllKeys)) {
            printCommandString(args, TOKEN_ID_PARAM, " <key entry name> [<CN>] [-explicitecc]");
            printCommandString(args, TOKEN_ID_PARAM, " [-all] [-explicitecc]");
            printTokenIdDescription();
            tooFewArguments(modArgs);
        }
        final String storeId = trimStoreId(modArgs[3]);
        final Pkcs11SlotLabelType slotType = getTokenLabelType(modArgs[3]);
        final KeyStoreTools container = KeyStoreToolsFactory.getInstance(modArgs[2], storeId, slotType, null,
                protectionParameter);
        final List<String> entries;
        if (forAllKeys) {
            entries = new LinkedList<>();
            final CachingKeyStoreWrapper ks = container.getKeyStore();
            final Enumeration<String> aliases = ks.aliases();
            while (aliases.hasMoreElements()) {
                final String alias = aliases.nextElement();
                if (ks.isKeyEntry(alias)) {
                    entries.add(alias);
                }
            }
        } else {
            entries = Collections.singletonList(modArgs[4]);
        }

        for (String entry : entries) {
            container.generateCertReq(entry, modArgs.length > 5 ? modArgs[5] : null, explicitEccParameters);
        }
        return true;
    }
    if (args[1].toLowerCase().trim().equals(INSTALL_CERT)) {
        if (args.length < 5) {
            printCommandString(args, TOKEN_ID_PARAM,
                    " <certificate chain files in PEM format (one chain per file)>");
            printTokenIdDescription();
            tooFewArguments(args);
        }
        final String storeId = trimStoreId(args[3]);
        final Pkcs11SlotLabelType slotType = getTokenLabelType(args[3]);
        final KeyStoreTools container = KeyStoreToolsFactory.getInstance(args[2], storeId, slotType, null,
                protectionParameter);
        boolean failure = false;
        for (int i = 4; i < args.length; i++) {
            try {
                container.installCertificate(args[i]);
            } catch (Exception ex) {
                failure = true;
                log.error("File " + args[i] + " failed.", ex);
            }
        }
        if (failure) {
            throw new Exception("At least one certificate could not be installed. See the log for more info.");
        }
        return true;
    }
    if (args[1].toLowerCase().trim().equals(INSTALL_TRUSTED_ROOT)) {
        if (args.length < 5) {
            printCommandString(args, TOKEN_ID_PARAM, " <trusted root certificate in PEM format>");
            printTokenIdDescription();
            tooFewArguments(args);
        }
        final String storeId = trimStoreId(args[3]);
        final Pkcs11SlotLabelType slotType = getTokenLabelType(args[3]);
        KeyStoreToolsFactory.getInstance(args[2], storeId, slotType, null, protectionParameter)
                .installTrustedRoot(args[4]);
        return true;
    }
    if (args[1].toLowerCase().trim().equals(ENCRYPT_SWITCH)) {
        String symmAlgOid = CMSEnvelopedGenerator.AES128_CBC;
        if (args.length < 5) {
            System.err.println("There are two ways of doing the encryption:");
            printCommandString(args, TOKEN_ID_PARAM,
                    " <input file> <output file> <key alias> [optional symm algorithm oid]");
            printCommandStringNoSharedLib(args,
                    "<input file> <output file> <file with certificate with public key to use> [optional symm algorithm oid]");
            printTokenIdDescription();
            System.err.println(
                    "Optional symmetric encryption algorithm OID can be for example 2.16.840.1.101.3.4.1.42 (AES256_CBC) or 1.2.392.200011.61.1.1.1.4 (CAMELLIA256_CBC). Default is to use AES256_CBC.");
            tooFewArguments(args);
        }
        if (args.length < 7) {
            Security.addProvider(new BouncyCastleProvider());
            if (args.length > 5) {
                // We have a symmAlg as last parameter
                symmAlgOid = args[5];
            }
            System.out.println("Using symmetric encryption algorithm: " + symmAlgOid);
            try (final InputStream certIS = new FileInputStream(args[4]);
                    final InputStream is = new FileInputStream(args[2]);
                    final OutputStream os = new FileOutputStream(args[3])) {
                final X509Certificate cert = (X509Certificate) CertificateFactory.getInstance("X.509")
                        .generateCertificate(new BufferedInputStream(certIS));
                CMS.encrypt(is, os, cert, symmAlgOid);
            }
        } else {
            if (args.length > 7) {
                // We have a symmAlg as last parameter
                symmAlgOid = args[7];
            }
            System.out.println("Using symmstric encryption algorithm: " + symmAlgOid);
            final String storeId = trimStoreId(args[3]);
            final Pkcs11SlotLabelType slotType = getTokenLabelType(args[3]);
            try (final InputStream is = new FileInputStream(args[4]);
                    final OutputStream os = new FileOutputStream(args[5]);) {
                final Certificate cert = KeyStoreToolsFactory
                        .getInstance(args[2], storeId, slotType, null, protectionParameter).getKeyStore()
                        .getCertificate(args[6]);
                CMS.encrypt(is, os, (X509Certificate) cert, symmAlgOid);
            }
        }
        return true;
    }
    if (args[1].toLowerCase().trim().equals(DECRYPT_SWITCH)) {
        if (args.length < 7) {
            printCommandString(args, TOKEN_ID_PARAM, " <input file> <output file> <key alias>");
            printTokenIdDescription();
            tooFewArguments(args);
        }
        final String storeId = trimStoreId(args[3]);
        final Pkcs11SlotLabelType slotType = getTokenLabelType(args[3]);
        try (final InputStream is = new FileInputStream(args[4]);
                final OutputStream os = new FileOutputStream(args[5])) {
            final KeyStoreTools keyStore = KeyStoreToolsFactory.getInstance(args[2], storeId, slotType, null,
                    protectionParameter);
            CMS.decrypt(is, os, (PrivateKey) keyStore.getKeyStore().getKey(args[6], null),
                    keyStore.getProviderName());
        }
        return true;
    }
    if (args[1].toLowerCase().trim().equals(SIGN_SWITCH)) {
        if (args.length < 7) {
            printCommandString(args, TOKEN_ID_PARAM, " <input file> <output file> <key alias>");
            printTokenIdDescription();
            tooFewArguments(args);
        }
        final String storeId = trimStoreId(args[3]);
        final Pkcs11SlotLabelType slotType = getTokenLabelType(args[3]);
        final KeyStoreTools keyStore = KeyStoreToolsFactory.getInstance(args[2], storeId, slotType, null,
                protectionParameter);
        final String alias = args[6];
        final PrivateKey key = (PrivateKey) keyStore.getKeyStore().getKey(alias, null);
        final X509Certificate cert = (X509Certificate) keyStore.getKeyStore().getCertificate(alias);
        try (final InputStream is = new FileInputStream(args[4]);
                final OutputStream os = new FileOutputStream(args[5]);) {
            CMS.sign(is, os, key, keyStore.getProviderName(), cert);
        }
        return true;
    }
    if (args[1].toLowerCase().trim().equals(LINKCERT_SWITCH)) {
        if (args.length < 8) {
            printCommandString(args, TOKEN_ID_PARAM,
                    " <old ca-cert> <new ca-cert> <output link-cert> <key alias> [<sig alg override>]");
            printTokenIdDescription();
            System.err.println();
            System.err.println("Creates a link certificate that links the old and new certificate files.");
            System.err.println("You should use this command with the old HSM key. It does not need any");
            System.err.println("access to the new key.");
            System.err.println();
            tooFewArguments(args);
        }
        final String storeId = trimStoreId(args[3]);
        final Pkcs11SlotLabelType slotType = getTokenLabelType(args[3]);
        final KeyStoreTools ksc = KeyStoreToolsFactory.getInstance(args[2], storeId, slotType, null,
                protectionParameter);
        final String alias = args[7];
        final String oldCertPath = args[4];
        final String newCertPath = args[5];
        final String outputPath = args[6];
        final String signProviderName = ksc.getProviderName();
        final String sigAlgOverride = (args.length > 8 ? args[8] : "null");

        // Parse certificates
        final byte[] oldCertBytes;
        try (final InputStream is = new FileInputStream(oldCertPath)) {
            oldCertBytes = IOUtils.toByteArray(is);
        }
        final byte[] newCertBytes;
        try (final InputStream is = new FileInputStream(newCertPath)) {
            newCertBytes = IOUtils.toByteArray(is);
        }
        final Certificate oldCert = CertTools.getCertfromByteArray(oldCertBytes,
                BouncyCastleProvider.PROVIDER_NAME, Certificate.class);
        final Certificate newCert = CertTools.getCertfromByteArray(newCertBytes,
                BouncyCastleProvider.PROVIDER_NAME, Certificate.class);
        final boolean isCVCA = (oldCert instanceof CardVerifiableCertificate);
        if (isCVCA != (newCert instanceof CardVerifiableCertificate)) {
            log.error("Error: Old and new certificates are not of the same type (X509 / CVC)");
            return true; // = valid command-line syntax
        }
        System.out.println("Type of certificates: " + (isCVCA ? "CVC" : "X509"));

        // Detect name change
        final String oldDN = CertTools.getSubjectDN(oldCert);
        final String newDN = CertTools.getSubjectDN(newCert);
        System.out.println("Old DN: " + oldDN);
        System.out.println("New DN: " + newDN);
        final boolean nameChange;
        if (!oldDN.equals(newDN)) {
            if (isCVCA) {
                System.out.println("Name change detected.");
            } else {
                System.out.println("Name change detected. Will add Name Change extension.");
            }
            nameChange = true;
        } else {
            System.out.println("No name change detected.");
            nameChange = false;
        }

        final ByteArrayOutputStream baos = new ByteArrayOutputStream();

        // Get new and old key
        final PublicKey newPubKey = newCert.getPublicKey();
        if (newPubKey == null) {
            System.err.println("Error: Failed to extract public key from new certificate");
            return true;
        }
        final Key oldKey = ksc.getKeyStore().getKey(alias, null);
        if (oldKey == null) {
            System.err.println("Error: Could not find the key named " + alias);
            return true;
        }
        final PrivateKey oldPrivKey = (PrivateKey) oldKey;

        if (isCVCA) {
            final CVCertificate oldCertCVC = ((CardVerifiableCertificate) oldCert).getCVCertificate();
            final CVCertificate newCertCVC = ((CardVerifiableCertificate) newCert).getCVCertificate();

            final String linkSigAlg;
            if (sigAlgOverride.equalsIgnoreCase("null")) {
                final OIDField oldKeyTypeOid = oldCertCVC.getCertificateBody().getPublicKey()
                        .getObjectIdentifier();
                linkSigAlg = AlgorithmUtil.getAlgorithmName(oldKeyTypeOid);
            } else {
                System.err.println("Error: Overriding the signature algorithm is not supported for CVC");
                return true;
            }
            System.out.println("Using signature algorithm " + linkSigAlg);

            final HolderReferenceField caHolder = oldCertCVC.getCertificateBody().getHolderReference();
            final CAReferenceField caRef = new CAReferenceField(caHolder.getCountry(), caHolder.getMnemonic(),
                    caHolder.getSequence());
            final HolderReferenceField certHolder = newCertCVC.getCertificateBody().getHolderReference();
            final AuthorizationRole authRole = newCertCVC.getCertificateBody().getAuthorizationTemplate()
                    .getAuthorizationField().getAuthRole();
            final AccessRights rights = newCertCVC.getCertificateBody().getAuthorizationTemplate()
                    .getAuthorizationField().getAccessRights();
            final Date validFrom = new Date(new Date().getTime() - 60L * 15L * 1000L); // back date by 15 minutes to allow for clock skew
            final Date validTo = oldCertCVC.getCertificateBody().getValidTo();

            final CVCertificate linkCert = CertificateGenerator.createCertificate(newPubKey, oldPrivKey,
                    linkSigAlg, caRef, certHolder, authRole, rights, validFrom, validTo, signProviderName);
            try (final DataOutputStream dos = new DataOutputStream(baos)) {
                linkCert.encode(dos);
            }
        } else {
            // X509 CA
            final X509Certificate oldCertX509 = (X509Certificate) oldCert;
            final X509Certificate newCertX509 = (X509Certificate) newCert;

            final String linkSigAlg;
            if (sigAlgOverride.equalsIgnoreCase("null")) {
                // Actually, we should use signature algorithm of new cert if the old key allows that.
                // Instead of doing that we allow the user to manually override the signature algorithm if needed.
                linkSigAlg = oldCertX509.getSigAlgName();
            } else {
                System.err.println("Warning: Signature algorithm manually overridden!");
                linkSigAlg = sigAlgOverride;
            }
            System.out.println("Using signature algorithm " + linkSigAlg);

            final BigInteger serno = SernoGeneratorRandom.instance().getSerno();
            final SubjectPublicKeyInfo pkinfo = SubjectPublicKeyInfo.getInstance(newPubKey.getEncoded());
            final Date validFrom = new Date(new Date().getTime() - 60L * 15L * 1000L); // back date by 15 minutes to allow for clock skew
            final Date validTo = oldCertX509.getNotAfter();

            final X500Name oldDNName = X500Name.getInstance(oldCertX509.getSubjectX500Principal().getEncoded());
            final X500Name newDNName = X500Name.getInstance(newCertX509.getSubjectX500Principal().getEncoded());

            final X509v3CertificateBuilder certbuilder = new X509v3CertificateBuilder(oldDNName, serno,
                    validFrom, validTo, newDNName, pkinfo);

            // Copy all extensions except AKID
            final ExtensionsGenerator extgen = new ExtensionsGenerator();
            final Set<String> oids = new LinkedHashSet<>();
            final Set<String> criticalOids = newCertX509.getCriticalExtensionOIDs();
            oids.addAll(criticalOids);
            oids.addAll(newCertX509.getNonCriticalExtensionOIDs());
            for (final String extOidStr : oids) {
                final ASN1ObjectIdentifier extoid = new ASN1ObjectIdentifier(extOidStr);
                if (!extoid.equals(Extension.authorityKeyIdentifier)) {
                    final byte[] extbytes = newCertX509.getExtensionValue(extOidStr);
                    final ASN1OctetString str = (ASN1OctetString) ASN1Primitive.fromByteArray(extbytes);
                    extgen.addExtension(extoid, criticalOids.contains(extOidStr),
                            ASN1Primitive.fromByteArray(str.getOctets()));
                }
            }

            if (nameChange) {
                // id-icao-mrtd-security-extensions-nameChange = 2.23.136.1.1.6.1
                extgen.addExtension(ICAOObjectIdentifiers.id_icao_extensions_namechangekeyrollover, false,
                        DERNull.INSTANCE);
            }

            // Some checks
            if (newCertX509.getExtensionValue(Extension.subjectKeyIdentifier.getId()) == null) {
                System.err.println(
                        "Warning: Certificate of new CSCA is missing the Subject Key Identifier extension, which is mandatory.");
            }
            if (newCertX509.getExtensionValue(Extension.authorityKeyIdentifier.getId()) == null) {
                System.err.println(
                        "Warning: Certificate of new CSCA is missing the Authority Key Identifier extension, which is mandatory.");
            }

            // If the new cert has an AKID, then add that extension but with the key id value of the old cert
            final byte[] oldSKIDBytes = oldCertX509.getExtensionValue(Extension.subjectKeyIdentifier.getId());
            if (oldSKIDBytes != null) {
                final ASN1OctetString str = (ASN1OctetString) ASN1Primitive.fromByteArray(oldSKIDBytes);
                final ASN1OctetString innerStr = (ASN1OctetString) ASN1Primitive.fromByteArray(str.getOctets());
                final AuthorityKeyIdentifier akidExt = new AuthorityKeyIdentifier(innerStr.getOctets());
                extgen.addExtension(Extension.authorityKeyIdentifier, false, akidExt);
            } else {
                System.err.println(
                        "Warning: The old certificate doesn't have any SubjectKeyIdentifier. The link certificate will not have any AuthorityKeyIdentifier.");
            }

            // Add extensions to the certificate
            final Extensions exts = extgen.generate();
            for (final ASN1ObjectIdentifier extoid : exts.getExtensionOIDs()) {
                final Extension ext = exts.getExtension(extoid);
                certbuilder.addExtension(extoid, ext.isCritical(), ext.getParsedValue());
            }

            // Sign the certificate
            final ContentSigner signer = new BufferingContentSigner(
                    new JcaContentSignerBuilder(linkSigAlg).setProvider(signProviderName).build(oldPrivKey),
                    20480);
            final X509CertificateHolder certHolder = certbuilder.build(signer);
            baos.write(certHolder.getEncoded());

            // Save to output file
            try (final FileOutputStream fos = new FileOutputStream(outputPath)) {
                baos.writeTo(fos);
            }
        }
        return true;
    }
    if (args[1].toLowerCase().trim().equals(VERIFY_SWITCH)) {
        final CMS.VerifyResult verifyResult;
        if (args.length < 5) {
            System.err.println("There are two ways of doing the encryption:");
            printCommandString(args, TOKEN_ID_PARAM, " <input file> <output file> <key alias>");
            printTokenIdDescription();
            printCommandStringNoSharedLib(args,
                    "<input file> <output file> <file with certificate with public key to use>");
            tooFewArguments(args);
        }
        if (args.length < 7) {
            Security.addProvider(new BouncyCastleProvider());
            try (final InputStream certIS = new FileInputStream(args[4]);
                    final InputStream is = new FileInputStream(args[2]);
                    final OutputStream os = new FileOutputStream(args[3]);) {
                final X509Certificate cert = (X509Certificate) CertificateFactory.getInstance("X.509")
                        .generateCertificate(new BufferedInputStream(certIS));
                verifyResult = CMS.verify(is, os, cert);
            }
        } else {
            final String storeId = trimStoreId(args[3]);
            final Pkcs11SlotLabelType slotType = getTokenLabelType(args[3]);
            final KeyStoreTools keyStore = KeyStoreToolsFactory.getInstance(args[2], storeId, slotType, null,
                    protectionParameter);
            final X509Certificate cert = (X509Certificate) keyStore.getKeyStore().getCertificate(args[6]);
            try (final InputStream is = new FileInputStream(args[4]);
                    final OutputStream os = new FileOutputStream(args[5])) {
                verifyResult = CMS.verify(is, os, cert);
            }
        }
        if (verifyResult == null) {
            System.err.println("Not possible to parse signed file.");
            System.exit(4); // Not verifying // NOPMD, it's not a JEE app
            return false;//will never be executes. just to avoid warning.
        }
        System.out.println(
                "The signature of the input " + (verifyResult.isVerifying ? "has been" : "could not be")
                        + " verified. The file was signed on '" + verifyResult.signDate
                        + "'. The public part of the signing key is in a certificate with serial number "
                        + verifyResult.signerId.getSerialNumber() + " issued by '"
                        + verifyResult.signerId.getIssuer() + "'.");
        if (!verifyResult.isVerifying) {
            System.exit(4); // Not verifying // NOPMD, it's not a JEE app
        }
        return true;
    }
    if (args[1].toLowerCase().trim().equals(TEST_SWITCH)) {
        if (args.length < 4) {
            printCommandString(args, TOKEN_ID_PARAM,
                    " [<'m:n' m # of threads, n # of tests>] [<alias for stress test>] [<type of stress test>]");
            printTokenIdDescription();
            System.err.println(
                    "    If a file named \"./testData\" exists then the data that is signed, is read from this file.");
            tooFewArguments(args);
        }
        final String storeId = trimStoreId(args[3]);
        final Pkcs11SlotLabelType slotType = getTokenLabelType(args[3]);
        final NrOfThreadsAndNrOfTests notanot = new NrOfThreadsAndNrOfTests(args.length > 4 ? args[4] : null);
        KeyStoreContainerTest.test(args[2], storeId, slotType, notanot.threads, notanot.tests,
                args.length > 5 ? args[5].trim() : null, args.length > 6 ? args[6].trim() : null,
                protectionParameter);
        return true;
    }
    if (args[1].toLowerCase().trim().equals(RENAME)) {
        if (args.length < 6) {
            printCommandString(args, TOKEN_ID_PARAM, " <old key alias> <new key alias>");
            printTokenIdDescription();
            tooFewArguments(args);
        }
        final String storeId = trimStoreId(args[3]);
        final Pkcs11SlotLabelType slotType = getTokenLabelType(args[3]);
        final KeyStoreTools keyStore = KeyStoreToolsFactory.getInstance(args[2], storeId, slotType, null,
                protectionParameter);

        keyStore.renameEntry(args[4], args[5]);
        return true;
    }
    if (args[1].toLowerCase().trim().equals(MOVE_SWITCH)) {
        if (args.length < 5) {
            printCommandString(args, "<from PKCS#11 token identifier> <to PKCS#11 token identifier>");
            printTokenIdDescription();
            tooFewArguments(args);
        }
        final KeyStoreTools fromKS = KeyStoreToolsFactory.getInstance(args[2], trimStoreId(args[3]),
                getTokenLabelType(args[3]), null, protectionParameter);
        final KeyStoreTools toKS = KeyStoreToolsFactory.getInstance(args[2], trimStoreId(args[4]),
                getTokenLabelType(args[4]), null, protectionParameter);
        System.out.println("Moving entry with alias '" + args[3] + "' to alias '" + args[4] + '.');
        final Enumeration<String> e = fromKS.getKeyStore().aliases();
        while (e.hasMoreElements()) {
            final String alias = e.nextElement();
            if (fromKS.getKeyStore().isKeyEntry(alias)) {
                final Key key = fromKS.getKeyStore().getKey(alias, null);
                final Certificate chain[] = fromKS.getKeyStore().getCertificateChain(alias);
                toKS.setKeyEntry(alias, key, chain);
            }
            fromKS.getKeyStore().deleteEntry(alias);
        }
        fromKS.getKeyStore().store(null, null);
        toKS.getKeyStore().store(null, null);
        return true;
    }
    return false;
}