Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Wordpress encrypt usermeta data database
<?php
/**
* Created by PhpStorm.
* User: Muhammad
* Date: 05/07/2016
* Time: 01:20 PM
*/
add_filter('get_user_metadata', 'decrypt_user_meta',10,4);
add_filter('add_user_metadata', 'encrypt_user_meta',10,5);
add_filter('update_user_metadata', 'encrypt_user_meta_in_update',10,5);
function get_meta_keys_to_encrypt(){
return array('first_name', 'last_name', 'display_name' ); // meta_key s from wp_usermeta table that you want to encrypte
}
function decrypt_user_meta($value = null ,$object_id,$meta_key,$single){
if(!in_array($meta_key, get_meta_keys_to_encrypt()))
return null;
$meta_cache = wp_cache_get($object_id, 'user' . '_meta');
if ( !$meta_cache ) {
$meta_cache = update_meta_cache( 'user', array( $object_id ) );
$meta_cache = $meta_cache[$object_id];
}
if ( ! $meta_key ) {
return decrypt($meta_cache);
}
if ( isset($meta_cache[$meta_key]) ) {
if ( $single )
return decrypt(maybe_unserialize( $meta_cache[$meta_key][0]));
else
return array_map('maybe_unserialize', decrypt($meta_cache[$meta_key]));
}
if ($single)
return '';
else
return array();
}
function encrypt_user_meta($value = null ,$object_id,$meta_key, $meta_value, $unique){
if(!in_array($meta_key, get_meta_keys_to_encrypt()))
return null;
global $wpdb;
$table = _get_meta_table( 'user' );
$column = sanitize_key('user' . '_id');
if ( $unique && $wpdb->get_var( $wpdb->prepare(
"SELECT COUNT(*) FROM $table WHERE meta_key = %s AND $column = %d",
$meta_key, $object_id ) ) )
return false;
$_meta_value = $meta_value;
$meta_value = encrypt(maybe_serialize( $meta_value ));
/**
* Fires immediately before meta of a specific type is added.
*
* The dynamic portion of the hook, `$meta_type`, refers to the meta
* object type (comment, post, or user).
*
* @since 3.1.0
*
* @param int $object_id Object ID.
* @param string $meta_key Meta key.
* @param mixed $meta_value Meta value.
*/
do_action( "add_user_meta", $object_id, $meta_key, $_meta_value );
$result = $wpdb->insert( $table, array(
$column => $object_id,
'meta_key' => $meta_key,
'meta_value' => $meta_value
) );
if ( ! $result )
return false;
$mid = (int) $wpdb->insert_id;
wp_cache_delete($object_id, 'user' . '_meta');
/**
* Fires immediately after meta of a specific type is added.
*
* The dynamic portion of the hook, `$meta_type`, refers to the meta
* object type (comment, post, or user).
*
* @since 2.9.0
*
* @param int $mid The meta ID after successful update.
* @param int $object_id Object ID.
* @param string $meta_key Meta key.
* @param mixed $meta_value Meta value.
*/
do_action( "added_user_meta", $mid, $object_id, $meta_key, $_meta_value );
return $mid;
}
function encrypt_user_meta_in_update($value = null ,$object_id,$meta_key, $meta_value, $prev_value){
if(!in_array($meta_key, get_meta_keys_to_encrypt()))
return null;
global $wpdb;
$meta_type = 'user';
$table = _get_meta_table( 'user' );
$column = sanitize_key('user' . '_id');
$id_column = 'umeta_id';
$raw_meta_key = $meta_key;
$passed_value = $meta_value;
// Compare existing value to new value if no prev value given and the key exists only once.
if ( empty($prev_value) ) {
$old_value = get_metadata('user', $object_id, $meta_key);
if ( count($old_value) == 1 ) {
if ( $old_value[0] === $meta_value )
return false;
}
}
$meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT $id_column FROM $table WHERE meta_key = %s AND $column = %d", $meta_key, $object_id ) );
if ( empty( $meta_ids ) ) {
return add_metadata( $meta_type, $object_id, $raw_meta_key, $passed_value );
}
$_meta_value = $meta_value;
$meta_value = maybe_serialize( encrypt($meta_value ));
$data = compact( 'meta_value' );
$where = array( $column => $object_id, 'meta_key' => $meta_key );
if ( !empty( $prev_value ) ) {
$prev_value = maybe_serialize($prev_value);
$where['meta_value'] = encrypt($prev_value);
}
foreach ( $meta_ids as $meta_id ) {
/**
* Fires immediately before updating metadata of a specific type.
*
* The dynamic portion of the hook, `$meta_type`, refers to the meta
* object type (comment, post, or user).
*
* @since 2.9.0
*
* @param int $meta_id ID of the metadata entry to update.
* @param int $object_id Object ID.
* @param string $meta_key Meta key.
* @param mixed $meta_value Meta value.
*/
do_action( "update_{$meta_type}_meta", $meta_id, $object_id, $meta_key, $_meta_value );
if ( 'post' == $meta_type ) {
/**
* Fires immediately before updating a post's metadata.
*
* @since 2.9.0
*
* @param int $meta_id ID of metadata entry to update.
* @param int $object_id Object ID.
* @param string $meta_key Meta key.
* @param mixed $meta_value Meta value.
*/
do_action( 'update_postmeta', $meta_id, $object_id, $meta_key, $meta_value );
}
}
$result = $wpdb->update( $table, $data, $where );
if ( ! $result )
return false;
wp_cache_delete($object_id, $meta_type . '_meta');
foreach ( $meta_ids as $meta_id ) {
/**
* Fires immediately after updating metadata of a specific type.
*
* The dynamic portion of the hook, `$meta_type`, refers to the meta
* object type (comment, post, or user).
*
* @since 2.9.0
*
* @param int $meta_id ID of updated metadata entry.
* @param int $object_id Object ID.
* @param string $meta_key Meta key.
* @param mixed $meta_value Meta value.
*/
do_action( "updated_{$meta_type}_meta", $meta_id, $object_id, $meta_key, $_meta_value );
if ( 'post' == $meta_type ) {
/**
* Fires immediately after updating a post's metadata.
*
* @since 2.9.0
*
* @param int $meta_id ID of updated metadata entry.
* @param int $object_id Object ID.
* @param string $meta_key Meta key.
* @param mixed $meta_value Meta value.
*/
do_action( 'updated_postmeta', $meta_id, $object_id, $meta_key, $meta_value );
}
}
return true;
}
function encrypt($src){
if(is_array($src)){
foreach ($src as $key => $val)
$src[$key] = encrypt_value($val);
return $src;
}else
return encrypt_value($src);
}
function encrypt_value($data){
$password = "SuperSecretEncryptionKey";
$salt = substr(md5(mt_rand(), true), 8);
$key = md5($password . $salt, true);
$iv = md5($key . $password . $salt, true);
$ct = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv);
return base64_encode('Salted__' . $salt . $ct);
}
function decrypt($src){
if(is_array($src)){
foreach ($src as $key => $val)
$src[$key] = decrypt_value($val);
return $src;
}else
return decrypt_value($src);
}
function decrypt_value($data){
$password = "SuperSecretEncryptionKey";
$data = base64_decode($data);
$salt = substr($data, 8, 8);
$ct = substr($data, 16);
$key = md5($password . $salt, true);
$iv = md5($key . $password . $salt, true);
$pt = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ct, MCRYPT_MODE_CBC, $iv);
return trim($pt);
}
@muhammad-naderi

