Example usage for org.bouncycastle.cms SignerInformationStore size

List of usage examples for org.bouncycastle.cms SignerInformationStore size

Introduction

In this page you can find the example usage for org.bouncycastle.cms SignerInformationStore size.

Prototype

public int size() 

Source Link

Document

Return the number of signers in the collection.

Usage

From source file:it.trento.comune.j4sign.verification.VerifyResult.java

License:Open Source License

private void initCountersignatures(Store certs, CMSSignedData cm, CertificationAuthorities roots,
        SignerInformation parentSigner, boolean isDownloadCRLForced) {

    SignerInformationStore cs = parentSigner.getCounterSignatures();
    if (cs.size() > 0) {

        risultatiCs = new Hashtable<X500Principal, VerifyResult>();

        log.info("detected " + cs.size() + " countersignatures for " + cert.getSubjectX500Principal());

        Iterator<SignerInformation> csIterator = cs.getSigners().iterator();

        while (csIterator.hasNext()) {
            SignerInformation counterSigner = csIterator.next();
            Collection cc = null;
            try {
                cc = certs.getMatches(counterSigner.getSID());

            } catch (StoreException ex1) {
                log.severe("Errore nel CertStore");
                // errors.add("Errore nel CertStore");
            }//w  ww .  j a v  a2 s.  c  o m

            if (cc.size() == 1) {

                X509CertificateHolder ch = (X509CertificateHolder) cc.toArray()[0];

                // get Certificate
                X509Certificate c;
                try {
                    c = new JcaX509CertificateConverter().setProvider("BC").getCertificate(ch);

                    log.info("CounterSigner CN: " + Verifier.getCommonName(c));

                    VerifyResult vr = new VerifyResult(conf, certs, c, cm, roots, counterSigner, true,
                            this.crlDownloadForced, this.checkQCStatements, this.crlDir);

                    risultatiCs.put(c.getSubjectX500Principal(), vr);

                } catch (CertificateException e) {
                    log.severe(
                            "Errore nell'estrazione del certificato del controfirmatario: " + e.getMessage());
                }

            }

        }
    }
}

From source file:org.demoiselle.signer.policy.impl.cades.pkcs7.impl.CAdESChecker.java

License:Open Source License

/**
 * Validation is done only on digital signatures with a single signer. Valid
 * only with content of type DATA.: OID ContentType 1.2.840.113549.1.9.3 =
 * OID Data 1.2.840.113549.1.7.1//w ww .  j  a v a2s  .  com
 *
 * @param content Is only necessary to inform if the PKCS7 package is NOT
 *        ATTACHED type. If it is of type attached, this parameter will be
 *        replaced by the contents of the PKCS7 package.
 * @param signedData Value in bytes of the PKCS7 package, such as the
 *        contents of a ".p7s" file. It is not only signature as in the
 *        case of PKCS1.
 */
// TODO: Implementar validao de co-assinaturas

