-
-
Save timnashcouk/dd1ff318489f6bfd8743 to your computer and use it in GitHub Desktop.
<?php | |
/** | |
* Plugin Name: WP PGP Email | |
* Version: 0.1 | |
* Description: Provides mechanism to encrypt outgoing email using PGP | |
* Author: Tim Nash | |
* Author URI: https://timnash.co.uk | |
* Plugin URI: https://timnash.co.uk/wordpress-pgp-email | |
* | |
* | |
* License: GPLv2 or later | |
* | |
* | |
* This program is free software; you can redistribute it and/or | |
* modify it under the terms of the GNU General Public License | |
* as published by the Free Software Foundation; either version 2 | |
* of the License, or (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program; if not, write to the Free Software | |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
*/ | |
/** | |
* Don't call this file directly. | |
*/ | |
if ( ! class_exists( 'WP' ) ) { | |
die(); | |
} | |
class wpPGP{ | |
function __construct() | |
{ | |
add_action('init', array($this, 'init')); | |
} | |
function init() | |
{ | |
//Add email filter | |
add_filter('wp_mail', array($this, 'filter_email')); | |
//Add Form actions for user profile | |
add_action('show_user_profile', array($this, 'add_profile_field')); | |
add_action('edit_user_profile', array($this, 'add_profile_field')); | |
add_action('personal_options_update', array($this, 'save_profile_field')); | |
add_action('edit_user_profile_update', array($this, 'save_profile_field')); | |
} | |
//Get key for user or return false if no key is found | |
static function get_key( $user_id = false ) | |
{ | |
if( !$user_id ) return null; | |
return get_user_meta( $user_id, 'pgp_key', true ); | |
} | |
//Set a key for a specific user, overriding any existing key. | |
static function set_key( $user_id = false, $key = false ) | |
{ | |
if( !$user_id || !$key ) return null; | |
//@todo validate key | |
return update_user_meta( $user_id, 'pgp_key', $key); | |
} | |
//Remove key from database, if $match = true only remove if $key matches existing key otherwise error | |
static function remove_key( $user_id = false, $key = false, $match = false ) | |
{ | |
if( !$user_id || !$key ) return null; | |
$check_key = FALSE; | |
if($match) | |
{ | |
$check_key = $key; | |
} | |
return delete_user_meta( $user_id, 'pgp_key', $check_key ); | |
} | |
//Encrypt contents using users key, if force is set to false and no key found return unencrypted content, if set to true return false. | |
static function encrypt_contents( $user_id = false, $contents = false, $force = false ) | |
{ | |
if( !$user_id || !$contents ) return null; | |
require_once 'libs/GPG.php'; | |
$gpg = new GPG(); | |
$key = self::get_key( $user_id ); | |
if(!$key){ | |
if($force) | |
{ | |
return false; | |
} | |
else | |
{ | |
return $contents; | |
} | |
} | |
//we have a key and contents, let's encrypt it | |
// create an instance of a GPG public key object based on ASCII key | |
$pub_key = new GPG_Public_Key($key); | |
// using the key, encrypt your plain text using the public key | |
return $gpg->encrypt($pub_key,$contents); | |
} | |
static function validate_key_type( $key ) | |
{ | |
var_dump($key); | |
require_once 'libs/GPG.php'; | |
$gpg = new GPG(); | |
$pub_key = new GPG_Public_Key($key); | |
return $pub_key->GetKeyType(); | |
} | |
//Filters WP_MAIL and encrypts content if being sent to a user with PGP key in the DB | |
function filter_email( $args ) | |
{ | |
//Check if the email is being sent to a user | |
$user = get_user_by( 'email', $args['to'] ); | |
if($user){ | |
if(self::get_key( $user->ID )) | |
{ | |
if($args['message']) | |
{ | |
$encrypted_contents = self::encrypt_contents( $user->ID, $args['message']); | |
if($encrypted_contents) $args['message'] = $encrypted_contents; | |
} | |
//For people using the Mandril plugin | |
elseif($args['html']) | |
{ | |
$encrypted_contents = self::encrypt_contents( $user->ID, $args['html']); | |
if($encrypted_contents) $args['html'] = $encrypted_contents; | |
} | |
} | |
} | |
return $args; | |
} | |
/* | |
* | |
* Admin Views | |
* These really should be in there own class but for this example we will leave them here | |
* | |
*/ | |
function add_profile_field( $user ) | |
{ | |
$pgp_key = self::get_key( $user->ID); | |
//Well this is unpleasant but very WordPressy | |
?> | |
<h3><?php _e('Email Encryption', 'wp-pgp-email'); ?></h3> | |
<table class="form-table"> | |
<tbody> | |
<tr> | |
<th> | |
<label for="pgp"><?php _e('Public PGP Key','wp-pgp-email'); ?></label> | |
</th> | |
<td> | |
<textarea name="pgp" id="pgp" rows="5" cols="30"><?php if($pgp_key) echo $pgp_key; ?></textarea> | |
<br> | |
<?php if($pgp_key){ ?> | |
<span class="description">KeyType: <?php echo self::validate_key_type($pgp_key); ?></span> | |
<?php } ?> | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
<?php | |
} | |
function save_profile_field( $user_id ) | |
{ | |
if ( !current_user_can( 'edit_user', $user_id ) ) | |
return false; | |
$key = $_POST['pgp']; | |
return self::set_key( $user_id, $key ); | |
} | |
} | |
$wp_pgp_email = new wpPGP; |
Hi,
Really useful code, thanks. However I've found a bug that stops it working. The incoming parameter to the encrypt_contents function is $contents plural. However the return on line 110 encrypts the variable $content (singular). This seems to result in a corrupt block that I can't decrypt.
Hope that saves someone else the head scratching I've just gone through!
Cheers,
--Toby
This is a great general pattern but is missing a few key pun intended) features and WordPress integrations. Have a look at the WP PGP Encrypted Emails plugin for a more complete solution to protect outgoing emails.
@meitar the mentioned plugin uses the same library, take a look at the code in the subversion repository.
Anyway, I highly recommend https://github.com/singpolyma/openpgp-php as there are many security related issues in php-gpg (ECB mode for example instead of CBC)
Thanks Daniel! As you probably know, WP PGP Encrypted Emails is now using the library you suggested. :)
Required lib https://github.com/jasonhinkle/php-gpg