This comment has been minimized.

Copy link
Owner Author

@muhammad-naderi muhammad-naderi commented Jul 12, 2016

based on Wordpress 4.5.3

@hiteskj

This comment has been minimized.

Copy link

@hiteskj hiteskj commented Jul 31, 2017

Where we have to add this script. And how to encrypt the old user data.

@Andrew5D

This comment has been minimized.

Copy link

@Andrew5D Andrew5D commented Aug 3, 2018

Because WooCommerce and WooCommerce's Subscriptions plugin replicate user data we're looking for something that extends encryption to wp_post and wp_postmeta.

How would encrypting Wordpress impact on something like WooCommerce and WooCommerce's Subscriptions plugin that heavily rely on wp_users, wp_post and wp_postmeta.

I suspect that they would be all-sorts of issues with the various Hooks, Filters and Classes that these plugins make available to us, so any custom PHP scripts will likely be impacted.

I also suspect that the WooCommerce and Subscriptions Wordpress Dashboard would also fall over.

May I ask your thoughts on this please.

Thanks

Andrew

@LourensThalen

This comment has been minimized.

Copy link

@LourensThalen LourensThalen commented Jun 20, 2019

@Andrew5D - from what I can see, this amends the regular get_user_metadata and set_user_metadata functions. When WooCommerce fetches data, they use these functions, most of the time, so they get the real values. It's possible to also amend the WooCommerce functions so they would also encrypt/decrypt when getting or setting stuff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment