Example usage for java.security.cert X509Certificate getSigAlgName

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

Introduction

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

Prototype

public abstract String getSigAlgName();

Source Link

Document

Gets the signature algorithm name for the certificate signature algorithm.

Usage

From source file:be.e_contract.eid.applet.service.impl.handler.IdentityDataMessageHandler.java

@Override
public Object handleMessage(IdentityDataMessage message, Map<String, String> httpHeaders,
        HttpServletRequest request, HttpSession session) throws ServletException {
    LOG.debug("handle identity");

    X509Certificate rrnCertificate = getCertificate(message.rrnCertFile);
    X509Certificate rootCertificate = getCertificate(message.rootCertFile);
    List<X509Certificate> rrnCertificateChain = new LinkedList<X509Certificate>();
    rrnCertificateChain.add(rrnCertificate);
    rrnCertificateChain.add(rootCertificate);

    IdentificationEvent identificationEvent = new IdentificationEvent(rrnCertificateChain);
    BeIDContextQualifier contextQualifier = new BeIDContextQualifier(request);
    try {/*  w  w  w  .  j  a  va  2  s . co m*/
        this.identificationEvent.select(contextQualifier).fire(identificationEvent);
    } catch (ExpiredCertificateSecurityException e) {
        return new FinishedMessage(ErrorCode.CERTIFICATE_EXPIRED);
    } catch (RevokedCertificateSecurityException e) {
        return new FinishedMessage(ErrorCode.CERTIFICATE_REVOKED);
    } catch (TrustCertificateSecurityException e) {
        return new FinishedMessage(ErrorCode.CERTIFICATE_NOT_TRUSTED);
    } catch (CertificateSecurityException e) {
        return new FinishedMessage(ErrorCode.CERTIFICATE);
    }
    if (false == identificationEvent.isValid()) {
        SecurityAuditEvent securityAuditEvent = new SecurityAuditEvent(Incident.TRUST, rrnCertificate);
        this.securityAuditEvent.select(contextQualifier).fire(securityAuditEvent);
        throw new SecurityException("invalid national registry certificate chain");
    }

    verifySignature(contextQualifier, rrnCertificate.getSigAlgName(), message.identitySignatureFile,
            rrnCertificate, request, message.idFile);

    Identity identity = TlvParser.parse(message.idFile, Identity.class);

    if (null != message.photoFile) {
        LOG.debug("photo file size: " + message.photoFile.length);
        /*
         * Photo integrity check.
         */
        byte[] expectedPhotoDigest = identity.photoDigest;
        byte[] actualPhotoDigest = digestPhoto(getDigestAlgo(expectedPhotoDigest.length), message.photoFile);
        if (false == Arrays.equals(expectedPhotoDigest, actualPhotoDigest)) {
            SecurityAuditEvent securityAuditEvent = new SecurityAuditEvent(Incident.DATA_INTEGRITY,
                    message.photoFile);
            this.securityAuditEvent.select(contextQualifier).fire(securityAuditEvent);
            throw new ServletException("photo digest incorrect");
        }
    }

    Address address;
    if (null != message.addressFile) {
        byte[] addressFile = trimRight(message.addressFile);
        verifySignature(contextQualifier, rrnCertificate.getSigAlgName(), message.addressSignatureFile,
                rrnCertificate, request, addressFile, message.identitySignatureFile);
        address = TlvParser.parse(message.addressFile, Address.class);
    } else {
        address = null;
    }

    /*
     * Check the validity of the identity data as good as possible.
     */
    GregorianCalendar cardValidityDateEndGregorianCalendar = identity.getCardValidityDateEnd();
    if (null != cardValidityDateEndGregorianCalendar) {
        Date now = new Date();
        Date cardValidityDateEndDate = cardValidityDateEndGregorianCalendar.getTime();
        if (now.after(cardValidityDateEndDate)) {
            SecurityAuditEvent securityAuditEvent = new SecurityAuditEvent(Incident.DATA_INTEGRITY,
                    message.idFile);
            this.securityAuditEvent.select(contextQualifier).fire(securityAuditEvent);
            throw new SecurityException("eID card has expired");
        }
    }

    this.identityEvent.select(contextQualifier).fire(new IdentityEvent(identity, address, message.photoFile));
    return new FinishedMessage();
}

From source file:org.apache.geode.internal.cache.tier.sockets.HandShake.java

/**
 * This assumes that authentication is the last piece of info in handshake
 *//* www  .ja va 2  s . c om*/
public void writeCredentials(DataOutputStream dos, DataInputStream dis, Properties p_credentials,
        boolean isNotification, DistributedMember member, HeapDataOutputStream heapdos)
        throws IOException, GemFireSecurityException {

    if (p_credentials == null) {
        // No credentials indicator
        heapdos.writeByte(CREDENTIALS_NONE);
        heapdos.flush();
        dos.write(heapdos.toByteArray());
        dos.flush();
        return;
    }

    if (dhSKAlgo == null || dhSKAlgo.length() == 0) {
        // Normal credentials without encryption indicator
        heapdos.writeByte(CREDENTIALS_NORMAL);
        DataSerializer.writeProperties(p_credentials, heapdos);
        heapdos.flush();
        dos.write(heapdos.toByteArray());
        dos.flush();
        return;
    }

    try {
        InternalLogWriter securityLogWriter = (InternalLogWriter) this.system.getSecurityLogWriter();
        securityLogWriter.fine("HandShake: using Diffie-Hellman key exchange with algo " + dhSKAlgo);
        boolean requireAuthentication = (certificateFilePath != null && certificateFilePath.length() > 0);
        if (requireAuthentication) {
            securityLogWriter.fine("HandShake: server authentication using digital " + "signature required");
        }
        // Credentials with encryption indicator
        heapdos.writeByte(CREDENTIALS_DHENCRYPT);
        heapdos.writeBoolean(requireAuthentication);
        // Send the symmetric encryption algorithm name
        DataSerializer.writeString(dhSKAlgo, heapdos);
        // Send the DH public key
        byte[] keyBytes = dhPublicKey.getEncoded();
        DataSerializer.writeByteArray(keyBytes, heapdos);
        byte[] clientChallenge = null;
        if (requireAuthentication) {
            // Authentication of server should be with the client supplied
            // challenge
            clientChallenge = new byte[64];
            random.nextBytes(clientChallenge);
            DataSerializer.writeByteArray(clientChallenge, heapdos);
        }
        heapdos.flush();
        dos.write(heapdos.toByteArray());
        dos.flush();

        // Expect the alias and signature in the reply
        byte acceptanceCode = dis.readByte();
        if (acceptanceCode != REPLY_OK && acceptanceCode != REPLY_AUTH_NOT_REQUIRED) {
            // Ignore the useless data
            dis.readByte();
            dis.readInt();
            if (!isNotification) {
                DataSerializer.readByteArray(dis);
            }
            readMessage(dis, dos, acceptanceCode, member);
        } else if (acceptanceCode == REPLY_OK) {
            // Get the public key of the other side
            keyBytes = DataSerializer.readByteArray(dis);
            if (requireAuthentication) {
                String subject = DataSerializer.readString(dis);
                byte[] signatureBytes = DataSerializer.readByteArray(dis);
                if (!certificateMap.containsKey(subject)) {
                    throw new AuthenticationFailedException(
                            LocalizedStrings.HandShake_HANDSHAKE_FAILED_TO_FIND_PUBLIC_KEY_FOR_SERVER_WITH_SUBJECT_0
                                    .toLocalizedString(subject));
                }

                // Check the signature with the public key
                X509Certificate cert = (X509Certificate) certificateMap.get(subject);
                Signature sig = Signature.getInstance(cert.getSigAlgName());
                sig.initVerify(cert);
                sig.update(clientChallenge);
                // Check the challenge string
                if (!sig.verify(signatureBytes)) {
                    throw new AuthenticationFailedException(
                            "Mismatch in client " + "challenge bytes. Malicious server?");
                }
                securityLogWriter
                        .fine("HandShake: Successfully verified the " + "digital signature from server");
            }

            byte[] challenge = DataSerializer.readByteArray(dis);
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFact = KeyFactory.getInstance("DH");
            // PublicKey pubKey = keyFact.generatePublic(x509KeySpec);
            this.clientPublicKey = keyFact.generatePublic(x509KeySpec);

            HeapDataOutputStream hdos = new HeapDataOutputStream(Version.CURRENT);
            try {
                DataSerializer.writeProperties(p_credentials, hdos);
                // Also add the challenge string
                DataSerializer.writeByteArray(challenge, hdos);

                // byte[] encBytes = encrypt.doFinal(hdos.toByteArray());
                byte[] encBytes = encryptBytes(hdos.toByteArray(),
                        getEncryptCipher(dhSKAlgo, this.clientPublicKey));
                DataSerializer.writeByteArray(encBytes, dos);
            } finally {
                hdos.close();
            }
        }
    } catch (IOException ex) {
        throw ex;
    } catch (GemFireSecurityException ex) {
        throw ex;
    } catch (Exception ex) {
        throw new AuthenticationFailedException("HandShake failed in Diffie-Hellman key exchange", ex);
    }
    dos.flush();
}

