Banner 1

Mini tutorial para encriptar datos con certificados digitales en PHP.

Mini tutorial para encriptar datos con certificados digitales en PHP.

Estoy trabajando en un proyecto en el cual es muy sensible la seguridad de los datos que se manejan, por lo que necesito encriptar y desencriptar datos con tecnologías de criptografía asimétrica, o más concretamente con certificados digitales. El tema en realidad es bastante simple, paso a explicarles los pasos necesarios.

En primer lugar necesitamos tener los certificados digitales que luego se usarán para encriptar y desencriptar los datos. Encriptaremos con la llave pública y desencriptaremos con la llave privada, para que de esta manera nuestros datos (que pueden ser guardados en una base de datos) no tengan ningún tipo de valor sin que se cuente con la llave privada y su correspondiente password.

Generación de los certificados o llaves pública y privada.

Vamos a generar un certificado firmado por nosotros mismos. Para ello necesitamos tener instalado el OpenSSL y entonces tipeamos:

pablot$ openssl req -new -x509 -out certificado.pem

Una vez hecho esto seguiremos los pasos que se ven a continuación como salida del comando anterior y completaremos la información solicitada según corresponda.
Generating a 1024 bit RSA private key
………………………..++++++
……….++++++
writing new private key to ‘privkey.pem’
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
—–
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter ‘.’, the field will be left blank.
—–
Country Name (2 letter code) [AU]:AR
State or Province Name (full name) [Some-State]:Santa Fe
Locality Name (eg, city) []:Rosario
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Mi empresa
Organizational Unit Name (eg, section) []:IT
Common Name (eg, YOUR name) []:José Perez
Email Address []:

Una vez hecho esto vamos a tener nuestro certificado en el archivo certificado.pem y nuestra llave privada en el archivo privkey.pem. Aca vemos el contenido de los dos archivos:

Este es el contenido de certificado.pem
—–BEGIN CERTIFICATE—–
MIIDADCCAmmgAwIBAgIBADANBgkqhkiG9w0BAQQFADBkMQswCQYDVQQGEwJBUjER
MA8GA1UECBMIU2FudGEgRmUxEDAOBg1VBAcTB1Jvc2FyaW8xEzARBgNVBAoTCk1p
IGVtcHJlc2ExCzAJBgNVBAsTAklUMQ4wDAYDVQQDEwVQYWJsbzAeFw0wODA2Mjcw
ODI4MzBaFw0wODA3MjcwODI4MzBaMGQxCzAJBgNVBAYTAkFSMREwDwYDVQQIEwhT
YW50YSBGZTEQMA4GA1UEBxMHUm9zYXJpbzETMBEGA1UEChMKTWkgZW1wcmVzYTEL
MAkGA1UECxMCSVQxDjAMBgNVBAMTBVBhYmxvMIGfMA0GCSqGSIb3DQEBAQUAA4GN
ADCBiQKBgQC9Hh9+H5+sBUCJklI+U5H7jVILZT21D9LtHqxeVtaBZUheLHJ1tJH6
rCKH/rToMYgNHPthHORQFif5+RMZJxev7o2F16osfwwkF4ak1+2xP7mTOPpT7n1o
t7DUZPNzhV4W9U2wGG7s8k8vX1XZ7KjQSsm0M1Wi7TJLUk+r2z/S7QIDAQABo4HB
MIG+MB0GA1UdDgQWBBTi3lAeHK6M0E0tXmxThxQcYGL5zDCBjgYDVR0jBIGGMIGD
gBTi3lAeHK6M0E0tXmxThxQcYGL5zKFopGYwZDELHAkGA1UEBhMCQVIxETAPBgNV
BAgTCFNhbnRhIEZlM2RAwDgYDVQQHEwSb3NhcmlvMRMwEQYDVQQKEwpNaSBlbXBy
ZXNhMQswCQYDVQQLEwJJVDEOMAwGA1UEAxMFUGFibG+CAQAwDAYDVR0TBAUwAwEB
/zANBgkqhkiG9w0BAQQFAAOBgQB+F7QLGre/v8tu0UZzBCauuygGjPk2KYddJC5/
gcaV5xpgHoyxIXkYkwzfuV+v+S33Ju+mTmXczt5UgPztYOxFdocGFUF0QBs6VGfk
uVSsANaT3TVS8lF/dqiy0M8e0/rsT4PdCvidalvZNMOEcHAl+7TALLzg53FU2bF2
O+Wujw==
—–END CERTIFICATE—–

Este es el contenido de privkey.pem
—–BEGIN RSA PRIVATE KEY—–
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,7269B348F1BAA2D9

