(this information is also available on http://docs.primekey.se/) There are several ways to sign log files. The most common is to sign the logs as they are beeing archived (rotated). Some examples: - Export signed logs in CSV format using the admin GUI - If logs are sent to syslog, the syslog rotation can sign files when they are rotated - Using openssl - Using a time stamp server (TSA) - If logs are stored by JBoss, a special log4j appender can be used to sign files when they are rotated - Using a time stamp server (TSA) These are general ways, which works for any application that either uses syslog or JBoss. Then there are application specific ways: - Implement a custom logger in EJBCA that signs each log row. Implementation of custom loggers are described in 'Appendixes->Log Configuration' on http://docs.primekey.se/. No such imelementation is done for the moment. If every log row should be signed a separate key on a high-performance HSM is needed, several log rows per secons is normally issued when actions are done. This document describes the three first options. Exporting signed logs in CSV format ================================================ In the 'View Log' functionality you can export the logs you view in the admin-GUI. You export logs by clicking the 'Export as csv' button. If you want the logs signed, you can select a CA in the drop down list besides the button. If you don't select a CA, the exported file is in plain csv format. If you select a CA, the exported file is a signed CMS/PKCS#7 file returned as 'logexport.p7m'. The signing certificate used is a special CMS signer certificate signed by the selected CA. This signing service is created when the CA is created, but it is by default disabled. You can enable the CMS Signing service in the 'Edit Certificate Authorities' view by editing a CA and activating the 'CMS Service'. A signed 'logexport.p7m' can be verified with for example: openssl smime -verify -inform DER -in logexport.p7m -CAfile adminca1.pem where adminca1.pem is the certificate of the CA that has the CMS Service used to sign the file. Enabling log signing using logrotate and openssl ================================================ Save and enable the below logrotate configuration for syslog, is should normaly be stored as the file syslog in the directory /etc/logrotate.d. If there is a previous configuration for syslog, you should remove this, perhaps merge some changes if you like. Syslog is normally not rotated in most linux distributions. After enabling the configuration you should make sure that logrotate is run as often as you like. Normally is is run every night. If you want to run it more often for syslog, you can add a crontab entry to run it every hour for example. In that cas call logrotate with the specified configuration file: logrotate syslog.conf Note, that when stored in logrotate.d, the syslog configuration will be called when logrotate is normally run. ----- /var/log/syslog { rotate 5 postrotate /usr/bin/killall -HUP syslogd endscript lastaction OPENSSL=/usr/bin/openssl LOGFILE=/var/log/syslog FILE="$LOGFILE.`date +%F.%H:%M:%S`.log" SIGNATUREFILE="$FILE.sign" cp $LOGFILE.1 "$FILE" PRIVATEKEY="/etc/logsigner/qc1.priv" $OPENSSL dgst -sign $PRIVATEKEY -sha1 $FILE > $SIGNATUREFILE endscript } ----- qc1.priv is the private key used for signing the logfile. See the simple shell script below for openssl command to convert a pkcs12 file to the public key and private key files that openssl uses for signing and verifying. To verify, you can issue the command: log-sign.sh verify qc1.pub syslog.2006-07-29.11\:06\:27.log syslog.2006-07-29.11\:06\:27.log.sign Where the dates and time correspond to the file you are verifying off-course. log.sign.sh is a simple shell script use to manually sign and verify files: ----- #!/bin/bash # Openssl command for signing and verifying #openssl dgst -sign superadmin.key -sha1 test.txt > test.txt.sign #openssl dgst -verify superadmin.pubkey -signature test.txt.sign -sha1 test.txt # Openssl command to convert a p12 file to cert and key files in pem # First cert: #openssl pkcs12 -in signer.p12 -nodes -nokeys -clcerts -out signer.pem # Then public key #openssl x509 -in signer.pem -pubkey -noout > signer.pub # Then private key: #openssl pkcs12 -in signer.p12 -nodes -nocerts -out signer.priv OPENSSL=/usr/bin/openssl SCRIPTNAME=`basename $0` OPTION=$1 DATE=`date +"%Y-%m-%d"` BACKUPDIR=signed_files if [ "$OPTION" = "sign" ]; then PRIVATEKEY="$2" FILE="$3" SIGNATUREFILE="$4" $OPENSSL dgst -sign $PRIVATEKEY -sha1 $FILE > $SIGNATUREFILE exit 0 elif [ "$OPTION" = "verify" ]; then PUBLICKEY="$2" FILE="$3" SIGNATUREFILE="$4" $OPENSSL dgst -verify $PUBLICKEY -signature $SIGNATUREFILE -sha1 $FILE exit 0 else echo "Usage:" echo "$SCRIPTNAME sign " echo "$SCRIPTNAME verify " exit 0 fi ----- Enabling log signing using logrotate and TSA ============================================ The same approach is taken for signing using the TSA server instead of openssl. In this example the timeStampClient and TSA from PrimeKey is used. After building 'signserver' the timeStampClient.jar and other needed jar files is in the dist-client directory. The new logrotate configuration: ----- /var/log/syslog { rotate 5 postrotate /usr/bin/killall -HUP syslogd endscript lastaction JAVA_HOME=/usr/local/java TSACLIENTDIR=/home/tomas/dev/workspace/signserver/dist-client LOGFILE=/var/log/syslog FILE="$LOGFILE.`date +%F.%H:%M:%S`.log" SIGNATUREFILE="$FILE.sign" cp $LOGFILE.1 "$FILE" $JAVA_HOME/bin/java -jar "$TSACLIENTDIR/timeStampClient.jar" -url "http://127.0.0.1:8080/signserver/tsa?signerId=1" -infile $FILE -outrep $SIGNATUREFILE -base64 endscript } ----- Replace the ip-address and port (127.0.0.1:8080) with the ip and port of your actual TSA. And the new shell script for verification (or manual signing). log-sign-tsa.sh ----- #!/bin/bash TSACLIENTDIR=/usr/local/signserver/dist-client SCRIPTNAME=`basename $0` OPTION=$1 DATE=`date +"%Y-%m-%d"` if [ "$OPTION" = "sign" ]; then FILE="$2" SIGNATUREFILE="$3" TSAURL="$4" java -jar "$TSACLIENTDIR/timeStampClient.jar" -url $TSAURL -infile $FILE -outrep $SIGNATUREFILE -base64 exit 0 elif [ "$OPTION" = "verify" ]; then PUBLICKEY="$2" FILE="$3" SIGNATUREFILE="$4" java -jar "$TSACLIENTDIR/timeStampClient.jar" -verify -inrep $SIGNATUREFILE -signerfile $PUBLICKEY sha1sum $FILE exit 0 else echo "Usage:" echo "To sign files you have to edit the script and add the files you want signed." echo "$SCRIPTNAME sign " echo "$SCRIPTNAME verify " exit 0 fi ----- When verifying the time stamp token, the sha1 hash from the time stamp token (signed) and the calculated sha1 hash of the file is printed. You must compare them manually. Enabling log signing using TSA in JBoss ======================================= There is an implementation that creates a signed time stamp, from a TSA, on JBoss log files when they are rolled-over. This can be every hour for example. - Stop JBoss - Issue the command: ant jbosslogsigning - Copy dist/ejbcalogsigning.jar to jboss.home/server/default/lib - Copy lib/bctsp-jdk to jboss.home/server/default/lib - Copy lib/bcprov-jdk to jboss.home/server/default/lib - Configure jboss.home/server/default/conf/log4j.xml, according to below - Start JBoss Logs will be rolled over at the selected interval, and a file with the same name as the log file, with ending .tsp will be created. The tsp file contains the complete base64 encoded response from the TSA. NOTE!!! Unforturnately you have to add bcprov to JBoss's lib directory. This means that you have to keep this jar in sync with the EJBCA release, if you upgrade EJBCA. When upgrading EJBCA, you should also copy a new version of bcprov from EJBCA to JBoss's lib directory. If you happen to start up JBoss at exactly the time when a log file rollover occurs, it is normal in the startup log with an error message like: SigningDailyRollingFileAppender: No reply bytes received, is TSA down? The log appender should recover from this and resume normal opperations. The section: ----- ----- should be replaced with: ----- ----- replace the ip-address and port '127.0.0.1:8080' with the IP and port of your actual TSA. The TSA should listen on the HTTP protocol as defined in RFC 3161. Enabling log signing using external script in JBoss =================================================== There is an implementation that runs an external script when JBoss log files when they are rolled-over. This can be every hour for example. - Stop JBoss - Issue the command: ant jbosslogsigning - Copy dist/ejbcalogsigning.jar to jboss.home/server/default/lib - Configure jboss.home/server/default/conf/log4j.xml, according to below - Create the script that is to be run (see example below) - Start JBoss As for the SigningDailyRollingFileAppender above, replace the default section in log4j.xml with: ----- ----- Where /home/jboss/log-sign-tsa-jboss.sh is your script that should be run to do the signing. signlog.sh must take one argument, which is the file to sign. And the new shell script for verification (or manual signing). log-sign-tsa-jboss.sh ----- #!/bin/bash TSACLIENTDIR=/usr/local/signserver/dist-client TSAURL="http://127.0.0.1:8080/signserver/tsa?signerId=1" SCRIPTNAME=`basename $0` FILE="$1" SIGNATUREFILE="$FILE.tsa" java -jar "$TSACLIENTDIR/timeStampClient.jar" -url $TSAURL -infile $FILE -outrep $SIGNATUREFILE -base64 exit 0 ----- In the script you must replace TSACLIENTDIR with the path to your TSA client and TSAURL with the url to your TSA. Verifying timestamps ==================== You can verify time stamps with a time stamp client, for example the one that comes with PrimeKeys TSA. After building 'signserver' the timeStampClient.jar and other needed jar files is in the dist-client directory. > java -jar timeStampClient.jar -verify -signerfile tsa1.pem -inrep server.log.2006-07-28-18-58.tsp Token was validated successfully. Token was generated on: Fri Jul 28 18:59:00 CEST 2006 Token hash alg: SHA1 MessageDigest=1a02dc7e05d06df45d2e0f74da502513852064d5 > sha1sum server.log.2006-07-28-18-58 1a02dc7e05d06df45d2e0f74da502513852064d5 *server.log.2006-07-28-18-58 If the hashes from the time stamp token (MessageDigest) matches the hash from sha1sum, the file is verified, i.e. has not been changed since the time stamp token was generated. Internal log signing in EJBCA ============================= There is a mechanism for internal log signing in EJBCA. This mechanism stores an additional protection row in the table TableProtectData, containing a HMAC of the row written to LogEntryData. If enabled the protection is verified and displayed when viewing log entrys in the admin-GUI. The current implementation is rather simple: - The hmac key is configured in protection.properties - It is possible to encrypt the key using an internal encryption key, so that it is not accidentaly visible to administrators. - If the hmac key is not available, protection is disabled. - The mechanism is extensible, so other signing mechanisms can be added later, without the need to re-sign old entries. Errors creating protection info or verifying is logged in the server.log begining with: PROTECT ERROR This information can be used to monitor logs for protection errors. To enable, you must add a file conf/protection.properties as defined below, and then doing 'ant clean', 'and deploy'. There is a conf/protection.properties.sample that you can copy. Don't forget, enabling log protection degrades performance a bit! See HOWTO-database.txt for some indexes that might speed things up a little bit again. ----- # # $Id: HOWTO-logsigning.txt,v 1.19 2006-12-29 11:33:51 anatom Exp $ # # This is a sample file to override properties used # during development (or deployment) of EJBCA # # You should store this file as protection.properties (in the same place as ejbca.properties) # and customize at will. # # Enable protection altogether # Default: false #protection.enabled=false # Enable protection of internal database logs # Default: false #protection.logprotect=false # Enable protection of internal CertificateData store # Default: false #protection.certprotect=false # Should we warn when verifying if a protection row is missing? # Default: true #protection.warnonmissingrow=true # Reference to a key to be read, mostly enabled for future use when several different keys can be used # for different types of protection entries. # Default: key1 #protection.keyref=key1 # The key referenced above, can be a clear text key, an encrypted key or some other type, # depending on the value of protection.keytype. # Default: foo123 #protection.key=foo123 # The type of key, to be able to decode the value and use it. # Supported types are: # SOFT_HMAC, for a clear text password # ENC_SOFT_HMAC, for an encrypted password, created with 'bin/ejbca.sh encryptpwd' # Default: SOFT_HMAC #protection.keytype=SOFT_HMAC -----