public boolean check(byte[] content, byte[] signedData) throws SignerException {
    Security.addProvider(new BouncyCastleProvider());
    CMSSignedData cmsSignedData = null;
    try {
        if (content == null) {
            if (this.checkHash) {
                cmsSignedData = new CMSSignedData(this.hashes, signedData);
                this.checkHash = false;
            } else {
                cmsSignedData = new CMSSignedData(signedData);
            }

        } else {
            if (this.getAttached(signedData, false) != null) {
                cmsSignedData = new CMSSignedData(signedData);
            } else {
                cmsSignedData = new CMSSignedData(new CMSProcessableByteArray(content), signedData);
            }

        }
    } catch (CMSException ex) {
        throw new SignerException(cadesMessagesBundle.getString("error.invalid.bytes.pkcs7"), ex);
    }

    // Quantidade inicial de assinaturas validadas
    int verified = 0;

    Store<?> certStore = cmsSignedData.getCertificates();
    SignerInformationStore signers = cmsSignedData.getSignerInfos();
    Iterator<?> it = signers.getSigners().iterator();

    // Realizao da verificao bsica de todas as assinaturas
    while (it.hasNext()) {
        SignatureInformations signatureInfo = new SignatureInformations();
        try {
            SignerInformation signerInfo = (SignerInformation) it.next();
            SignerInformationStore signerInfoStore = signerInfo.getCounterSignatures();

            logger.info("Foi(ram) encontrada(s) " + signerInfoStore.size() + " contra-assinatura(s).");

            @SuppressWarnings("unchecked")
            Collection<?> certCollection = certStore.getMatches(signerInfo.getSID());

            Iterator<?> certIt = certCollection.iterator();
            X509CertificateHolder certificateHolder = (X509CertificateHolder) certIt.next();

            X509Certificate varCert = new JcaX509CertificateConverter().getCertificate(certificateHolder);

            CRLValidator cV = new CRLValidator();
            try {
                cV.validate(varCert);
            } catch (CertificateValidatorCRLException cvce) {
                signatureInfo.getValidatorErrors().add(cvce.getMessage());
                logger.info(cvce.getMessage());
            } catch (CertificateRevocationException cre) {
                signatureInfo.getValidatorErrors().add(cre.getMessage());
                logger.info("certificado revogado");
            }

            PeriodValidator pV = new PeriodValidator();
            try {
                pV.validate(varCert);

            } catch (CertificateValidatorException cve) {
                signatureInfo.getValidatorErrors().add(cve.getMessage());
            }

            if (signerInfo.verify(
                    new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(certificateHolder))) {
                verified++;
                logger.info(cadesMessagesBundle.getString("info.signature.valid.seq", verified));
            }

            // recupera atributos assinados
            logger.info(cadesMessagesBundle.getString("info.signed.attribute"));
            String varOIDPolicy = PKCSObjectIdentifiers.id_aa_ets_sigPolicyId.getId();
            AttributeTable signedAttributes = signerInfo.getSignedAttributes();
            if ((signedAttributes == null) || (signedAttributes != null && signedAttributes.size() == 0)) {
                signatureInfo.getValidatorErrors()
                        .add(cadesMessagesBundle.getString("error.signed.attribute.table.not.found"));
                logger.info(cadesMessagesBundle.getString("error.signed.attribute.table.not.found"));
                //throw new SignerException(cadesMessagesBundle.getString("error.signed.attribute.table.not.found"));
            } else {
                //Validando atributos assinados de acordo com a politica
                Attribute idSigningPolicy = null;
                idSigningPolicy = signedAttributes.get(new ASN1ObjectIdentifier(varOIDPolicy));
                if (idSigningPolicy == null) {
                    signatureInfo.getValidatorErrors().add(
                            cadesMessagesBundle.getString("error.pcks7.attribute.not.found", varOIDPolicy));
                } else {
                    for (Enumeration<?> p = idSigningPolicy.getAttrValues().getObjects(); p
                            .hasMoreElements();) {
                        String policyOnSignature = p.nextElement().toString();
                        for (PolicyFactory.Policies pv : PolicyFactory.Policies.values()) {
                            if (policyOnSignature.contains(pv.getUrl())) {
                                setSignaturePolicy(pv);
                                break;
                            }
                        }
                    }
                }
            }
            Date dataHora = null;
            if (signedAttributes != null) {
                // Valida o atributo ContentType
                Attribute attributeContentType = signedAttributes.get(CMSAttributes.contentType);
                if (attributeContentType == null) {
                    signatureInfo.getValidatorErrors().add(
                            cadesMessagesBundle.getString("error.pcks7.attribute.not.found", "ContentType"));
                    //throw new SignerException(cadesMessagesBundle.getString("error.pcks7.attribute.not.found", "ContentType"));
                    logger.info(
                            cadesMessagesBundle.getString("error.pcks7.attribute.not.found", "ContentType"));
                }

                if (!attributeContentType.getAttrValues().getObjectAt(0).equals(ContentInfo.data)) {
                    signatureInfo.getValidatorErrors()
                            .add(cadesMessagesBundle.getString("error.content.not.data"));
                    //throw new SignerException(cadesMessagesBundle.getString("error.content.not.data"));
                    logger.info(cadesMessagesBundle.getString("error.content.not.data"));
                }

                // Validando o atributo MessageDigest
                Attribute attributeMessageDigest = signedAttributes.get(CMSAttributes.messageDigest);
                if (attributeMessageDigest == null) {
                    throw new SignerException(
                            cadesMessagesBundle.getString("error.pcks7.attribute.not.found", "MessageDigest"));
                }
                // Mostra data e  hora da assinatura, no  carimbo de tempo
                Attribute timeAttribute = signedAttributes.get(CMSAttributes.signingTime);

                if (timeAttribute != null) {
                    dataHora = (((ASN1UTCTime) timeAttribute.getAttrValues().getObjectAt(0)).getDate());
                    logger.info(cadesMessagesBundle.getString("info.date.utc", dataHora));
                } else {
                    logger.info(cadesMessagesBundle.getString("info.date.utc", "N/D"));
                }

            }

            if (signaturePolicy == null) {
                signatureInfo.getValidatorErrors().add(
                        cadesMessagesBundle.getString("error.policy.on.component.not.found", varOIDPolicy));
                logger.info(cadesMessagesBundle.getString("error.policy.on.component.not.found"));
            } else {
                if (signaturePolicy.getSignPolicyInfo().getSignatureValidationPolicy().getCommonRules()
                        .getSignerAndVeriferRules().getSignerRules().getMandatedSignedAttr()
                        .getObjectIdentifiers() != null) {
                    for (ObjectIdentifier objectIdentifier : signaturePolicy.getSignPolicyInfo()
                            .getSignatureValidationPolicy().getCommonRules().getSignerAndVeriferRules()
                            .getSignerRules().getMandatedSignedAttr().getObjectIdentifiers()) {
                        String oi = objectIdentifier.getValue();
                        Attribute signedAtt = signedAttributes.get(new ASN1ObjectIdentifier(oi));
                        logger.info(oi);
                        if (signedAtt == null) {
                            signatureInfo.getValidatorErrors().add(cadesMessagesBundle.getString(
                                    "error.signed.attribute.not.found", oi,
                                    signaturePolicy.getSignPolicyInfo().getSignPolicyIdentifier().getValue()));
                        }
                    }
                }
            }

            // recupera os atributos NO assinados
            logger.info(cadesMessagesBundle.getString("info.unsigned.attribute"));
            AttributeTable unsignedAttributes = signerInfo.getUnsignedAttributes();
            if ((unsignedAttributes == null)
                    || (unsignedAttributes != null && unsignedAttributes.size() == 0)) {
                // Apenas info pois a RB no tem atributos no assinados
                logger.info(cadesMessagesBundle.getString("error.unsigned.attribute.table.not.found"));
            }
            if (signaturePolicy != null) {
                // Validando atributos NO assinados de acordo com a politica
                if (signaturePolicy.getSignPolicyInfo().getSignatureValidationPolicy().getCommonRules()
                        .getSignerAndVeriferRules().getSignerRules().getMandatedUnsignedAttr()
                        .getObjectIdentifiers() != null) {
                    for (ObjectIdentifier objectIdentifier : signaturePolicy.getSignPolicyInfo()
                            .getSignatureValidationPolicy().getCommonRules().getSignerAndVeriferRules()
                            .getSignerRules().getMandatedUnsignedAttr().getObjectIdentifiers()) {
                        String oi = objectIdentifier.getValue();
                        Attribute unSignedAtt = unsignedAttributes.get(new ASN1ObjectIdentifier(oi));
                        logger.info(oi);
                        if (unSignedAtt == null) {
                            signatureInfo.getValidatorErrors().add(cadesMessagesBundle.getString(
                                    "error.unsigned.attribute.not.found", oi,
                                    signaturePolicy.getSignPolicyInfo().getSignPolicyIdentifier().getValue()));
                        }
                        if (oi.equalsIgnoreCase(PKCSObjectIdentifiers.id_aa_signatureTimeStampToken.getId())) {
                            //Verificando timeStamp
                            try {
                                byte[] varSignature = signerInfo.getSignature();
                                Timestamp varTimeStampSigner = validateTimestamp(unSignedAtt, varSignature);
                                signatureInfo.setTimeStampSigner(varTimeStampSigner);
                            } catch (Exception ex) {
                                signatureInfo.getValidatorErrors().add(ex.getMessage());
                                // nas assinaturas feitas na applet o unsignedAttributes.get gera exceo.                  
                            }
                        }
                        if (oi.equalsIgnoreCase("1.2.840.113549.1.9.16.2.25")) {
                            logger.info("++++++++++  EscTimeStamp ++++++++++++");
                        }
                    }
                }
            }

            LinkedList<X509Certificate> varChain = (LinkedList<X509Certificate>) CAManager.getInstance()
                    .getCertificateChain(varCert);
            if (varChain.size() < 3) {
                signatureInfo.getValidatorErrors()
                        .add(cadesMessagesBundle.getString("error.no.ca", varCert.getIssuerDN()));
                logger.info(cadesMessagesBundle.getString("error.no.ca", varCert.getIssuerDN()));
            }
            signatureInfo.setSignDate(dataHora);
            signatureInfo.setChain(varChain);
            signatureInfo.setSignaturePolicy(signaturePolicy);
            this.getSignaturesInfo().add(signatureInfo);

        } catch (OperatorCreationException | java.security.cert.CertificateException ex) {
            signatureInfo.getValidatorErrors().add(ex.getMessage());
            logger.info(ex.getMessage());
        } catch (CMSException ex) {
            // When file is mismatch with sign
            if (ex instanceof CMSSignerDigestMismatchException) {
                signatureInfo.getValidatorErrors()
                        .add(cadesMessagesBundle.getString("error.signature.mismatch"));
                logger.info(cadesMessagesBundle.getString("error.signature.mismatch"));
                throw new SignerException(cadesMessagesBundle.getString("error.signature.mismatch"), ex);
            } else {
                signatureInfo.getValidatorErrors()
                        .add(cadesMessagesBundle.getString("error.signature.invalid"));
                logger.info(cadesMessagesBundle.getString("error.signature.invalid"));
                throw new SignerException(cadesMessagesBundle.getString("error.signature.invalid"), ex);
            }
        } catch (ParseException e) {
            signatureInfo.getValidatorErrors().add(e.getMessage());
            logger.info(e.getMessage());
        }
    }
    logger.info(cadesMessagesBundle.getString("info.signature.verified", verified));
    // TODO Efetuar o parsing da estrutura CMS
    return true;
}

