source: trunk/security/classes/CertificadoB.php @ 1574

Revision 1574, 9.6 KB checked in by rafaelraymundo, 14 years ago (diff)

Ticket #699 - Otimização das rotinas de criptografia,
assinatura digital e verificação da mesma.

Line 
1<?php
2require_once('funcoes_auxiliares.php');
3require_once('Verifica_Certificado_conf.php');
4require_once('Verifica_Certificado.php');
5
6//  Pre-requisito: A extensao openssl deve estar disponivel no PHP ....
7class certificadoB
8{
9  public $dados = array();        # Area para armazenar os dados recuperados do certificado.
10  public $apresentado = false;    # Deve ser testado para verificar se no certificado processado foi localizado o CPF
11  public $erros_ssl = array();
12  public $cert_assinante = ''; 
13  public $msg_sem_assinatura = '';  #conteï¿œdo da mensagem sem assinatura, que retorna da funᅵᅵo verify do openssl
14  public $arquivos_para_deletar = array();
15 
16  public function __construct()
17  {
18    if(!extension_loaded('openssl'))
19    {
20      #PHP sem suporte ao openssl.....
21      return false;
22    }
23    $this->dados = array();
24    $this->dados_xml = '';
25    $this->apresentado = false;
26    $this->erros_ssl = array();
27    $this->cert_assinante = '';
28    $this->msg_sem_assinatura = '';
29    $this->arquivos_para_deletar = array();
30  }
31
32public function __destruct()
33  {
34    #Remover arquivos temporarios..... 
35    deleta_arquivos_temporarios($this->arquivos_para_deletar);
36  }
37
38# Recupera dados de um certificado no formato pem
39  function certificado($certificado_pem)
40  {             
41      if (!$certificado_pem)
42    {
43        $this->apresentado = False;
44        return False;    # Sem parametro ...
45    }
46   $this->dados = recupera_dados_do_ceritificado_digital($certificado_pem);
47   $this->dados_xml = gera_xml_com_dados_do_certificado($this->dados);
48     # Certificado foi processado, as informacoes obtidas estao em $this->dados.
49  $this->apresentado = true; 
50  }
51
52# Encriptar senha ......
53        public function encriptar_senha($s,$c)
54        {
55                if($s == '')    return false;
56                if($c == '')    return false;
57                $senha_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
58                //echo $senha_arquivo_temporario.'<br>';
59                if(!grava_arquivo($senha_arquivo_temporario,$s))
60                {
61                        return false;
62                }
63                $cert_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
64                //echo $cert_arquivo_temporario.'<br>';
65                if(!grava_arquivo($cert_arquivo_temporario,$c))
66                {
67                        return false;
68                }
69                $senha_criptografada_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
70                //echo $senha_criptografada_arquivo_temporario.'<br>';
71
72                $w = exec('openssl rsautl -in ' . $senha_arquivo_temporario . ' -out ' . $senha_criptografada_arquivo_temporario . ' -inkey ' . $cert_arquivo_temporario . ' -certin -pkcs -keyform PEM -encrypt',$saida);
73               
74                if(!file_exists($senha_criptografada_arquivo_temporario))
75                {
76                        deleta_arquivos_temporarios($this->arquivos_para_deletar);
77                        $this->arquivos_para_deletar = array();
78                        return false;
79                }
80
81                # Recupera a senha criptada, binario.....               
82                $retorno = file_get_contents($senha_criptografada_arquivo_temporario);
83
84                deleta_arquivos_temporarios($this->arquivos_para_deletar);
85                $this->arquivos_para_deletar = array();
86
87                if(strlen($retorno) != 128) return false;
88
89                return base64_encode($retorno);
90        }
91
92
93# Encriptar uma msg($m) para o(s) destinatario(s) $c(array com certificados)com os headers passados em $h.
94        public function encriptar($m,$c,$h)
95        {
96                if($m == '')    return false;
97                if(!is_array($c))       return false;
98                $aux = count($c);
99                if($aux < 1)    return false;           
100                if(!is_array($h) )      return false;
101                # Tem de verificar todos os certificados que serao utilizados para criptografar a msg..
102                # Inserir a rotina aqui....
103                $m_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
104                //echo $m_arquivo_temporario.'<br>';
105                if(!grava_arquivo($m_arquivo_temporario,$m))
106                {
107                        return false;
108                }
109                $enc_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
110                //echo $enc_arquivo_temporario.'<br>';
111               
112                // LIMPA ERROS ... Pode ser um problema para outras aplicacoes que usam openssl(fonte de erros unica).
113                while ($erro = openssl_error_string()); //  Limpa buffer de erros anteriores......
114                $this->erros_ssl = array();
115                $resultado = openssl_pkcs7_encrypt($m_arquivo_temporario,$enc_arquivo_temporario,$c,$h,$flags=0,$cipherid=OPENSSL_CIPHER_DES);
116                //$resultado = openssl_pkcs7_encrypt($m_arquivo_temporario,$enc_arquivo_temporario,$c,$h);
117                if(!$resultado)
118                {
119                        // Guarda msgs de erro ...
120                        while ($erro = openssl_error_string())
121                        {
122                                $this->erros_ssl[] = $erro;
123                        }
124                        deleta_arquivos_temporarios($this->arquivos_para_deletar);
125                        $this->arquivos_para_deletar = array();
126                        return false;
127                }
128                # Recupera a msg criptada......         
129                $retorno = file_get_contents($enc_arquivo_temporario);
130                deleta_arquivos_temporarios($this->arquivos_para_deletar);
131                $this->arquivos_para_deletar = array();
132                return $retorno;
133        }
134
135
136# Verifica uma msg($m) assinada...
137        public function verificar($m)
138        {
139                if($m == '') return false;
140                $m_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
141                if(!grava_arquivo($m_arquivo_temporario,$m))
142                {
143                        deleta_arquivos_temporarios($this->arquivos_para_deletar);
144                        $this->arquivos_para_deletar = array();
145                        return false;
146                }
147                $vrf_cert_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
148                $vrf_msg_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
149                // LIMPA ERROS ... Pode ser um problema para outras aplicacoes que usam openssl(fonte de erros unica).
150                while ($erro = openssl_error_string()); //  Limpa buffer de erros anteriores......
151                $this->erros_ssl = array();
152                $resultado = openssl_pkcs7_verify($m_arquivo_temporario,0, $vrf_cert_arquivo_temporario,array($GLOBALS['CAs']),$GLOBALS['CAs'],$vrf_msg_arquivo_temporario);
153                $retorno = true;
154                if($resultado === false || $resultado == -1)
155                {
156                        # Indica ocorrencia de erro ...
157                        $retorno = false;
158                        // Guarda msgs de erro ...
159                        while ($erro = openssl_error_string())
160                        {
161                                $this->erros_ssl[] = $erro;
162                        }
163                        If(file_exists($vrf_msg_arquivo_temporario)) 
164                                {
165                                        $this->msg_sem_assinatura =  file_get_contents($vrf_msg_arquivo_temporario);
166                                }
167                        else
168                                {
169                                        $this->msg_sem_assinatura =  'Nao pode exibir a msg(CD-1)';
170                                }
171                        # Reexecuta o comando com um nivel menor de criticas.
172                        $this->cert_assinante = $this->extrai_certificado_da_msg_assinada($m);
173                        if(!$this->cert_assinante)
174                        {
175                                # Se nao foi possivel obter o certificado retorna com falso .....
176                                If(file_exists($vrf_msg_arquivo_temporario)) 
177                                        {
178                                                $this->msg_sem_assinatura =  file_get_contents($vrf_msg_arquivo_temporario);
179                                        }
180                                else
181                                        {
182                                                $this->msg_sem_assinatura =  'Nao pode exibir a msg(CD-2)';
183                                        }
184                                deleta_arquivos_temporarios($this->arquivos_para_deletar);
185                                $this->arquivos_para_deletar = array();
186                                return false;
187                        }
188                }
189                else
190                {
191                        # Guarda o certificado usado para assinar a msg
192                        $this->cert_assinante  =   file_get_contents($vrf_cert_arquivo_temporario);
193                 }
194                If(file_exists($vrf_msg_arquivo_temporario))  $this->msg_sem_assinatura =  file_get_contents($vrf_msg_arquivo_temporario);
195                $this->certificado($this->cert_assinante);
196                if (!$this->apresentado)
197                {
198                        $this->erros_ssl[] = 'Certificado da Msg nao pode ser tratado.';
199                        $retorno = false;
200                }
201                else
202                {
203                        while ($erro = openssl_error_string()); //  Limpa buffer de erros anteriores......
204                        # Certificado poderia ter assinado um email??
205                        if(!($this->dados['KEYUSAGE']['digitalSignature']))
206                        {
207                                $this->erros_ssl[] = 'Certificado nao poderia ter sido utilizado para assinar email.';
208                                while ($erro = openssl_error_string())
209                                        {
210                                                $this->erros_ssl[] = $erro;
211                                        }
212                                $retorno = false;
213                        }
214                        $revogado = new Verifica_Certificado($this->dados,$this->cert_assinante);
215                        $this->dados['REVOGADO'] = false;
216                        if(!$revogado->status){
217                                $this->erros_ssl[] = $revogado->msgerro;
218                                foreach ($revogado->erros_ssl as $item)
219                                        {
220                                                $this->erros_ssl[] = $item;
221                                        }
222                                if ($revogado->revogado)
223                                        $this->dados['REVOGADO'] = true;
224                                $retorno  = false;
225                        }
226                }
227                deleta_arquivos_temporarios($this->arquivos_para_deletar);
228                $this->arquivos_para_deletar = array();
229                return $retorno;
230        }       
231
232        public function extrai_certificado_da_msg_assinada($m)
233        {
234                $retorno = false;
235                if(!$m)
236                {
237                        return $retorno;
238                }
239                $m_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
240                if(!grava_arquivo($m_arquivo_temporario,$m))
241                {
242                        deleta_arquivos_temporarios($this->arquivos_para_deletar);
243                        $this->arquivos_para_deletar = array();
244                        return $retorno;
245                }
246                $w='';
247                $saida = array();
248                $w = exec('cat ' . $m_arquivo_temporario . ' | openssl smime -pk7out | openssl pkcs7 -print_certs',$saida);
249                if(!$w=='')
250                {
251                        deleta_arquivos_temporarios($this->arquivos_para_deletar);
252                        $this->arquivos_para_deletar = array();
253                        return $retorno;
254                }
255                $aux1 = '';
256                // gera uma unica string com o conteudo retornado pelo comando...
257                foreach($saida as $linha)
258                {
259                        $aux1 .= $linha.chr(0x0A);
260                }
261                // cria um array com os certificados retornados..
262                $aux2 = explode('-----BEGIN CERTIFICATE-----',$aux1);
263                array_shift($aux2);
264                // isolando certificados..
265                $aux5 = array();
266                foreach($aux2 as $item)
267                {
268                        $aux3 = explode('-----END CERTIFICATE-----',$item);
269                        $aux4 = '-----BEGIN CERTIFICATE-----' . $aux3[0] . '-----END CERTIFICATE-----';
270                        $aux5[] = $aux4;
271                }
272                // Testa qual dos certificados nao he uma CA ....
273                foreach($aux5 as $item)
274                {
275                        $Dados_cert = recupera_dados_do_ceritificado_digital($item);
276                        if(!$Dados_cert['CA'])
277                                {
278                                        $retorno = $item;
279                                        break;
280                                }               
281                }
282                deleta_arquivos_temporarios($this->arquivos_para_deletar);
283                $this->arquivos_para_deletar = array();
284                return $retorno;
285        }
286}
287?>
Note: See TracBrowser for help on using the repository browser.