From source file:org.apache.geode.internal.cache.tier.sockets.HandShake.java

/**
 * This method writes what readCredential() method expects to read. (Note the use of singular
 * credential). It is similar to writeCredentials(), except that it doesn't write
 * credential-properties.//ww w. java 2  s .c  o  m
 */
public byte writeCredential(DataOutputStream dos, DataInputStream dis, String authInit, boolean isNotification,
        DistributedMember member, HeapDataOutputStream heapdos) throws IOException, GemFireSecurityException {

    if (!this.multiuserSecureMode && (authInit == null || authInit.length() == 0)) {
        // No credentials indicator
        heapdos.writeByte(CREDENTIALS_NONE);
        heapdos.flush();
        dos.write(heapdos.toByteArray());
        dos.flush();
        return -1;
    }

    if (dhSKAlgo == null || dhSKAlgo.length() == 0) {
        // Normal credentials without encryption indicator
        heapdos.writeByte(CREDENTIALS_NORMAL);
        this.appSecureMode = CREDENTIALS_NORMAL;
        // DataSerializer.writeProperties(p_credentials, heapdos);
        heapdos.flush();
        dos.write(heapdos.toByteArray());
        dos.flush();
        return -1;
    }
    byte acceptanceCode = -1;
    try {
        InternalLogWriter securityLogWriter = (InternalLogWriter) this.system.getSecurityLogWriter();
        securityLogWriter.fine("HandShake: using Diffie-Hellman key exchange with algo " + dhSKAlgo);
        boolean requireAuthentication = (certificateFilePath != null && certificateFilePath.length() > 0);
        if (requireAuthentication) {
            securityLogWriter.fine("HandShake: server authentication using digital " + "signature required");
        }
        // Credentials with encryption indicator
        heapdos.writeByte(CREDENTIALS_DHENCRYPT);
        this.appSecureMode = CREDENTIALS_DHENCRYPT;
        heapdos.writeBoolean(requireAuthentication);
        // Send the symmetric encryption algorithm name
        DataSerializer.writeString(dhSKAlgo, heapdos);
        // Send the DH public key
        byte[] keyBytes = dhPublicKey.getEncoded();
        DataSerializer.writeByteArray(keyBytes, heapdos);
        byte[] clientChallenge = null;
        if (requireAuthentication) {
            // Authentication of server should be with the client supplied
            // challenge
            clientChallenge = new byte[64];
            random.nextBytes(clientChallenge);
            DataSerializer.writeByteArray(clientChallenge, heapdos);
        }
        heapdos.flush();
        dos.write(heapdos.toByteArray());
        dos.flush();

        // Expect the alias and signature in the reply
        acceptanceCode = dis.readByte();
        if (acceptanceCode != REPLY_OK && acceptanceCode != REPLY_AUTH_NOT_REQUIRED) {
            // Ignore the useless data
            dis.readByte();
            dis.readInt();
            if (!isNotification) {
                DataSerializer.readByteArray(dis);
            }
            readMessage(dis, dos, acceptanceCode, member);
        } else if (acceptanceCode == REPLY_OK) {
            // Get the public key of the other side
            keyBytes = DataSerializer.readByteArray(dis);
            if (requireAuthentication) {
                String subject = DataSerializer.readString(dis);
                byte[] signatureBytes = DataSerializer.readByteArray(dis);
                if (!certificateMap.containsKey(subject)) {
                    throw new AuthenticationFailedException(
                            LocalizedStrings.HandShake_HANDSHAKE_FAILED_TO_FIND_PUBLIC_KEY_FOR_SERVER_WITH_SUBJECT_0
                                    .toLocalizedString(subject));
                }

                // Check the signature with the public key
                X509Certificate cert = (X509Certificate) certificateMap.get(subject);
                Signature sig = Signature.getInstance(cert.getSigAlgName());
                sig.initVerify(cert);
                sig.update(clientChallenge);
                // Check the challenge string
                if (!sig.verify(signatureBytes)) {
                    throw new AuthenticationFailedException(
                            "Mismatch in client " + "challenge bytes. Malicious server?");
                }
                securityLogWriter
                        .fine("HandShake: Successfully verified the " + "digital signature from server");
            }

            // Read server challenge bytes
            byte[] serverChallenge = DataSerializer.readByteArray(dis);
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFact = KeyFactory.getInstance("DH");
            // PublicKey pubKey = keyFact.generatePublic(x509KeySpec);
            this.clientPublicKey = keyFact.generatePublic(x509KeySpec);

            HeapDataOutputStream hdos = new HeapDataOutputStream(Version.CURRENT);
            try {
                // Add the challenge string
                DataSerializer.writeByteArray(serverChallenge, hdos);
                // byte[] encBytes = encrypt.doFinal(hdos.toByteArray());
                byte[] encBytes = encryptBytes(hdos.toByteArray(),
                        getEncryptCipher(dhSKAlgo, this.clientPublicKey));
                DataSerializer.writeByteArray(encBytes, dos);
            } finally {
                hdos.close();
            }
        }
    } catch (IOException ex) {
        throw ex;
    } catch (GemFireSecurityException ex) {
        throw ex;
    } catch (Exception ex) {
        throw new AuthenticationFailedException("HandShake failed in Diffie-Hellman key exchange", ex);
    }
    dos.flush();
    return acceptanceCode;
}

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

/** Simple methods that returns the signature algorithm value from the certificate. Not usable for setting
 * signature algorithms names in EJBCA, only for human presentation.
 * //from w ww .j ava2  s  . c  o m
 * @return Signature algorithm from the certificate as a human readable string, for example SHA1WithRSA.
 */
public static String getCertSignatureAlgorithmAsString(Certificate cert) {
    String certSignatureAlgorithm = null;
    if (cert instanceof X509Certificate) {
        X509Certificate x509cert = (X509Certificate) cert;
        certSignatureAlgorithm = x509cert.getSigAlgName();
        if (log.isDebugEnabled()) {
            log.debug("certSignatureAlgorithm is: " + certSignatureAlgorithm);
        }
    } else if (StringUtils.equals(cert.getType(), "CVC")) {
        CardVerifiableCertificate cvccert = (CardVerifiableCertificate) cert;
        CVCPublicKey cvcpk;
        try {
            cvcpk = cvccert.getCVCertificate().getCertificateBody().getPublicKey();
            OIDField oid = cvcpk.getObjectIdentifier();
            certSignatureAlgorithm = AlgorithmUtil.getAlgorithmName(oid);
        } catch (NoSuchFieldException e) {
            log.error("NoSuchFieldException: ", e);
        }
    }
    // Try to make it easier to display some signature algorithms that cert.getSigAlgName() does not have a good string for.
    if (certSignatureAlgorithm.equalsIgnoreCase("1.2.840.113549.1.1.10")) {
        certSignatureAlgorithm = AlgorithmConstants.SIGALG_SHA256_WITH_RSA_AND_MGF1;
    }
    // SHA256WithECDSA does not work to be translated in JDK5.
    if (certSignatureAlgorithm.equalsIgnoreCase("1.2.840.10045.4.3.2")) {
        certSignatureAlgorithm = AlgorithmConstants.SIGALG_SHA256_WITH_ECDSA;
    }
    return certSignatureAlgorithm;
}

From source file:homenetapp.HomeNetAppGui.java

