Firmar un archivo no es otra cosa que garantizar su fuente de origen. Recordando lo básico del uso de las llaves.
La privada es una llave que puede cifrar algo y esto se puede descifrar con la pública y de la pública cualquiera puede tener acceso a ella, esto no es para cifrar el contenido del archivo y que nadie lo más lo vea. Usando la lógica sabemos que si algo es cifrado con la clave privada y esa clave solo la conoce el autor del archivo, significa que solo él pudo firmar el archivo. En este caso la llave pública solo sirve para confirmar que el documento o archivo provienen de quien se dice que viene.
Los usos de esto son muchos, el primero es evitar la suplantación de identidad, si alguien envía un memorándum en una empresa firmando como el director general se debe poder confirmar que el memorándum viene de quien dice venir, del director y que no ha sido otra persona que simplemente se paso por el . Otro uso inmediato es la incorruptibilidad del documento. Nadie podría modificar el documento en lo más mínimo, ni un solo punto y coma podría ser agregados o retirados. Muy útil para firmar ordenes de compras, documento autorizados o cotizaciones.
¿ Por qué usar llaves públicas y privadas ( RSA ) en lugar de una simple sumatoria MD5 ?
La respuesta es simple, Colisiones MD5, aquí no hay colisión posible por lo que es mucho más seguro firmar con RSA que con MD5
Puedes probar esto con archivos que he firmado para este artículo
Descárgalos aquí y verifícalos aquí
Video mostrando el funcionamiento
El siguiente código de PHP muestra de forma rápida como firmar documentos y como verificarlos, se asume que ya se cuenta con una llave pública y privada.
Verificar la firma
<?php
$uploads_dir = "/basuradelabasura/tmp";
$tmp_name =
$_FILES["userfile"]["tmp_name"][0];
$name1 =
$_FILES["userfile"]["name"][0];
move_uploaded_file($tmp_name, "$uploads_dir/$name1");
$tmp_name =
$_FILES["userfile"]["tmp_name"][1];
$name2 =
$_FILES["userfile"]["name"][1];
move_uploaded_file($tmp_name, "$uploads_dir/$name2");
$archivo1 = $uploads_dir."/".$name1;
$archivo2 = $uploads_dir."/".$name2;
$gestor = fopen($archivo1, "r");
$dato = fread($gestor, filesize($archivo1));
fclose($gestor);
$gestor = fopen($archivo2, "r");
$firma = fread($gestor, filesize($archivo2));
fclose($gestor);
unlink ($archivo1);
unlink ($archivo2);
// El contenido de $Dato y $Firma deben ser los archivos completos.
$respuesta =
openssl_verify($dato,$firma,"file://publica.key",OPENSSL_ALGO_SHA256);
if ($respuesta == 1) echo "Valido";
else echo "Falso";
?>
Firmar un archivo
<?php
$uploads_dir = "/basuradelabasura/tmp";
$tmp_name =
$_FILES["userfile"]["tmp_name"][0];
$name1 =
$_FILES["userfile"]["name"][0];
move_uploaded_file($tmp_name, "$uploads_dir/$name1");
$archivo1 = $uploads_dir."/".$name1;
$gestor = fopen($archivo1, "r");
$dato = fread($gestor, filesize($archivo1));
fclose($gestor);
unlink ($archivo1);
// El contenido de dato es el archivo que se ha subido a fima y $firma
obtendra el valor de la firma que debe ser volada al archivo.sig
$respuesta = openssl_sign($dato, $firma, "file://privada.key",
OPENSSL_ALGO_SHA256);
if ($respuesta == TRUE) {
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$name1.sig\"");
echo $firma;
}
?>