Usando OpenSSL en El Mundo Real
Usando OpenSSL en El Mundo Real
Usando OpenSSL en El Mundo Real
OpenSSL es una herramienta libre muy potente que nos ayuda a implementar
los protocolos y algoritmos de SSL (Secure Socket Layer) y TLS Transport
Layer Security). OpenSSL incluye una API criptográfica de propósito general y
una utilidad de línea de comandos muy potente. OpenSSL posee una licencia
muy parecida a la de Apache.
Hay una cita muy buena que dice: “Las palabras son enanos y los ejemplos son
gigantes” o algo así. Entonces vamos al lío, veamos que podemos hacer con
OpenSSL.
Standard commands
asn1parse ca ciphers crl crl2pkcs7
dgst dh dhparam dsa dsaparam
enc engine errstr gendh gendsa
genrsa nseq ocsp passwd pkcs12
pkcs7 pkcs8 rand req rsa
rsautl s_client s_server s_time sess_id
smime speed spkac verify version
x509
Message Digest commands (see the 'dgst' command for more details)
md2 md4 md5 mdc2 rmd160
sha sha1
Vamos a ver unos ejemplos usados para sacar un digest MD5 del archivo
/etc/secure/data:
$ openssl dgst -md5 /etc/secure/data
MD5(/etc/secure/data)= f268fc3e92ef844117365a3368b8fe45
OpenSSL puede combinarse con el comando find para hacer “huellas digitales”
(fingerprints) de muchos archivos a la vez:
$ find /etc -type f | xargs openssl md5 > /etc/secure/md5_sigs.txt
El anterior comando creará un archivo MD5 hash de todos los archivos del
directorio /etc. Estos finger prints deben ser almacenados como solo lectura y
en un lugar seguro.
Descifrando datos:
Para descifrar datos que han sido cifrados previamente usaremos la opción –d
tras el algoritmo de cifrado en el comando openssl. El siguiente ejemplo
muestra como descifrar el archivo /etc/secure/sensitive_data.enc.3des que fue
cifrado con el algoritmo 3DES:
$ openssl enc -des3 -d -in /etc/secure/sensitive_data.enc.3des \
-out /etc/secure/sensitive_data
Generar contraseñas:
La opción "-1" indica que usaremos MD5 como algoritmo y la opción “-stdin”
indica que le pasamos la contraseña a través de la entrada estándar. Si tu
sistema operativo no soporta MD5 las contraseñas puede ser creadas con
CRYPT:
$ echo blah | openssl passwd -stdin -crypt -salt GH
Este comando generará una contraseña crypt de “blah” con “GH” como salt.
Certificados Digitales:
Una vez que el certificado ha sido exportado, éste puede ser convertido a PEM
o DER con el siguiente comando:
$ openssl pkcs12 -in cert.crt.p12 -out cert.crt.pem
SCRIPT 1 (ver Anexo) muestra como OpenSSL puede ser usado para
comprobar si un servidor Web-SSL está respondiendo a nuevas conexiones. La
opción openssl s_client es invocada y se le pasa una petición HTTP GET al
servidor Web después de crearse la conexión SSL. Si el servidor falla se
registra un mensaje vía syslog y se envía un mail a la cuenta configurada en
dicho script. Este script puede ejecutarse periódicamente a través del cron.
SCRIPT 2 (ver Anexo) (ssl-cert-check) es un shell script que usa GNU date y el
commando openssl s_client. ssl-cert-check diferentes operaciones y puede ser
configurado para enviar un mail cuando un certificado está a punto de caducar.
ssl-cert-check muestra la ayuda cuando es ejecutado sin opciones:
$ ./ssl-cert-check
Usage: ./ssl-cert-check {{ [ -b ] && [ -f cert_file ] } || { \
[ -s common_name ] && [ -p port] }} [ -e email ] \
[ -x expir_days ] [ -q ] [ -a ] [ -h ]
-a : Send a warning message through email
-b : Print the expiration date for all
certificates in cert_file (batch mode)
-e email address : Email address to send expiration notices
-f cert file : File with a list of common names and ports
(eg., blatch.com 443)
-h : Print this screen
-p port : Port to connect to (interactive mode)
-s commmon name : Server to connect to (interactive mode)
-q : Don't print anything on the console
-x days : Certificate expiration interval
(eg. if cert_date < days)
El siguiente certificado puede ser usado para ver la caducidad del certificado de
del www.daemons.net que está en el puerto 443:
$ ./ssl-cert-check -s www.daemons.net -p 443
$ ./ssl-cert-check -b -f ssldomains
Conclusión:
Referencias
Webs:
OpenSSL: http://www.openssl.org
ssl-cert-check: http://www.daemons.net/software
TLS 1.0 RFC: http://www.ietf.org/html.charters/tls-charter.html
Libros:
Schneier, Bruce. 1996. Applied Cryptography. John Wiley & Sons.
Stallings, William. 2003. Cryptography and Network Security:
Principles and Practice. Prentice Hall.
Thomas, Stephen. 2000. SSL & TLS Essentials: Securing the Web.
John Wiley & Sons.
Viega, John; Matt Messier; and Pravir Chandra. Network Security with
OpenSSL: Cryptography for Secure Communications. O'Reilly &
Associates.
Ryan Matteson has been a UNIX systems administrator for eight years. He
specializes in network security, Web technologies, Storage Area Networks,
high-availability systems, Linux, and the Solaris operating systems. Questions
and comments about this article can be addressed to: [email protected].
ANEXO:
SCRIPT 1 web-server-status.sh
#!/bin/sh
TMP="$HOME/connect.$$"
umask 077
touch ${TMP}
openssl s_client -quiet -connect ${HOST}:${PORT} > ${TMP} 2>&1 << EOF
GET / HTTP/1.0
EOF
rm -f ${TMP}
SCRIPT 2 ssl-cert-check.sh
#!/bin/bash
#
# Program: SSL Certificate Check <ssl-cert-check>
#
# Author: Ryan Matteson <[email protected]>
#
# Current Version: 1.2
#
# Revision History:
# Version 1.2
# Added checks for each binary required
# Added checks for connection timeouts
#
# Versions 1.1
# Added checks for GNU date
# Added a "-h" option
# Cleaned up the documentation
#
# Version 1.0
# Initial Release
#
# Last Updated: 5-23-2004
#
# Purpose:
# ssl-cert-check checks to see if a digital certificate in X.509
format
# has expired. ssl-cert-check can be run in interactive and batch
mode,
# and provides facilities to alarm if a certificate is about to
expire.
#
# License:
# This program is free software; you can redistribute it and/or
modify it
# under the terms of the GNU General Public License as published by
the
# Free Software Foundation; either version 2, or (at your option)
any
# later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.
#
# Requirements:
# Requires openssl and GNU date
#
# Installation:
# Copy the shell script to a suitable location
#
# Usage:
# Usage: ./ssl-cert-check {{ [ -b ] && [ -f cert_file ] } || \
# { [ -s common_name ] && [ -p port] }}
# [ -e email ] [ -x expir_days ] [ -q ] [ -a ] [ -h ]
# -a : Send a warning message through email
# -b : Print the expiration date for all
certificates in
# cert_file (batch mode)
# -e email address : Email address to send expiration notices
# -f cert file : File with a list of common names and ports
# (eg., mail.daemons.net 443)
# -h : Print this screen
# -p port : Port to connect to (interactive mode)
# -s commmon name : Server to connect to (interactive mode)
# -q : Don't print anything on the console
# -x days : Certificate expiration interval (eg. if
cert_date < days)
#
# Examples:
# Print the certificate expiration dates for a list of domains
specified
# in the file ssldomains:
# $ ssl-cert-check -b -f ssldomains
#
# Print the certificate expiration date for mail.daemons.net:
# $ ssl-cert-check -s mail.daemons.net -p 995
#
# Run ssl-cert-check in quiet mode, check for all certificates that
will
# expire in 75-days or less. Email the expiring certs to
[email protected]:
# $ ssl-cert-check -a -b -f ssldomains -q -x 75 -e
[email protected]
#
# This method takes a HOST ($1) and PORT ($2) and checks to see
# if the certificate has expired
check_cert() {
else
# Get the expiration date with openssl
CERTDATE=`${OPENSSL} x509 -in ${CERT_TMP} -enddate -
noout \
| sed 's/notAfter\=//'`
# Convert the date to seconds, and get the diff between NOW
and
# the expiration date
CERTUTC=`utcseconds "${CERTDATE}"`
CERTDIFF=`date_diff ${NOWUTC} ${CERTUTC}`
if [ ${CERTDIFF} -lt 0 ]
then
if [ "${ALARM}" == "TRUE" ]
then
echo "The SSL certificate for ${1} has
expired!" \
| ${MAIL} -s "Certificate for ${1} has
expired!" ${ADMIN}
fi
DAYS=`date_days $CERTDIFF`
prints ${1} ${2} "Expired" "$CERTDATE" "$DAYS"
DAYS=`date_days $CERTDIFF`
prints ${1} ${2} "Expiring" "${CERTDATE}"
"${DAYS}"
else
DAYS=`date_days $CERTDIFF`
prints ${1} ${2} "Valid" "${CERTDATE}"
"${DAYS}"
fi
fi
}
if [ ! -f ${OPENSSL} ]
then
echo "ERROR: $OPENSSL does not exist. Please modify the \$OPENSSL
variable."
exit 1
fi
if [ ! -f ${DATE} ]
then
echo "ERROR: $DATE does not exist. Please modify the \$DATE
variable."
exit 1
fi
if [ ! -f ${MAIL} ]
then
echo "ERROR: $MAIL does not exist. Please modify the \$MAIL
variable."
exit 1
fi
# If a file and a "-a" are passed on the command line, check all
# of the certificates in the file to see if they are about to expire
elif [ "${REPORT_ALL}" == "TRUE" ] && [ -f "${SERVERFILE}" ]
then
print_heading
while read HOST PORT
do
check_cert "${HOST}" "${PORT}"