arquivos_para_deletar); } #-------------------------------------------------------------------------------------------------------------------------------------------------------- #-------------------------------------------------------------------------------------------------------------------------------------------------------- # Recupera dados de um certificado no formato pem #-------------------------------------------------------------------------------------------------------------------------------------------------------- function certificado($certificado_pem) { if (!$certificado_pem) { $this->apresentado = False; return False; # Sem parametro ... } $this->dados = recupera_dados_do_ceritificado_digital($certificado_pem); # Certificado foi processado, as informacoes obtidas estao em $this->dados. $this->apresentado = true; } #-------------------------------------------------------------------------------------------------------------------------------------------------------- #-------------------------------------------------------------------------------------------------------------------------------------------------------- # Encriptar uma msg($m) para o(s) destinatario(s) $c(array com certificados)com os headers passados em $h. #-------------------------------------------------------------------------------------------------------------------------------------------------------- public function encriptar($m,$c,$h) { if($m == '') return false; if(!is_array($c)) return false; $aux = count($c); if($aux < 1) return false; if(!is_array($h) ) return false; # Tem de verificar todos os certificados que serao utilizados para criptografar a msg.. # Inserir a rotina aqui.... $m_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar); //echo $m_arquivo_temporario.'
'; if(!grava_arquivo($m_arquivo_temporario,$m)) { return false; } $enc_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar); //echo $enc_arquivo_temporario.'
'; // LIMPA ERROS ... Pode ser um problema para outras aplicacoes que usam openssl(fonte de erros unica). while ($erro = openssl_error_string()); // Limpa buffer de erros anteriores...... $this->erros_ssl = array(); $resultado = openssl_pkcs7_encrypt($m_arquivo_temporario,$enc_arquivo_temporario,$c,$h); if(!$resultado) { // Guarda msgs de erro ... while ($erro = openssl_error_string()) { $this->erros_ssl[] = $erro; } deleta_arquivos_temporarios($this->arquivos_para_deletar); $this->arquivos_para_deletar = array(); return false; } # Recupera a msg criptada...... $retorno = file_get_contents($enc_arquivo_temporario); //$aux = explode(chr(0x0A),file_get_contents($enc_arquivo_temporario)); //$retorno=''; /* $flag = false; for ($i = 0; $i < count($aux); $i++) { if(!$aux[$i]) { if(!$flag) { //$retorno .= '-----BEGIN PKCS7-----'.chr(0x0A); $flag = true; } } else { $retorno .= $aux[$i].chr(0x0A); } } //$retorno .= '-----END PKCS7-----'.chr(0x0A); */ deleta_arquivos_temporarios($this->arquivos_para_deletar); $this->arquivos_para_deletar = array(); return $retorno; } #-------------------------------------------------------------------------------------------------------------------------------------------------------- #-------------------------------------------------------------------------------------------------------------------------------------------------------- # Verifica uma msg($m) assinada... #-------------------------------------------------------------------------------------------------------------------------------------------------------- public function verificar($m) { if($m == '') return false; $m_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar); if(!grava_arquivo($m_arquivo_temporario,$m)) { deleta_arquivos_temporarios($this->arquivos_para_deletar); $this->arquivos_para_deletar = array(); return false; } $vrf_cert_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar); $vrf_msg_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar); // LIMPA ERROS ... Pode ser um problema para outras aplicacoes que usam openssl(fonte de erros unica). while ($erro = openssl_error_string()); // Limpa buffer de erros anteriores...... $this->erros_ssl = array(); $resultado = openssl_pkcs7_verify($m_arquivo_temporario,0, $vrf_cert_arquivo_temporario,array($GLOBALS['CAs']),$GLOBALS['CAs'],$vrf_msg_arquivo_temporario); $retorno = true; if(!$resultado) { # Indica ocorrencia de erro ... $retorno = false; // Guarda msgs de erro ... while ($erro = openssl_error_string()) { $this->erros_ssl[] = $erro; } # Reexecuta o comando com um nivel menor de criticas. $this->cert_assinante = $this->extrai_certificado_da_msg_assinada($m); if(!$this->cert_assinante) { # Se nao foi possivel obter o certificado retorna com falso ..... deleta_arquivos_temporarios($this->arquivos_para_deletar); $this->arquivos_para_deletar = array(); return false; } } else { # Guarda o certificado usado para assinar a msg $this->cert_assinante = file_get_contents($vrf_cert_arquivo_temporario); } $this->msg_sem_assinatura = file_get_contents($vrf_msg_arquivo_temporario); $this->certificado($this->cert_assinante); if (!$this->apresentado) { $this->erros_ssl[] = 'Certificado da Msg nao pode ser tratado.'; $retorno = false; } else { while ($erro = openssl_error_string()); // Limpa buffer de erros anteriores...... # Certificado poderia ter assinado um email?? if(!openssl_x509_checkpurpose($vrf_cert_arquivo_temporario,X509_PURPOSE_SMIME_SIGN)) { $this->erros_ssl[] = 'Certificado nao poderia ter sido utilizado para assinar email.'; while ($erro = openssl_error_string()) { $this->erros_ssl[] = $erro; } $retorno = false; } // Isto esta codificado assim antecipando nova versao do parseador.... $this->dados['KEYUSAGE']['digitalSignature'] =TRUE; $this->dados['EXTKEYUSAGE']['emailProtection'] = '1.3.6.1.5.5.7.3.4'; //testa se certificado revogado $revogado = new Verifica_Certificado($this->dados,$this->cert_assinante); $this->dados['REVOGADO'] = false; if(!$revogado->status){ $this->erros_ssl[] = $revogado->msgerro; foreach ($revogado->erros_ssl as $item) { $this->erros_ssl[] = $item; } if ($revogado->revogado) $this->dados['REVOGADO'] = true; $retorno = false; } } deleta_arquivos_temporarios($this->arquivos_para_deletar); $this->arquivos_para_deletar = array(); return $retorno; } public function extrai_certificado_da_msg_assinada($m) { $retorno = false; if(!$m) { return $retorno; } $m_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar); if(!grava_arquivo($m_arquivo_temporario,$m)) { deleta_arquivos_temporarios($this->arquivos_para_deletar); $this->arquivos_para_deletar = array(); return $retorno; } $w=''; $saida = array(); $w = exec('cat ' . $m_arquivo_temporario . ' | openssl smime -pk7out | openssl pkcs7 -print_certs',$saida); if(!$w=='') { deleta_arquivos_temporarios($this->arquivos_para_deletar); $this->arquivos_para_deletar = array(); return $retorno; } $aux1 = ''; // gera uma unica string com o conteudo retornado pelo comando... foreach($saida as $linha) { $aux1 .= $linha.chr(0x0A); } // cria um array com os certificados retornados.. $aux2 = explode('-----BEGIN CERTIFICATE-----',$aux1); array_shift($aux2); // isolando certificados.. $aux5 = array(); foreach($aux2 as $item) { $aux3 = explode('-----END CERTIFICATE-----',$item); $aux4 = '-----BEGIN CERTIFICATE-----' . $aux3[0] . '-----END CERTIFICATE-----'; $aux5[] = $aux4; } // Gera array com as CAs que assinaram os certificados encontrados na msg.... $aux5_ACs = array(); foreach($aux5 as $item) { $cert = openssl_x509_parse($item); $aux5_ACs[$cert[issuer][CN]] = $cert[issuer][CN]; } // Verifica qual certificado tem no subject um CN que nao he uma CA. foreach($aux5 as $item) { $cert = openssl_x509_parse($item); if(!$aux5_ACs[$cert[subject][CN]]) { $retorno = $item; break; } } deleta_arquivos_temporarios($this->arquivos_para_deletar); $this->arquivos_para_deletar = array(); return $retorno; } } ?>