Encryption Transmission

From OpenEMR Project Wiki
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Data needs to encrypted "at rest" and "in motion", per HIPAA.

A good document describing recent changes to HIPAA in the HITECH part of the ARRA is http://www.passionforsubro.com/hipaa/hhs-publishes-hitech-hipaa-guidance/ .

The easiest way to encrypt data "at rest" is to use an encrypted file system on the server running the health care application. This is intended to protect the health care information in the event the server or the computer containing this information is stolen.

Encrypted transmission is relatively easy using SSL and can be implemented with Public Private key encryption methods. A method for doing this was worked out during a discussion between Fred Trotter, Justin Doiel and Sam Bowen at the FOSS Healthcare conference in Houston, Texas July 31 through August 2009.

Fred Trotter went on to write the basics of how to do this in a general way and shared them with our group.



From the FOSS conference in Houston August, 2009 – Fred Trotter. OpenEMR was out in force at the conference and we had some interesting discussions about the best way to make php applications more secure. The following code is in php but the theory applies to any electronic health record. The wonderful thing about this method is that Apache does all of the heavy lifting for you.

<?php
        //first we force ssl, which is required for x509 certificates.
        // you do not have to use self signed server certificates either, 
        //since cacert.org will also provide cheap server certs....
        //another promising configuration that I have tried is to use is 
        //to have port 80 forward to a file that does nothing but link to
        // the cacert.org root certificate, and set a cookie. So it forces
        //you to install the root cert in firefox and then autoforwards 
        //you to https the rest of the time, ensuring that you never get 
        //a https error... I might post code for that later.
 
        if($_SERVER['SERVER_PORT'] == '80'){
                $new_url = 'https://'. $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
                header("refresh: 0; url=$new_url");
                die();
        }
 
        //now we can access the SSL client variables provided to us 
        //by apache:

        if(
                isset($_SERVER['SSL_CLIENT_VERIFY']) &&
                isset($_SERVER['SSL_CLIENT_S_DN_Email'])
        ){
                //here we know that client certs have been enabled 
                //and that we the client has attempted to submit one.
 
                if($_SERVER['SSL_CLIENT_VERIFY'] == 'SUCCESS'){
 
                // here we know that the client cert if valid.
 
                        $full_name = $_SERVER['SSL_CLIENT_S_DN_CN'];
                        list($cert_first_name,$cert_last_name) = split(' ',strtolower($full_name));
                        $cert_email = $_SERVER['SSL_CLIENT_S_DN_Email'];
                        // echo "cert first = $cert_first_name and 
                        //cert_last = $cert_last_name email = $email";
                        // a test echo here that shows that we know the first
                        //and last name and the email from the valid cacert
                        //certificate...magic happens
 
                        // here you can put code to do whatever you want, 
                        //and be sure that you have a connection with a 
                        //browser that has a private key from someone who 
                        //has been assured by the CACert.org web of trust 
                        //process.  This should be combined with a password 
                        //to be sure that someone has not hijacked a browser.
                        //You could do signing using a standard hash here, 
                        //along with username and certificate data and be 
                        //sure that you are at the valid end of a x509 process
                        // for that purpose.
 
                }else{// end SSL_CLIENT_VERIFY = SUCCESS if statement
 
                        // you had a certificate but it was not valid... make an
                        // error..
 
                }
 
        }else{// end SSL_CLIENT_VERIFY isset
 
                // apache is not properly configured to require certificates
                //and/or one was not supplied make an error..
 
        }
 
 
                //this script could be re-written to either be a class or
                //globally included file
 
?>


Of course, none of this works without an apache configuration!!

<VirtualHost 10.10.10.10:80>
 
# another fine way to enforce https only.
 
        ServerName example.com:80
        AddType application/x-httpd-php .php .phtml .php3
        DocumentRoot "/var/www/html/example/"
 
        <Directory "/var/www/html/example/">
        #The following rewrite just forces everything to https!!!
        RewriteEngine On
        RewriteCond %{HTTPS} off
        RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
        </Directory>

</VirtualHost>
 
 
<VirtualHost 10.10.10.10:443>
        ServerName example.com:443
 
        # Standard stuff
        ErrorLog logs/ssl_error_log
        LogLevel warn
        SSLEngine on
        SSLProtocol all -SSLv2
        SSLCipherSuite 
        SSLOptions +StdEnvVars 
                nokeepalive ssl-unclean-shutdown \
        CustomLog logs/ssl_request_log \
               "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
 
        # end standard stuff
 
 
        # the certificate that CACert.org has signed...
        SSLCertificateFile /etc/pki/tls/certs/example.com.crt
        # my super secret private key
        SSLCertificateKeyFile /etc/pki/tls/private/example.com.key
 
        # not that I can use the directory command to protect a
        # single file!!
        <Directory "/var/www/html/example/protected_file.php">
                # requries a client certificate
                SSLVerifyClient require
                SSLVerifyDepth 2
                # in order to validate the client certificates I need to have
                # a copy of the CAcert.org root certificate
                SSLCACertificateFile /etc/pki/tls/certs/cacert.crt
                SSLOptions +StdEnvVars
         </Directory>
</VirtualHost>