private void checkClientCert() {
    try {//from   w  w w. j av a2 s.  c o  m
        URL url = new URL("https://" + homenetapp.clientServer + "/");
        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
        conn.connect();
        Certificate[] certs = conn.getServerCertificates();

        //System.out.println("Cert Chain Length: "+certs.length);

        Certificate c = certs[0];
        X509Certificate xc = (X509Certificate) c;

        String[] from = homenetapp.splitTokens(xc.getIssuerX500Principal().getName(), "=, ");
        String[] to = homenetapp.splitTokens(xc.getSubjectX500Principal().getName(), "=, ");

        certPropertiesLabel.setText("<html>Issued by: " + from[1] + "<br>For: " + to[1] + "<br>Expires: "
                + xc.getNotAfter() + "</html>");

        System.out.println("Cert: " + c.getType());

        System.out.println("Not After: " + xc.getNotAfter());
        System.out.println("Subject DN: " + xc.getSubjectX500Principal());
        System.out.println("Issuer DN: " + xc.getIssuerX500Principal());
        System.out.println("getSigAlgName: " + xc.getSigAlgName());

    } catch (Exception e) {
        certPropertiesLabel.setText("Failed to load certficate");
    }

}

From source file:mitm.common.security.certificate.impl.StandardX509CertificateBuilderTest.java

@Test
public void testGenerateSelfSignedV3Certificate() throws Exception {
    X509CertificateBuilder certificateBuilder = new StandardX509CertificateBuilder("BC", "BC");

    KeyPairGenerator keyPairGenerator = securityFactory.createKeyPairGenerator("RSA");

    keyPairGenerator.initialize(2048, randomSource);

    KeyPair keyPair = keyPairGenerator.generateKeyPair();

    X500PrincipalBuilder issuerBuilder = new X500PrincipalBuilder();

    issuerBuilder.setCommonName("Martijn Brinkers");
    issuerBuilder.setCountryCode("NL");
    issuerBuilder.setEmail("test@example.com", "test2@example.com");
    issuerBuilder.setGivenName("Martijn");
    issuerBuilder.setSurname("Brinkers");
    issuerBuilder.setLocality("Amsterdam");
    issuerBuilder.setOrganisation("None");
    issuerBuilder.setState("NH");

    AltNamesBuilder altNamesBuider = new AltNamesBuilder();

    altNamesBuider.setRFC822Names("m.brinkers@pobox.com");
    altNamesBuider.setDNSNames("example.com");

    X500Principal issuer = issuerBuilder.buildPrincipal();
    GeneralNames altNames = altNamesBuider.buildAltNames();

    Set<KeyUsageType> keyUsage = new HashSet<KeyUsageType>();

    keyUsage.add(KeyUsageType.DIGITALSIGNATURE);
    keyUsage.add(KeyUsageType.KEYENCIPHERMENT);
    keyUsage.add(KeyUsageType.NONREPUDIATION);

    Set<ExtendedKeyUsageType> extendedKeyUsage = new HashSet<ExtendedKeyUsageType>();

    extendedKeyUsage.add(ExtendedKeyUsageType.CLIENTAUTH);
    extendedKeyUsage.add(ExtendedKeyUsageType.EMAILPROTECTION);

    Date notBefore = DateUtils.addHours(new Date(), -1);
    Date notAfter = DateUtils.addYears(new Date(), 10);

    certificateBuilder.setSubject(issuer);
    certificateBuilder.setIssuer(issuer);
    certificateBuilder.setAltNames(altNames, true);
    certificateBuilder.setKeyUsage(keyUsage, true);
    certificateBuilder.setExtendedKeyUsage(extendedKeyUsage, true);
    certificateBuilder.setNotBefore(notBefore);
    certificateBuilder.setNotAfter(notAfter);
    certificateBuilder.setPublicKey(keyPair.getPublic());
    certificateBuilder.setSerialNumber(new BigInteger("1"));
    certificateBuilder.setSignatureAlgorithm("SHA256WithRSA");
    certificateBuilder.setIsCA(true, true /* critical */);
    certificateBuilder.setPathLengthConstraint(5);

    Set<String> crlDistPoints = new HashSet<String>();
    crlDistPoints.add("http://example.com");
    crlDistPoints.add("123");

    certificateBuilder.setCRLDistributionPoints(crlDistPoints);

    X509Certificate certificate = certificateBuilder.generateCertificate(keyPair.getPrivate(), null);

    assertNotNull(certificate);// w  w w . j ava 2  s.co m

    File file = new File(tempDir, "testGenerateSelfSignedV3Certificate.cer");

    CertificateUtils.writeCertificate(certificate, file);

    X509CertificateInspector certInspector = new X509CertificateInspector(certificate);

    assertEquals(
            "EMAILADDRESS=test2@example.com, EMAILADDRESS=test@example.com, GIVENNAME=Martijn, "
                    + "SURNAME=Brinkers, CN=Martijn Brinkers, O=None, L=Amsterdam, ST=NH, C=NL",
            certInspector.getSubjectFriendly());

    assertEquals(certInspector.getIssuerFriendly(), certInspector.getSubjectFriendly());

    AltNamesInspector altNamesInspector = new AltNamesInspector(certificate.getSubjectAlternativeNames());

    List<String> rFC822Names = altNamesInspector.getRFC822Names();

    assertEquals(1, rFC822Names.size());
    assertEquals("m.brinkers@pobox.com", rFC822Names.get(0));

    List<String> dNSNames = altNamesInspector.getDNSNames();

    assertEquals(1, dNSNames.size());
    assertEquals("example.com", dNSNames.get(0));

    assertEquals(3, certInspector.getKeyUsage().size());
    assertTrue(certInspector.getKeyUsage().contains(KeyUsageType.DIGITALSIGNATURE));
    assertTrue(certInspector.getKeyUsage().contains(KeyUsageType.KEYENCIPHERMENT));
    assertTrue(certInspector.getKeyUsage().contains(KeyUsageType.NONREPUDIATION));

    assertEquals(2, certInspector.getExtendedKeyUsage().size());
    assertTrue(certInspector.getExtendedKeyUsage().contains(ExtendedKeyUsageType.CLIENTAUTH));
    assertTrue(certInspector.getExtendedKeyUsage().contains(ExtendedKeyUsageType.EMAILPROTECTION));

    // we cannot compare the dates because of encoding we loose some detail so check if within 1 sec
    assertTrue(Math.abs(notAfter.getTime() - certificate.getNotAfter().getTime()) < 1000);
    assertTrue(Math.abs(notBefore.getTime() - certificate.getNotBefore().getTime()) < 1000);

    assertEquals("1", certInspector.getSerialNumberHex());

    assertEquals("SHA256WITHRSA", certificate.getSigAlgName());

    assertTrue(certInspector.isCA());
    assertEquals(5, certInspector.getBasicConstraints().getPathLenConstraint().intValue());

    Set<String> crlDistPointsCert = CRLDistributionPointsInspector
            .getURIDistributionPointNames(certInspector.getCRLDistibutionPoints());

    assertTrue(crlDistPointsCert.contains("http://example.com"));
    assertTrue(crlDistPointsCert.contains("123"));
}

