Skip to content

Instantly share code, notes, and snippets.

@muhammad-naderi
Created July 12, 2016 11:57
  • Star 17 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save muhammad-naderi/1d1453258ea3f30f5fa6b5c8f9275341 to your computer and use it in GitHub Desktop.
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
Copy link
Author

based on Wordpress 4.5.3

@hiteskj
Copy link

hiteskj commented Jul 31, 2017

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

@Andrew5D
Copy link

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
Copy link

@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