source: branches/2.2/security/classes/CertificadoB.php @ 3232

Revision 3232, 10.5 KB checked in by rafaelraymundo, 14 years ago (diff)

Ticket #1237 - Atualizados componentes de suporte ao uso do Certificado Digital.

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                if(!$m_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar))
141                    {
142                        $this->erros_ssl[] = 'Não foi possível verificar a assinatura gerada. Contate o administrador';
143                        $this->arquivos_para_deletar = array();
144                        return false;
145                    }
146                if(!grava_arquivo($m_arquivo_temporario,$m))
147                {
148                        $this->erros_ssl[] = 'Não foi possível verificar a assinatura gerada. Contate o administrador';
149                        deleta_arquivos_temporarios($this->arquivos_para_deletar);
150                        $this->arquivos_para_deletar = array();
151                        return false;
152                }
153                if(!$vrf_cert_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar))
154                    {
155                        $this->erros_ssl[] = 'Não foi possível verificar a assinatura gerada. Contate o administrador';
156                        $this->arquivos_para_deletar = array();
157                        return false;
158                    }
159                if(!$vrf_msg_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar))
160                    {
161                        $this->erros_ssl[] = 'Não foi possível verificar a assinatura gerada. Contate o administrador';
162                        $this->arquivos_para_deletar = array();
163                        return false;
164                    }
165                // LIMPA ERROS ... Pode ser um problema para outras aplicacoes que usam openssl(fonte de erros unica).
166                while ($erro = openssl_error_string()); //  Limpa buffer de erros anteriores......
167                $this->erros_ssl = array();
168                $resultado = openssl_pkcs7_verify($m_arquivo_temporario,0, $vrf_cert_arquivo_temporario,array($GLOBALS['CAs']),$GLOBALS['CAs'],$vrf_msg_arquivo_temporario);
169                $retorno = true;
170                if($resultado === false || $resultado == -1)
171                {
172                        # Indica ocorrencia de erro ...
173                        $retorno = false;
174                        // Guarda msgs de erro ...
175                        while ($erro = openssl_error_string())
176                        {
177                                $this->erros_ssl[] = $erro;
178                        }
179                        If(file_exists($vrf_msg_arquivo_temporario)) 
180                                {
181                                        $this->msg_sem_assinatura =  file_get_contents($vrf_msg_arquivo_temporario);
182                                }
183                        else
184                                {
185                                        $this->msg_sem_assinatura =  'Nao pode exibir a msg(CD-1)';
186                                }
187                        # Reexecuta o comando com um nivel menor de criticas.
188                        $this->cert_assinante = $this->extrai_certificado_da_msg_assinada($m);
189                        if(!$this->cert_assinante)
190                        {
191                                # Se nao foi possivel obter o certificado retorna com falso .....
192                                If(file_exists($vrf_msg_arquivo_temporario)) 
193                                        {
194                                                $this->msg_sem_assinatura =  file_get_contents($vrf_msg_arquivo_temporario);
195                                        }
196                                else
197                                        {
198                                                $this->msg_sem_assinatura =  'Nao pode exibir a msg(CD-2)';
199                                        }
200                                deleta_arquivos_temporarios($this->arquivos_para_deletar);
201                                $this->arquivos_para_deletar = array();
202                                return false;
203                        }
204                }
205                else
206                {
207                        # Guarda o certificado usado para assinar a msg
208                        $this->cert_assinante  =   file_get_contents($vrf_cert_arquivo_temporario);
209                 }
210                If(file_exists($vrf_msg_arquivo_temporario))  $this->msg_sem_assinatura =  file_get_contents($vrf_msg_arquivo_temporario);
211                $this->certificado($this->cert_assinante);
212                if (!$this->apresentado)
213                {
214                        $this->erros_ssl[] = 'Certificado da Msg nao pode ser tratado.';
215                        $retorno = false;
216                }
217                else
218                {
219                        while ($erro = openssl_error_string()); //  Limpa buffer de erros anteriores......
220                        # Certificado poderia ter assinado um email??
221                        if(!($this->dados['KEYUSAGE']['digitalSignature']))
222                        {
223                                $this->erros_ssl[] = 'Certificado nao poderia ter sido utilizado para assinar email.';
224                                while ($erro = openssl_error_string())
225                                        {
226                                                $this->erros_ssl[] = $erro;
227                                        }
228                                $retorno = false;
229                        }
230                        $revogado = new Verifica_Certificado($this->dados,$this->cert_assinante);
231                        $this->dados['REVOGADO'] = false;
232                        if(!$revogado->status){
233                                $this->erros_ssl[] = $revogado->msgerro;
234                                foreach ($revogado->erros_ssl as $item)
235                                        {
236                                                $this->erros_ssl[] = $item;
237                                        }
238                                if ($revogado->revogado)
239                                        $this->dados['REVOGADO'] = true;
240                                $retorno  = false;
241                        }
242                }
243                deleta_arquivos_temporarios($this->arquivos_para_deletar);
244                $this->arquivos_para_deletar = array();
245                return $retorno;
246        }       
247
248        public function extrai_certificado_da_msg_assinada($m)
249        {
250                $retorno = false;
251                if(!$m)
252                {
253                        return $retorno;
254                }
255                $m_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
256                if(!grava_arquivo($m_arquivo_temporario,$m))
257                {
258                        deleta_arquivos_temporarios($this->arquivos_para_deletar);
259                        $this->arquivos_para_deletar = array();
260                        return $retorno;
261                }
262                $w='';
263                $saida = array();
264                $w = exec('cat ' . $m_arquivo_temporario . ' | openssl smime -pk7out | openssl pkcs7 -print_certs',$saida);
265                if(!$w=='')
266                {
267                        deleta_arquivos_temporarios($this->arquivos_para_deletar);
268                        $this->arquivos_para_deletar = array();
269                        return $retorno;
270                }
271                $aux1 = '';
272                // gera uma unica string com o conteudo retornado pelo comando...
273                foreach($saida as $linha)
274                {
275                        $aux1 .= $linha.chr(0x0A);
276                }
277                // cria um array com os certificados retornados..
278                $aux2 = explode('-----BEGIN CERTIFICATE-----',$aux1);
279                array_shift($aux2);
280                // isolando certificados..
281                $aux5 = array();
282                foreach($aux2 as $item)
283                {
284                        $aux3 = explode('-----END CERTIFICATE-----',$item);
285                        $aux4 = '-----BEGIN CERTIFICATE-----' . $aux3[0] . '-----END CERTIFICATE-----';
286                        $aux5[] = $aux4;
287                }
288                // Testa qual dos certificados nao he uma CA ....
289                foreach($aux5 as $item)
290                {
291                        $Dados_cert = recupera_dados_do_ceritificado_digital($item);
292                        if(!$Dados_cert['CA'])
293                                {
294                                        $retorno = $item;
295                                        break;
296                                }               
297                }
298                deleta_arquivos_temporarios($this->arquivos_para_deletar);
299                $this->arquivos_para_deletar = array();
300                return $retorno;
301        }
302}
303?>
Note: See TracBrowser for help on using the repository browser.