Menu

Carga de archivos de certificados

2024-06-25
2024-07-01
  • Leon Sanchez

    Leon Sanchez - 2024-06-25

    Hola estoy implementando en mi proyecto la carga de certificados utilizando estas anotaciones : @File, @Column, private Strigng archivoCer; y poder extraer datos del certificado, pero obtengo error , pero al hacer la extraccion tengo error de incompatibilidad ya que lo hago mediante bytes, pueden ayudarme sobre esto porfavor

     
  • Javier Paniza

    Javier Paniza - 2024-06-27

    Hola Leon:

    Pon el código de tu entidad y todo el resto de código relacionado con el tema, como acciones o cualquier otra cosa. Incluye también la traza completa de la excepción.


    Ayuda a otros en este foro como yo te ayudo a ti.

     
  • Leon Sanchez

    Leon Sanchez - 2024-06-27

    Hola,
    Inicialmente implemente este código y verifique que si se almacenen dentro de la base de datos, y efectivamente si se almacena al igual se almacena en la tabla por default oxfiles, pero lo que me muestra en la tabla en la que indico donde se debe almacenar es 'datos_csd' me almacena un referencia de esta tabla oxfiles a mi tabla 'datos_csd', entonces no me permite acceder directamente a los bytes.
    @Entity
    @Table(name = "datos_csd")
    public class Certificado {
    @File
    @Column(length = 100)
    @OnChange(ExtraerDatosCertificadoAction.class)
    private String archivoCer;

    @File
    @Column (length = 32)
    private String archivoKey;
    
    @Stereotype("PASSWORD")
    @Column(length = 100)
    private String password;
    
    /************ METODOS DE LAS VARIABLES *************/
    public String getArchivoCer() {
        return archivoCer;
    }
    
    public void setArchivoCer(String archivoCer) {
        this.archivoCer = archivoCer;
        //procesarCertificado(); // Llamada al método aquí
    }
    
    private void procesarCertificado() {
        try {
            byte[] decodedBytes = getArchivoCerBytes();
            if (decodedBytes != null && decodedBytes.length > 0) {
                String base64Content = Base64.getEncoder().encodeToString(decodedBytes);
                System.out.println("Contenido del archivo CER (Base64): " + base64Content);
                System.out.println("Tamaño del archivo CER (bytes): " + decodedBytes.length);
                boolean isValid = isValidCertificate(decodedBytes);
                System.out.println("¿Es un certificado válido? " + isValid);
            } else {
                System.out.println("El archivo CER está vacío o es nulo");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public boolean isValidCertificate(byte[] bytes) {
        try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes)) {
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(bis);
            System.out.println("Certificado emitido por: " + certificate.getIssuerDN().getName());
            System.out.println("Certificado emitido a: " + certificate.getSubjectDN().getName());
            return certificate != null;
        } catch (CertificateException | IOException e) {
            System.err.println("Error al validar el certificado: " + e.getMessage());
            e.printStackTrace();
            return false;
        }
    }
    
    public byte[] getArchivoCerBytes() {
        if (this.archivoCer != null) {
            return Base64.getDecoder().decode(this.archivoCer);
        }
        return null;
    }
    

    }
    En esta clase integre el metodo de la accion para leer el certificado:
    public class ExtraerDatosCertificadoAction extends OnChangePropertyBaseAction {

    @Override
    public void execute() throws Exception {
        Certificado certificado = (Certificado) getView().getEntity();
    
        // Obtener el archivo CER como bytes
        byte[] bytesCer = certificado.getArchivoCerBytes();
        if (bytesCer == null || bytesCer.length == 0) {
            addError("archivoCer_no_seleccionado");
            return;
        }
    
        try {
            // Validar y obtener datos del certificado
            String base64Content = Base64.getEncoder().encodeToString(bytesCer);
            System.out.println("Contenido del archivo CER (Base64): " + base64Content);
    
            byte[] decodedBytes = Base64.getDecoder().decode(base64Content);
            System.out.println("Tamaño del archivo CER (bytes): " + decodedBytes.length);
            boolean isValid = isValidCertificate(decodedBytes);
            System.out.println("¿Es un certificado válido? " + isValid);
    
            if (!isValid) {
                addError("archivoCer_no_valido");
                return;
            }
    
            Map<String, String> certData = obtenerDatosDelCertificado(decodedBytes);
            actualizarCertificado(certificado, certData);
            getView().refresh(); // Refrescar la vista para mostrar los datos actualizados
            addMessage("datos_certificado_extraidos");
        } catch (CertificateException e) {
            addError("error_extraer_certificado", e.getMessage());
            e.printStackTrace();
        }
    }
    
    private Map<String, String> obtenerDatosDelCertificado(byte[] bytesCer) throws CertificateException, IOException {
        Map<String, String> certData = new HashMap<>();
        try (ByteArrayInputStream bis = new ByteArrayInputStream(bytesCer)) {
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(bis);
    
            certData.put("startDate", certificate.getNotBefore().toString());
            certData.put("endDate", certificate.getNotAfter().toString());
            certData.put("signatureAlgorithm", certificate.getSigAlgName());
            certData.put("serialNumber", certificate.getSerialNumber().toString());
    
            Date currentDate = new Date();
            certData.put("isExpired", currentDate.after(certificate.getNotAfter()) ? "true" : "false");
    
            String subjectDN = certificate.getSubjectDN().getName();
            System.out.println("subjectDN: " + subjectDN); // Imprimir el subjectDN completo
            String[] subjectDNArray = subjectDN.split(",");
            for (String dn : subjectDNArray) {
                dn = dn.trim();
                if (dn.startsWith("OID.2.5.4.45=")) {
                    certData.put("rfcEmisor", dn.substring("OID.2.5.4.45=".length()));
                } else if (dn.startsWith("O=")) {
                    certData.put("razonSocial", dn.substring(2));
                }
            }
        }
        return certData;
    }
    
    private boolean isValidCertificate(byte[] bytes) {
        try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes)) {
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(bis);
            System.out.println("Certificado emitido por: " + certificate.getIssuerDN().getName());
            System.out.println("Certificado emitido a: " + certificate.getSubjectDN().getName());
            return certificate != null;
        } catch (CertificateException | IOException e) {
           System.err.println("Error al validar el certificado: " + e.getMessage());
            e.printStackTrace();
            return false;
        }
    }
    
    private void actualizarCertificado(Certificado certificado, Map<String, String> certData) {
        try {
            certificado.setStartDate(certData.get("startDate"));
            certificado.setEndDate(certData.get("endDate"));
            certificado.setSignatureAlgorithm(certData.get("signatureAlgorithm"));
            certificado.setSerialNumber(certData.get("serialNumber"));
            certificado.setIsExpired(certData.get("isExpired"));
            certificado.setRfcEmisor(certData.get("rfcEmisor"));
            certificado.setRazonSocial(certData.get("razonSocial"));
            XPersistence.getManager().merge(certificado);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    

    }, en el error me manda imprimir lo que se encuentra dentro de la referencia '402880e7905bec3401905bf3cc750001', adjunto el error: Hibernate:
    insert
    into
    OXFILES
    (data, libraryId, name, id)
    values
    (?, ?, ?, ?)
    Contenido del archivo CER (Base64): 402880e7905bec3401905bf3cc750001
    Error al validar el certificado: Could not parse certificate: java.io.IOException: Empty input
    java.security.cert.CertificateException: Could not parse certificate: java.io.IOException: Empty input
    Tamaño del archivo CER (bytes): 24

    Es sobre esto...

     
  • Javier Paniza

    Javier Paniza - 2024-07-01

    Hola Leon:

    Cuando usas @File solo guardas un id de 32 bytes en la propiedad. Has de usar FilePeristorFactory, que deuvelve un IFilePersistor para manejar los archivos descargados. En tu caso podrías reescribir tu método getArchivoCerBytes() así:

    public byte[] getArchivoCerBytes() {
        if (this.archivoCer != null) {
            AttachedFile file = FilePeristorFactory.getInstance().find(archivoCer);
            return file.getData();
        }
        return null;
    }
    

    Ayuda a otros en este foro como yo te ayudo a ti.

     

Log in to post a comment.