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