Enigma: Optional server-side key generation

pull/291/head
Aleksander Machniak 9 years ago
parent 6f249b0e38
commit a0dfcb14a8

@ -17,7 +17,8 @@ Implemented features:
+ PGP: signatures verification + PGP: signatures verification
+ PGP: messages decryption + PGP: messages decryption
+ PGP: Sending of encrypted/signed messages + PGP: Sending of encrypted/signed messages
+ PGP: keys management UI (keys import and delete) + PGP: keys management UI (key import, delete)
+ PGP: key generation (client- or server-side)
+ Handling of PGP keys attached to incoming messages + Handling of PGP keys attached to incoming messages
+ User preferences to disable plugin features + User preferences to disable plugin features
@ -28,7 +29,6 @@ TODO (must have):
TODO (later): TODO (later):
------------- -------------
- Handling of big messages with temp files - Handling of big messages with temp files
- Server-side keys generation (warning: no-entropy issue, max_execution_time issue)
- Key info in contact details page (optional) - Key info in contact details page (optional)
- Extended key management: - Extended key management:
- disable, - disable,

@ -28,3 +28,14 @@ $config['enigma_encrypt_all'] = false;
// Default for how long to store private key passwords (in minutes). // Default for how long to store private key passwords (in minutes).
// When set to 0 passwords will be stored for the whole session. // When set to 0 passwords will be stored for the whole session.
$config['enigma_password_time'] = 5; $config['enigma_password_time'] = 5;
// Enables server-side keys generation which would be used
// if user browser does not support web-crypto features.
//
// WARNING: Key generation requires true random numbers, and as such can be
// slow. If the operating system runs out of entropy, key generation will
// block until more entropy is available.
//
// To solve that a hardware entropy generator or
// an entropy gathering daemon may be installed (e.g. randomsound).
$config['enigma_keygen_server'] = false;

@ -97,7 +97,7 @@ rcube_webmail.prototype.enigma_key_create_save = function()
openpgp.generateKeyPair(options).then(function(keypair) { openpgp.generateKeyPair(options).then(function(keypair) {
// success // success
post = {_a: 'import', _keys: keypair.privateKeyArmored}; var post = {_a: 'import', _keys: keypair.privateKeyArmored};
// send request to server // send request to server
rcmail.http_post('plugin.enigmakeys', post, lock); rcmail.http_post('plugin.enigmakeys', post, lock);
@ -108,8 +108,13 @@ rcube_webmail.prototype.enigma_key_create_save = function()
}); });
} }
// generate keys on the server // generate keys on the server
else if (rcmail.env.enigma_keygen_server) {
lock = this.set_busy(true, 'enigma.keygenerating');
options = {_a: 'generate', _user: user, _password: password, _size: size};
rcmail.http_post('plugin.enigmakeys', options, lock);
}
else { else {
// @TODO rcmail.display_message(rcmail.gettext('enigma.keygennosupport'), 'error');
} }
}; };

@ -67,7 +67,7 @@ abstract class enigma_driver
* *
* @return mixed Import status array or enigma_error * @return mixed Import status array or enigma_error
*/ */
abstract function import($content, $isfile=false); abstract function import($content, $isfile = false);
/** /**
* Keys listing. * Keys listing.
@ -76,7 +76,7 @@ abstract class enigma_driver
* *
* @return mixed Array of enigma_key objects or enigma_error * @return mixed Array of enigma_key objects or enigma_error
*/ */
abstract function list_keys($pattern=''); abstract function list_keys($pattern = '');
/** /**
* Single key information. * Single key information.
@ -90,7 +90,7 @@ abstract class enigma_driver
/** /**
* Key pair generation. * Key pair generation.
* *
* @param array Key/User data * @param array Key/User data (name, email, password, size)
* *
* @return mixed Key (enigma_key) object or enigma_error * @return mixed Key (enigma_key) object or enigma_error
*/ */

@ -188,8 +188,32 @@ class enigma_driver_gnupg extends enigma_driver
return $list; return $list;
} }
/**
* Key pair generation.
*
* @param array Key/User data (user, email, password, size)
*
* @return mixed Key (enigma_key) object or enigma_error
*/
public function gen_key($data) public function gen_key($data)
{ {
try {
$keygen = new Crypt_GPG_KeyGenerator(array(
'homedir' => $this->homedir,
// 'binary' => '/usr/bin/gpg2',
// 'debug' => true,
));
$key = $keygen
->setExpirationDate(0)
->setPassphrase($data['password'])
->generateKey($data['user'], $data['email']);
return $this->parse_key($key);
}
catch (Exception $e) {
return $this->get_error_from_exception($e);
}
} }
public function delete_key($keyid) public function delete_key($keyid)
@ -263,12 +287,15 @@ class enigma_driver_gnupg extends enigma_driver
$data['bad'] = $e->getBadPassphrases(); $data['bad'] = $e->getBadPassphrases();
$data['missing'] = $e->getMissingPassphrases(); $data['missing'] = $e->getMissingPassphrases();
} }
else if ($e instanceof Crypt_GPG_NoDataException) else if ($e instanceof Crypt_GPG_NoDataException) {
$error = enigma_error::E_NODATA; $error = enigma_error::E_NODATA;
else if ($e instanceof Crypt_GPG_DeletePrivateKeyException) }
else if ($e instanceof Crypt_GPG_DeletePrivateKeyException) {
$error = enigma_error::E_DELKEY; $error = enigma_error::E_DELKEY;
else }
else {
$error = enigma_error::E_INTERNAL; $error = enigma_error::E_INTERNAL;
}
$msg = $e->getMessage(); $msg = $e->getMessage();