From source file:controller.CCInstance.java

public final boolean signPdf(final String pdfPath, final String destination, final CCSignatureSettings settings,
        final SignatureListener sl) throws CertificateException, IOException, DocumentException,
        KeyStoreException, SignatureFailedException, FileNotFoundException, NoSuchAlgorithmException,
        InvalidAlgorithmParameterException {
    PrivateKey pk;/*from  w ww  .  j ava 2  s . c om*/

    final PdfReader reader = new PdfReader(pdfPath);
    pk = getPrivateKeyFromAlias(settings.getCcAlias().getAlias());

    if (getCertificationLevel(pdfPath) == PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED) {
        String message = Bundle.getBundle().getString("fileDoesNotAllowChanges");
        if (sl != null) {
            sl.onSignatureComplete(pdfPath, false, message);
        }
        throw new SignatureFailedException(message);
    }

    if (reader.getNumberOfPages() - 1 < settings.getPageNumber()) {
        settings.setPageNumber(reader.getNumberOfPages() - 1);
    }

    if (null == pk) {
        String message = Bundle.getBundle().getString("noSmartcardFound");
        if (sl != null) {
            sl.onSignatureComplete(pdfPath, false, message);
        }
        throw new CertificateException(message);
    }

    if (null == pkcs11ks.getCertificateChain(settings.getCcAlias().getAlias())) {
        String message = Bundle.getBundle().getString("certificateNullChain");
        if (sl != null) {
            sl.onSignatureComplete(pdfPath, false, message);
        }
        throw new CertificateException(message);
    }
    final ArrayList<Certificate> embeddedCertificateChain = settings.getCcAlias().getCertificateChain();
    final Certificate owner = embeddedCertificateChain.get(0);
    final Certificate lastCert = embeddedCertificateChain.get(embeddedCertificateChain.size() - 1);

    if (null == owner) {
        String message = Bundle.getBundle().getString("certificateNameUnknown");
        if (sl != null) {
            sl.onSignatureComplete(pdfPath, false, message);
        }
        throw new CertificateException(message);
    }

    final X509Certificate X509C = ((X509Certificate) lastCert);
    final Calendar now = Calendar.getInstance();
    final Certificate[] filledMissingCertsFromChainInTrustedKeystore = getCompleteTrustedCertificateChain(
            X509C);

    final Certificate[] fullCertificateChain;
    if (filledMissingCertsFromChainInTrustedKeystore.length < 2) {
        fullCertificateChain = new Certificate[embeddedCertificateChain.size()];
        for (int i = 0; i < embeddedCertificateChain.size(); i++) {
            fullCertificateChain[i] = embeddedCertificateChain.get(i);
        }
    } else {
        fullCertificateChain = new Certificate[embeddedCertificateChain.size()
                + filledMissingCertsFromChainInTrustedKeystore.length - 1];
        int i = 0;
        for (i = 0; i < embeddedCertificateChain.size(); i++) {
            fullCertificateChain[i] = embeddedCertificateChain.get(i);
        }
        for (int f = 1; f < filledMissingCertsFromChainInTrustedKeystore.length; f++, i++) {
            fullCertificateChain[i] = filledMissingCertsFromChainInTrustedKeystore[f];
        }
    }

    // Leitor e Stamper
    FileOutputStream os = null;
    try {
        os = new FileOutputStream(destination);
    } catch (FileNotFoundException e) {
        String message = Bundle.getBundle().getString("outputFileError");
        if (sl != null) {
            sl.onSignatureComplete(pdfPath, false, message);
        }
        throw new IOException(message);
    }

    // Aparncia da Assinatura
    final char pdfVersion;
    switch (Settings.getSettings().getPdfVersion()) {
    case "/1.2":
        pdfVersion = PdfWriter.VERSION_1_2;
        break;
    case "/1.3":
        pdfVersion = PdfWriter.VERSION_1_3;
        break;
    case "/1.4":
        pdfVersion = PdfWriter.VERSION_1_4;
        break;
    case "/1.5":
        pdfVersion = PdfWriter.VERSION_1_5;
        break;
    case "/1.6":
        pdfVersion = PdfWriter.VERSION_1_6;
        break;
    case "/1.7":
        pdfVersion = PdfWriter.VERSION_1_7;
        break;
    default:
        pdfVersion = PdfWriter.VERSION_1_7;
    }

    final PdfStamper stamper = (getNumberOfSignatures(pdfPath) == 0
            ? PdfStamper.createSignature(reader, os, pdfVersion)
            : PdfStamper.createSignature(reader, os, pdfVersion, null, true));

    final PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
    appearance.setSignDate(now);
    appearance.setReason(settings.getReason());
    appearance.setLocation(settings.getLocation());
    appearance.setCertificationLevel(settings.getCertificationLevel());
    appearance.setSignatureCreator(SIGNATURE_CREATOR);
    appearance.setCertificate(owner);

    final String fieldName = settings.getPrefix() + " " + (1 + getNumberOfSignatures(pdfPath));
    if (settings.isVisibleSignature()) {
        appearance.setVisibleSignature(settings.getPositionOnDocument(), settings.getPageNumber() + 1,
                fieldName);
        appearance.setRenderingMode(PdfSignatureAppearance.RenderingMode.DESCRIPTION);
        if (null != settings.getAppearance().getImageLocation()) {
            appearance.setImage(Image.getInstance(settings.getAppearance().getImageLocation()));
        }

        com.itextpdf.text.Font font = new com.itextpdf.text.Font(FontFactory
                .getFont(settings.getAppearance().getFontLocation(), BaseFont.IDENTITY_H, BaseFont.EMBEDDED, 0)
                .getBaseFont());

        font.setColor(new BaseColor(settings.getAppearance().getFontColor().getRGB()));
        if (settings.getAppearance().isBold() && settings.getAppearance().isItalic()) {
            font.setStyle(Font.BOLD + Font.ITALIC);
        } else if (settings.getAppearance().isBold()) {
            font.setStyle(Font.BOLD);
        } else if (settings.getAppearance().isItalic()) {
            font.setStyle(Font.ITALIC);
        } else {
            font.setStyle(Font.PLAIN);
        }

        appearance.setLayer2Font(font);
        String text = "";
        if (settings.getAppearance().isShowName()) {
            if (!settings.getCcAlias().getName().isEmpty()) {
                text += settings.getCcAlias().getName() + "\n";
            }
        }
        if (settings.getAppearance().isShowReason()) {
            if (!settings.getReason().isEmpty()) {
                text += settings.getReason() + "\n";
            }
        }
        if (settings.getAppearance().isShowLocation()) {
            if (!settings.getLocation().isEmpty()) {
                text += settings.getLocation() + "\n";
            }
        }
        if (settings.getAppearance().isShowDate()) {
            DateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
            SimpleDateFormat sdf = new SimpleDateFormat("Z");
            text += df.format(now.getTime()) + " " + sdf.format(now.getTime()) + "\n";
        }
        if (!settings.getText().isEmpty()) {
            text += settings.getText();
        }

        PdfTemplate layer2 = appearance.getLayer(2);
        Rectangle rect = settings.getPositionOnDocument();
        Rectangle sr = new Rectangle(rect.getWidth(), rect.getHeight());
        float size = ColumnText.fitText(font, text, sr, 1024, PdfWriter.RUN_DIRECTION_DEFAULT);
        ColumnText ct = new ColumnText(layer2);
        ct.setRunDirection(PdfWriter.RUN_DIRECTION_DEFAULT);
        ct.setAlignment(Element.ALIGN_MIDDLE);
        int align;
        switch (settings.getAppearance().getAlign()) {
        case 0:
            align = Element.ALIGN_LEFT;
            break;
        case 1:
            align = Element.ALIGN_CENTER;
            break;
        case 2:
            align = Element.ALIGN_RIGHT;
            break;
        default:
            align = Element.ALIGN_LEFT;
        }

        ct.setSimpleColumn(new Phrase(text, font), sr.getLeft(), sr.getBottom(), sr.getRight(), sr.getTop(),
                size, align);
        ct.go();
    } else {
        appearance.setVisibleSignature(new Rectangle(0, 0, 0, 0), 1, fieldName);
    }

    // CRL <- Pesado!
    final ArrayList<CrlClient> crlList = null;

    // OCSP
    OcspClient ocspClient = new OcspClientBouncyCastle();

    // TimeStamp
    TSAClient tsaClient = null;
    if (settings.isTimestamp()) {
        tsaClient = new TSAClientBouncyCastle(settings.getTimestampServer(), null, null);
    }

    final String hashAlg = getHashAlgorithm(X509C.getSigAlgName());

    final ExternalSignature es = new PrivateKeySignature(pk, hashAlg, pkcs11Provider.getName());
    final ExternalDigest digest = new ProviderDigest(pkcs11Provider.getName());

    try {
        MakeSignature.signDetached(appearance, digest, es, fullCertificateChain, crlList, ocspClient, tsaClient,
                0, MakeSignature.CryptoStandard.CMS);
        if (sl != null) {
            sl.onSignatureComplete(pdfPath, true, "");
        }
        return true;
    } catch (Exception e) {
        os.flush();
        os.close();
        new File(destination).delete();
        if ("sun.security.pkcs11.wrapper.PKCS11Exception: CKR_FUNCTION_CANCELED".equals(e.getMessage())) {
            throw new SignatureFailedException(Bundle.getBundle().getString("userCanceled"));
        } else if ("sun.security.pkcs11.wrapper.PKCS11Exception: CKR_GENERAL_ERROR".equals(e.getMessage())) {
            throw new SignatureFailedException(Bundle.getBundle().getString("noPermissions"));
        } else if (e instanceof ExceptionConverter) {
            String message = Bundle.getBundle().getString("timestampFailed");
            if (sl != null) {
                sl.onSignatureComplete(pdfPath, false, message);
            }
            throw new SignatureFailedException(message);
        } else {
            if (sl != null) {
                sl.onSignatureComplete(pdfPath, false, Bundle.getBundle().getString("unknownErrorLog"));
            }
            controller.Logger.getLogger().addEntry(e);
        }
        return false;
    }
}