From source file:org.demoiselle.signer.policy.impl.cades.pkcs7.impl.CAdESSigner.java

License:Open Source License

/**
 * Validation is done only on digital signatures with a single signer. Valid
 * only with content of type DATA.: OID ContentType 1.2.840.113549.1.9.3 =
 * OID Data 1.2.840.113549.1.7.1/* www . j  a v a  2s  .c  o  m*/
 *
 * @param content Is only necessary to inform if the PKCS7 package is NOT
 *        ATTACHED type. If it is of type attached, this parameter will be
 *        replaced by the contents of the PKCS7 package.
 * @param signedData Value in bytes of the PKCS7 package, such as the
 *        contents of a ".p7s" file. It is not only signature as in the
 *        case of PKCS1.
 * @deprecated moved to CadESChecker
 */
@SuppressWarnings("unchecked")
@Override

public boolean check(byte[] content, byte[] signedData) throws SignerException {
    Security.addProvider(new BouncyCastleProvider());
    CMSSignedData cmsSignedData = null;
    try {
        if (content == null) {
            if (this.checkHash) {
                cmsSignedData = new CMSSignedData(this.hashes, signedData);
                this.checkHash = false;
            } else {
                cmsSignedData = new CMSSignedData(signedData);
            }

        } else {
            cmsSignedData = new CMSSignedData(new CMSProcessableByteArray(content), signedData);
        }
    } catch (CMSException ex) {
        throw new SignerException(cadesMessagesBundle.getString("error.invalid.bytes.pkcs7"), ex);
    }

    // Quantidade inicial de assinaturas validadas
    int verified = 0;

    Store<?> certStore = cmsSignedData.getCertificates();
    SignerInformationStore signers = cmsSignedData.getSignerInfos();
    Iterator<?> it = signers.getSigners().iterator();

    // Realizao da verificao bsica de todas as assinaturas
    while (it.hasNext()) {
        try {
            SignerInformation signer = (SignerInformation) it.next();
            SignerInformationStore s = signer.getCounterSignatures();
            SignatureInformations si = new SignatureInformations();
            logger.info("Foi(ram) encontrada(s) " + s.size() + " contra-assinatura(s).");

            Collection<?> certCollection = certStore.getMatches(signer.getSID());

            Iterator<?> certIt = certCollection.iterator();
            X509CertificateHolder certificateHolder = (X509CertificateHolder) certIt.next();

            X509Certificate varCert = new JcaX509CertificateConverter().getCertificate(certificateHolder);
            PeriodValidator pV = new PeriodValidator();
            try {
                pV.validate(varCert);

            } catch (CertificateValidatorException cve) {
                si.getValidatorErrors().add(cve.getMessage());
            }

            CRLValidator cV = new CRLValidator();
            try {
                cV.validate(varCert);
            } catch (CertificateValidatorCRLException cvce) {
                si.getValidatorErrors().add(cvce.getMessage());
            }

            if (signer.verify(
                    new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(certificateHolder))) {
                verified++;
                logger.info(cadesMessagesBundle.getString("info.signature.valid.seq", verified));
            }

            // Realiza a verificao dos atributos assinados
            logger.info(cadesMessagesBundle.getString("info.signed.attribute"));
            AttributeTable signedAttributes = signer.getSignedAttributes();
            if ((signedAttributes == null) || (signedAttributes != null && signedAttributes.size() == 0)) {
                throw new SignerException(
                        cadesMessagesBundle.getString("error.signed.attribute.table.not.found"));
            }

            // Realiza a verificao dos atributos no assinados
            logger.info(cadesMessagesBundle.getString("info.unsigned.attribute"));
            AttributeTable unsignedAttributes = signer.getUnsignedAttributes();
            if ((unsignedAttributes == null)
                    || (unsignedAttributes != null && unsignedAttributes.size() == 0)) {
                logger.info(cadesMessagesBundle.getString("error.unsigned.attribute.table.not.found"));
            }

            // Mostra data e  hora da assinatura, no  carimbo de tempo
            Attribute signingTime = signedAttributes.get(CMSAttributes.signingTime);
            Date dataHora = null;
            if (signingTime != null) {
                dataHora = (((ASN1UTCTime) signingTime.getAttrValues().getObjectAt(0)).getDate());
                logger.info(cadesMessagesBundle.getString("info.date.utc", dataHora));
            } else {
                logger.info(cadesMessagesBundle.getString("info.date.utc", "N/D"));
            }

            logger.info(cadesMessagesBundle.getString("info.attribute.validation"));
            // Valida o atributo ContentType
            Attribute attributeContentType = signedAttributes.get(CMSAttributes.contentType);
            if (attributeContentType == null) {
                throw new SignerException(
                        cadesMessagesBundle.getString("error.pcks7.attribute.not.found", "ContentType"));
            }

            if (!attributeContentType.getAttrValues().getObjectAt(0).equals(ContentInfo.data)) {
                throw new SignerException(cadesMessagesBundle.getString("error.content.not.data"));
            }

            // Validando o atributo MessageDigest
            Attribute attributeMessageDigest = signedAttributes.get(CMSAttributes.messageDigest);
            if (attributeMessageDigest == null) {
                throw new SignerException(
                        cadesMessagesBundle.getString("error.pcks7.attribute.not.found", "MessageDigest"));
            }

            // Validando o atributo MessageDigest
            Attribute idSigningPolicy = null;
            idSigningPolicy = signedAttributes
                    .get(new ASN1ObjectIdentifier(PKCSObjectIdentifiers.id_aa_ets_sigPolicyId.getId()));
            if (idSigningPolicy == null) {
                throw new SignerException(
                        cadesMessagesBundle.getString("error.pcks7.attribute.not.found", "idSigningPolicy"));
            }

            //Verificando timeStamp
            try {
                Attribute attributeTimeStamp = null;
                attributeTimeStamp = unsignedAttributes.get(
                        new ASN1ObjectIdentifier(PKCSObjectIdentifiers.id_aa_signatureTimeStampToken.getId()));
                if (attributeTimeStamp != null) {
                    byte[] varSignature = signer.getSignature();
                    Timestamp varTimeStampSigner = validateTimestamp(attributeTimeStamp, varSignature);
                    si.setTimeStampSigner(varTimeStampSigner);
                }
            } catch (Exception ex) {
                // nas assinaturas feitas na applet o unsignedAttributes.get gera exceo.                  
            }

            LinkedList<X509Certificate> varChain = (LinkedList<X509Certificate>) CAManager.getInstance()
                    .getCertificateChain(varCert);
            si.setSignDate(dataHora);
            si.setChain(varChain);
            si.setSignaturePolicy(signaturePolicy);
            this.getSignatureInfo().add(si);

        } catch (OperatorCreationException | java.security.cert.CertificateException ex) {
            throw new SignerException(ex);
        } catch (CMSException ex) {
            // When file is mismatch with sign
            if (ex instanceof CMSSignerDigestMismatchException)
                throw new SignerException(cadesMessagesBundle.getString("error.signature.mismatch"), ex);
            else
                throw new SignerException(cadesMessagesBundle.getString("error.signature.invalid"), ex);
        } catch (ParseException e) {
            throw new SignerException(e);
        }
    }

    logger.info(cadesMessagesBundle.getString("info.signature.verified", verified));
    // TODO Efetuar o parsing da estrutura CMS
    return true;
}

