CertificateException::translateOpensslErrors()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 16
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4.0466

Importance

Changes 0
Metric Value
cc 4
eloc 6
c 0
b 0
f 0
nc 4
nop 1
dl 0
loc 16
ccs 6
cts 7
cp 0.8571
crap 4.0466
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Derafu: Biblioteca PHP (Núcleo).
7
 * Copyright (C) Derafu <https://www.derafu.org>
8
 *
9
 * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10
 * bajo los términos de la Licencia Pública General Affero de GNU publicada por
11
 * la Fundación para el Software Libre, ya sea la versión 3 de la Licencia, o
12
 * (a su elección) cualquier versión posterior de la misma.
13
 *
14
 * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15
 * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16
 * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la Licencia Pública
17
 * General Affero de GNU para obtener una información más detallada.
18
 *
19
 * Debería haber recibido una copia de la Licencia Pública General Affero de GNU
20
 * junto a este programa.
21
 *
22
 * En caso contrario, consulte <http://www.gnu.org/licenses/agpl.html>.
23
 */
24
25
namespace Derafu\Lib\Core\Package\Prime\Component\Certificate\Exception;
26
27
use Derafu\Lib\Core\Common\Exception\Exception;
28
use Throwable;
29
30
/**
31
 * Clase de excepción personalizada para la firma electrónica.
32
 */
33
class CertificateException extends Exception
34
{
35
    /**
36
     * Errores específicos de la firma electrónica.
37
     *
38
     * @var array
39
     */
40
    private array $errors;
41
42
    /**
43
     * Listado de errores que podría entregar OpenSSL traducidos a un mensaje
44
     * entendible por humanos en español.
45
     *
46
     * NOTE: Las traducciones terminan sin punto a propósito pues se
47
     * concatenará el código de error entre paréntesis al final y ahí se
48
     * agregará el punto final del error.
49
     *
50
     * @var array
51
     */
52
    private $defaultOpensslTranslations = [
53
        '0308010C' => 'Algoritmo o método de cifrado no soportado',
54
        '11800071' => 'Falló la verificación MAC en PKCS12, el certificado o contraseña es incorrecto',
55
        '0906D06C' => 'No se pudo cargar el certificado X.509',
56
        '0B080074' => 'Formato PEM no válido',
57
        '0A000086' => 'Longitud de clave no permitida',
58
        '06065064' => 'Error en la clave privada: contraseña incorrecta',
59
        '14094418' => 'Error en la capa SSL: certificación no válida o CA no conocida',
60
        '14090086' => 'Error de configuración SSL: problema con el certificado o clave',
61
        '0907B068' => 'Error en la lectura de un archivo de certificado',
62
        '1403100E' => 'Error en SSL: protocolo no compatible',
63
    ];
64
65
    /**
66
     * Constructor de la excepción.
67
     *
68
     * @param string $message Mensaje de la excepción.
69
     * @param array $errors Arreglo con errores con los detalles.
70
     * @param int $code Código de la excepción (opcional).
71
     * @param Throwable|null $previous Excepción previa (opcional).
72
     */
73 8
    public function __construct(
74
        string $message,
75
        array $errors = [],
76
        int $code = 0,
77
        ?Throwable $previous = null
78
    ) {
79 8
        if (empty($errors)) {
80 8
            while ($error = openssl_error_string()) {
81 1
                $errors[] = $error;
82
            }
83
        }
84 8
        $errors = $this->translateOpensslErrors($errors);
85
86 8
        $message = trim(sprintf(
87 8
            '%s %s',
88 8
            $message,
89 8
            implode(' ', $errors)
90 8
        ));
91
92 8
        $this->errors = $errors;
93 8
        parent::__construct($message, $code, $previous);
94
    }
95
96
    /**
97
     * Obtiene los errores asociados a la excepción.
98
     *
99
     * @return array Arreglo de errores.
100
     */
101
    public function getErrors(): array
102
    {
103
        return $this->errors;
104
    }
105
106
    /**
107
     * Traduce los errores de OpenSSL a mensajes más sencillos para humanos.
108
     *
109
     * @param array $errors Arreglo con los errores originales de OpenSSL.
110
     * @return array Arreglo con los errores traducidos.
111
     */
112 8
    private function translateOpensslErrors(array $errors): array
113
    {
114
        // Definir reglas de traducción.
115 8
        $translations = $this->defaultOpensslTranslations;
116
117
        // Traducir los errores.
118 8
        foreach ($errors as &$error) {
119 1
            foreach ($translations as $code => $trans) {
120 1
                if (str_contains($error, 'error:' . $code)) {
121
                    $error = sprintf('%s (Error #%s).', $trans, $code);
122
                }
123
            }
124
        }
125
126
        // Entregar errores traducidos.
127 8
        return $errors;
128
    }
129
}
130