@ -926,6 +926,29 @@ class enigma_engine
return $result; return $result;
} }
/**
* PGP keys pair generation.
*
* @param array Key pair parameters
*
* @return mixed enigma_key or enigma_error
*/
function generate_key($data)
{
$this->load_pgp_driver();
$result = $this->pgp_driver->gen_key($data);
if ($result instanceof enigma_error) {
rcube::raise_error(array(
'code' => 600, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Enigma plugin: " . $result->getMessage()
), true, false);
}
return $result;
}
/** /**
* PGP keys/certs importing. * PGP keys/certs importing.
* *

@ -59,6 +59,10 @@ class enigma_ui
$this->key_import(); $this->key_import();
break; break;
case 'generate':
$this->key_generate();
break;
case 'create': case 'create':
$this->key_create(); $this->key_create();
break; break;
@ -483,6 +487,45 @@ class enigma_ui
return $out; return $out;
} }
/**
* Server-side key pair generation handler
*/
private function key_generate()
{
$user = rcube_utils::get_input_value('_user', rcube_utils::INPUT_POST, true);
$pass = rcube_utils::get_input_value('_password', rcube_utils::INPUT_POST, true);
$size = (int) rcube_utils::get_input_value('_size', rcube_utils::INPUT_POST);
if ($size > 4096) {
$size = 4096;
}
$ident = rcube_mime::decode_address_list($user, 1, false);
if (empty($ident)) {
$this->rc->output->show_message('enigma.keygenerateerror', 'error');
$this->rc->output->send();
}
$this->enigma->load_engine();
$result = $this->enigma->engine->generate_key(array(
'user' => $ident[1]['name'],
'email' => $ident[1]['mailto'],
'password' => $pass,
'size' => $size,
));
if ($result instanceof enigma_key) {
$this->rc->output->command('enigma_key_create_success');
$this->rc->output->show_message('enigma.keygeneratesuccess', 'confirmation');
}
else {
$this->rc->output->show_message('enigma.keygenerateerror', 'error');
}
$this->rc->output->send();
}
/** /**
* Key generation page handler * Key generation page handler
*/ */
@ -494,6 +537,8 @@ class enigma_ui
'keyform' => array($this, 'tpl_key_create_form'), 'keyform' => array($this, 'tpl_key_create_form'),
)); ));
$this->rc->output->set_env('enigma_keygen_server', $this->rc->config->get('enigma_keygen_server'));
$this->rc->output->set_pagetitle($this->enigma->gettext('keygenerate')); $this->rc->output->set_pagetitle($this->enigma->gettext('keygenerate'));
$this->rc->output->send('enigma.keycreate'); $this->rc->output->send('enigma.keycreate');
} }
@ -538,7 +583,8 @@ class enigma_ui
$this->rc->output->add_gui_object('keyform', $attrib['id']); $this->rc->output->add_gui_object('keyform', $attrib['id']);
$this->rc->output->add_label('enigma.keygenerating', 'enigma.formerror', $this->rc->output->add_label('enigma.keygenerating', 'enigma.formerror',
'enigma.passwordsdiffer', 'enigma.keygenerateerror', 'enigma.nonameident'); 'enigma.passwordsdiffer', 'enigma.keygenerateerror', 'enigma.nonameident',
'enigma.keygennosupport');
return $this->rc->output->form_tag(array(), $table->show($attrib)); return $this->rc->output->form_tag(array(), $table->show($attrib));
} }

@ -98,5 +98,6 @@ $messages['passwordsdiffer'] = 'Passwords do not match!';
$messages['nonameident'] = 'Idenity must have a user name defined!'; $messages['nonameident'] = 'Idenity must have a user name defined!';
$messages['keygenerateerror'] = 'Failed to generate a key pair'; $messages['keygenerateerror'] = 'Failed to generate a key pair';
$messages['keygeneratesuccess'] = 'A key pair generated and imported successfully.'; $messages['keygeneratesuccess'] = 'A key pair generated and imported successfully.';
$messages['keygennosupport'] = 'Your web browser does not support cryptography. Unable to generate a key pair!';
?> ?>

Loading…
Cancel
Save