From source file:org.votingsystem.signature.smime.SMIMESignedValidator.java

License:Open Source License

/**
 * verify that the sig is correct and that it was generated when the 
 * certificate was current(assuming the cert is contained in the message).
 *///from w w  w . j  a  v a  2s  . com
public static boolean isValidSignature(SMIMESigned smimeSigned) throws Exception {
    // certificates and crls passed in the signature
    Store certs = smimeSigned.getCertificates();
    // SignerInfo blocks which contain the signatures
    SignerInformationStore signers = smimeSigned.getSignerInfos();
    log.info("signers.size(): " + signers.size());
    Collection c = signers.getSigners();
    Iterator it = c.iterator();
    boolean result = false;
    // check each signer
    while (it.hasNext()) {
        SignerInformation signer = (SignerInformation) it.next();
        Collection certCollection = certs.getMatches(signer.getSID());
        log.info("Collection matches: " + certCollection.size());
        Iterator certIt = certCollection.iterator();
        X509Certificate cert = new JcaX509CertificateConverter().setProvider(ContextVS.PROVIDER)
                .getCertificate((X509CertificateHolder) certIt.next());
        log.info("SubjectDN: " + cert.getSubjectDN() + " - Not before: " + cert.getNotBefore()
                + " - Not after: " + cert.getNotAfter() + " - SigningTime: " + getSigningTime(signer));
        if (signer
                .verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(ContextVS.PROVIDER).build(cert))) {
            log.info("signature verified");
            result = true;
        } else {
            log.info("signature failed!");
            result = false;
        }
    }
    return result;
}