RC+B4fUTgQx5qCGmC1VXvlErXmnpbqE+DLGq8dqZYlwTksKnDnMv32uRc3rAeyNc
Eg+aNU6KWhEnu3WYfcHTJsW4R3aILNX2vKF/zOXHHSxBA1zJRgyMzqKrRPfB4BEj
5Enn48ehgG/DwKBcXcQSsNAQ121qJf4QBG3rj6H6jE8wNcIiV7AI5ZKcOB25V/9q
Q7IgplPKX+PfF/piQUDIjNDQ1Nfrfn59qdewkxRQiCoEeJKwXpn6je2JCLDTV5cz
4ZUc5hT/1IePjWHY8TkRnma4v4obBCd8N3fEqkTP5nLBhGAcor9RuBcusmKyhlxt
ftiWTgBs6k15HuCcmzIuARQ/PE5elJMeGYJfrcby40QPLcTdlz9wqR2ULmpAUxTe
g9e1EKTOTAGjF+oUpCrDEIN5Txru6Q8hDQ6NuV9b0baeFJare7dlcqrzcjm2Lwin
Sq3N78xdOiA4kMJ1AKDM6cBXbFvZ92XeUFEZPH53wDC+aiNc4urlqew06uwAgHDu
Br60ODWnhw3babNWQaM5nxAIs5nR8DJZmdzrj2c4zYkYKLmcoaJzsSTGn466kqce
96F4503ev2+/iCgSh9h8lFU9JRRsQnbs4IaxemboHU5MY5Fu3h7MZXSejgUbZ2Z7
3rI9T/VQUyJyxcuzHIKeEJNMwxwUBE+3xqffluZXAxPP8GuyWHSn9owErCPg9RhU
xeBl+MYZi2zzSscdVZ6ZxDbsNRYiGlAdqPBWofv+UTej7ch0vggrhjzkONuGTJn/
IiJB4QUAjkiuDCtZR8OVutxrebmPNnRZmiFHx8L7QYw=
—–END RSA PRIVATE KEY—–

NOTA: Cabe destacar que si queremos tener un certificado digital otorgado por una entidad certificante como Verisign, debemos generar un CSR o Certificate Sign Request (con el comando openssl req -new -out cert.csr) que debe ser enviado (el archivo cert.csr) a la autoridad certificante para que, previo pago, nos devuelva un certificado como el que tenemos en el archivo certificado.pem.

Ahora que ya tenemos el certificado y nuestra llave privada, vamos a ver un ejemplo para encriptar datos con la llave pública que luego podrían ser grabados en una base de datos.


$texto_plano = "Dato supersecreto que pone en riesgo la seguridad nacional";


$llave_publica = “file://certificado.pem”;
openssl_public_encrypt($texto_plano, $texto_encriptado, $llave_publica);

// Si imprimimos esto, vemos "basura" que en realidad es el dato ya encriptado.
// Es por esto que probablemente nos convenga por ejemplo codificarlo en base64 con
// $texto_encriptado = base64_encode($texto_encriptado) antes de grabarlo
// en un campo de una base de datos
//echo $texto_encriptado;
?>

Y ahora cuando tengamos que desencriptar los datos tendremos que usar la llave privada que es la única que podrá desencriptarlos.

// El segundo parametro es la clave que ingresamos al crear el certificado
// si es que optamos por hacerlo.
// Si antes codificamos en base64 el texto encriptado, ahora hay que acordarse
// de hacerle un $texto_encriptado = base64_decode($texto_encriptado) antes de
// desencriptarlo.
$res = openssl_get_privatekey($llave_privada,”miclave”);
openssl_private_decrypt($texto_encriptado, $texto_desencriptado, $res);

//Esto debe dar como salida el mismo texto que antes estaba en la variable $texto_plano
echo $texto_desencriptado;
?>

¡Y listo!, ya esta, no hay nada más. Ya sabemos lo que tenemos que hacer antes de grabar un dato crítico en la base de datos y lo que tenemos que hacer luego de recuperarlo de la base para poder desencriptarlo.

De esta manera la base de datos será solo basura para cualquiera que no tenga la llave privada y su correspondiente clave.

Aclaración importante: El largo de la cadena de datos a encriptar esta limitado por el tamaño de la clave, por lo cual para una clave de 1024 bits como la del ejemplo OpenSSL permite encriptar hasta 936 bits, o sea 936/8=117 caracteres. En consecuencia para claves de 1024 bits solo podremos encriptar hasta 117 caracteres, pero el límite se incrementa si usamos claves de 2048 o 4096 bits.

Por otro lado se recomienda una clave de al menos 2048 bits, pero teniéndo OpenSSL la posibilidad de generar claves de 4096 bits, yo diría que sea de 4096 bits ;-)

Nota: No intenten capturar el contenido de los archivos certificado.pem y privkey.pem que muestro y usarlos porque son inválidos. Deben generarse los propios. Esto esta hecho a propósito para ¡proteger a los inocentes! para que nadie los copie y los use directamente, ya que el hecho de estar publicados los torna totalmente inútiles desde el punto de vista de seguridad.


fuente y agradecimientos: http://elblogdepablot.wordpress.com/mini-tutorial-para-encriptar-datos-con-certificados-digitales-en-php/


y perdon por la tardanza :)

No hay comentarios:

Powered by Bad Robot
Helped by Blackubay