Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Some enterprise clients require that all email addresses be encrypted at rest (i.e., the actual values stored in the database must be encrypted). I've put together something that seems to do the trick, based on quick testing. But I want to know if anything looks glaringly missing or wrong?

One thing I'm reasonably sure of: there are no filters or hooks in the WP_User class that allow you to control what it returns. So any plugins that use that class directly will probably break. But is there anything in core that'll break because of this? Am I taking the wrong approach altogether here?

(For the sake if simplicity, I'm just base64encoding values in this example. I realize this is not encryption :))

<?php

    /*
    Plugin Name: Email Encryption at rest.
    Version: 1.0
    Description: Testing encryption at rest for email addresses
    */

    /**
     * Intercept user queries, and fix 'em if necessary
     */
    function wpsx_pre_user_query( $obj_query ) {

        // Trim off the *s. These seem to be added automatically to the query.
        $search = isset( $obj_query->query_vars['search'] ) ? trim( $obj_query->query_vars['search'], '*' ) : '';

        // Figure out if the search term is an email address. If so, encrypt it.
        // This precludes partial matches on emails address searches
        if( is_email( $search ) )
            $obj_query->query_where = str_replace( $search, wpsx_encrypt_email( $search ), $obj_query->query_where);

    }
    add_action( 'pre_user_query', 'wpsx_pre_user_query' );

    /**
     * Custom version of the get_user_by() function,
     * which is used by a lot of things to get user data.
     */
    if ( !function_exists('get_user_by') ) {

        function get_user_by( $field, $value ) {

            // If we're checking against an email address, be sure we're checking the encrypted version
            if( 'email' == $field )
                $value = wpsx_encrypt_email( $value );

            $userdata = WP_User::get_data_by( $field, $value );

            if ( !$userdata )
                return false;

            $user = new WP_User;
            $user->init( $userdata );

            // If we pulled an email out of the DB that looks encrypted, decrypt it
            if( isset( $user->user_email ) && !is_email( $user->user_email ) )
                $user->user_email = wpsx_decrypt_email( $user->user_email );

            return $user;
        }

    }

    /**
     * When the current user is set, make sure we decrypt any email the obj contains
     */
    function wpsx_set_current_user( $user ) {

        global $current_user;

        if( ( $current_user instanceof WP_User ) && isset( $current_user->data->user_email ) && !is_email( $current_user->data->user_email ) )
            $current_user->data->user_email = wpsx_decrypt_email( $current_user->data->user_email );

    }
    add_action( 'set_current_user', 'wpsx_set_current_user' );

    /**
     * Encrypt the given email address, if necessary
     */
    function wpsx_encrypt_email( $email ) {

        if( !is_email( $email ) )
            return $email;

        return base64_encode( $email );

    }
    add_filter( 'pre_comment_author_email', 'wpsx_encrypt_email' );
    add_filter( 'pre_user_email', 'wpsx_encrypt_email' );

    /**
     * Decrypt the given email address, if necessary
     */
    function wpsx_decrypt_email( $email ) {

        if( is_email( $email ) )
            return $email;

        return base64_decode( $email );

    }
    add_filter( 'the_author_email', 'wpsx_decrypt_email' );
    add_filter( 'comment_author_email', 'wpsx_decrypt_email' );
    add_filter( 'user_email', 'wpsx_decrypt_email', 1 );

?>
share|improve this question
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.