From source file:test.unit.be.e_contract.mycarenet.etee.EncryptionTokenTest.java

License:Open Source License

@Test
public void testReadEncryptionToken() throws Exception {
    InputStream etkInputStream = EncryptionTokenTest.class.getResourceAsStream("/etk-fcorneli.der");
    assertNotNull(etkInputStream);/*from   ww  w .j  a v a2  s  .  c o  m*/

    CMSSignedData cmsSignedData = new CMSSignedData(etkInputStream);
    LOG.debug("SignedData version: " + cmsSignedData.getVersion());

    SignerInformationStore signers = cmsSignedData.getSignerInfos();
    LOG.debug("signers: " + signers.size());
    SignerInformation signer = (SignerInformation) signers.getSigners().iterator().next();
    SignerId signerId = signer.getSID();
    LOG.debug("signer Id: " + signerId.getIssuer());

    Store certificateStore = cmsSignedData.getCertificates();
    @SuppressWarnings("unchecked")
    Collection<X509CertificateHolder> certificateCollection = certificateStore.getMatches(signerId);
    X509CertificateHolder certificateHolder = certificateCollection.iterator().next();

    LOG.debug("certificate collection size: " + certificateCollection.size());

    CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
    X509Certificate certificate = (X509Certificate) certificateFactory
            .generateCertificate(new ByteArrayInputStream(certificateHolder.getEncoded()));
    LOG.debug("signer certificate: " + certificate);

    CMSTypedData signedContent = cmsSignedData.getSignedContent();
    byte[] data = (byte[]) signedContent.getContent();

    X509Certificate encryptionCertificate = (X509Certificate) certificateFactory
            .generateCertificate(new ByteArrayInputStream(data));
    LOG.debug("encryption certificate: " + encryptionCertificate);
}