- Posts: 103
- Thank you received: 5
Ask the community, share ideas, and connect with other LimeSurvey users!
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048 openssl rsa -pubout -in private_key.pem -out public_key.pem
[...]
4. Open a terminal in that directory.
5. Execute php decrypt.php > data.csv
php decrypt.php > data.csv
Please enter the path to the private key file: "" Warning: file_get_contents(): Filename cannot be empty in C:\LSEncryption\Test\decrypt.php on line 42
php decrypt.php > data.csv
php encrypted.cmd.txt > data.csv
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048 openssl rsa -pubout -in private_key.pem -out public_key.pem
socius wrote: IMaybe I ask the question here: do the following lines generate a key that can be used by LSEncrypt? (or is there something wrong with algorithm, length etc.)
if (isset($argv[1])) { $privateKey = openssl_pkey_get_private(file_get_contents($argv[1])); } else { echo "Please enter the path to the private key file: "; $file = rtrim(fgets($stdin)); echo '"' . $file . '"' . PHP_EOL; $key = file_get_contents($file); $privateKey = openssl_pkey_get_private($key); }
php encrypted.cmd.txt private_key.pem > data.csv
php decrypt.php private_key.pem encrypted.cmd.txt > data.csv
@echo off php -r "$f = fopen('%~0', 'rb'); fseek($f, 117); $code = stream_get_contents($f); eval($code); " exit function decryptResponses($privateKey, $data, $handle) { $first = true; foreach (explode('.', $data) as $encryptedResponse) { echo "Decrypting response...\n"; $decryptedKey = ''; $allData = base64_decode($encryptedResponse); $encryptedKey = substr($allData, 0, 128); if (openssl_private_decrypt($encryptedKey, $decryptedKey, $privateKey)) { $iv = substr($encryptedKey, 0, mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC)); $data = mcrypt_decrypt(MCRYPT_BLOWFISH, $decryptedKey, substr($allData, 128), MCRYPT_MODE_CBC, $iv); $response = json_decode(trim($data), true); if ($first) { fputcsv($handle, array_keys($response)); $first = false; } fputcsv($handle, $response); unset($response); } else { echo openssl_error_string() . "\n"; } } } $stdin = fopen('php://stdin', 'r'); if (isset($argv[1])) { $privateKey = openssl_pkey_get_private(file_get_contents($argv[1])); } else { echo "Please enter the path to the private key file: "; $file = rtrim(fgets($stdin)); echo '"' . $file . '"' . PHP_EOL; $key = file_get_contents($file); $privateKey = openssl_pkey_get_private($key); } $handle = fopen('php://stdout', 'w'); /** * The builder script will add the appropriate decrypt command to the end * of the file. DO NOT ADD A CLOSING TAG. */ decryptResponses($privateKey, 'kcZRc1h9wojA6clxkPI+t4Y1e/CKAsmerNcLr+qeoDxJ89GvURYBetPltQOEukQBkU2uIIMMpZNk/ElyJMWu57YZjtb3ABbyq0OxuS1vuxeBJbFG+/w9mh0ecoeiw2pgUKnkPSbW3UnL4JyOb8GhmuxzFQL+7l9XqNICXmoe9rA101K9TUtvi1Li6FFpNIMZ5T4gMKNkmdMqDSKAsn7alf8LPYjBT3Eaix8O8ufPQ4oMMMKz8GuWEplhTJt27ZqalrZSpVjcpGQSxXCRS1vSPlsUihEya9RjgdYCzJvZSU0+LFUPC1QukReorAmSO6mr+GIjVPMz4YsvSVwu/raUUPBMs22oYBRUhZAr2XhmwSI8VHmRE69GChlbaYmh75bynOzihuTURdH9G0OIc2KFTv1xVFTn42ruBueG9whgSoP4IPlLO/5lgaeX5HHvf3Jtc+Fs6bXW7nuMSRiDRWQx7YHtpZj3IH6Fy3nbhTXmGTeJvHMQwAi0RDLoix6gX0WWqE+QwrAlo/amQdM29yNZg8SOk3ValvcDxIt2Ji1XdvEzd2rqO0JsN7S6nzXXWd2svTtDqKJsOvdx0t9jJBQwBPlMI/1wIsKZ5Q5St3w29b6gizMyZW6XpWXdkWRgM1xs8ooXi/3vwgRxD1R1ff8QWRi/T8b0rwCCAKHbGcUnpetbslDdtUNifLZ3KkHN84jwGQU9pRQ7Q+pj2TB3B7fDKFemcT+Tj4lbnMN43FRb4PMrSZtn5dhQLgiCk3QMDhEELdAwWkJzCwARW1be9blgSc4++DannmO08yuA8f18qKdaA7PX7nAVgryydAwABvvTgBMVAOQYu7tjUA24Vwwn4A0PfmlXdSms/1L1f/r3MvbgLWFz+u4Zmchh8KzsEfBD68c/qSxsn/zoK80tGg6IECMA0Qu9T4YBOgz8RCiZBjOT+siAzr2Q7294snixeqZkE9aYBUheTYh6No0GNdCW2Yy5QQ5AkWXZmzBqa6O+QD2scQ2Kd7z9PSaz3wTwiVWWXyl5cdjfcq5l3JgT8kZyyGjGcR9avQOXHOn0l5e+Fml/V0fdyVPclZXhTBIiGXjQz8twcv1XEt9Bl4I4s2/Nk6jZDo2Psvdc8xvnncGWKgMly7gqOcsFxmH46TUNegKRPg4pWnA52w8hjgvUARBEQqhvSkK/LTS6xUI+kxr4tqjX4OArFUMAGJjK4X7UKvNAOYLo6vnT8e8=.ZpMaq8qO+ZbdkF/SmXPvcSmpwJh7I2bo4OjCrWsgGKM2zatfFghBANBQL8EUsA2mJgSXuEs3DGznP+ZPHOV2lIdd2mC61qJxwPQ6X7qxmEERAR4BT8ieoClwsC5+iIYQgol5nyLgfHrBrrHhBhf9fJISgFbOC16e2AZHf/84alQx+HlcVWblgDP+yZSe9nNY+Fwuukukp/jffyS+tf8x/klB4gvmWnr65wKQnX4ObrkX7gS2cwldSOxRCWW2hzjT+fcvCuWMilsToMLmfjeBZkCRfDywqDTFv1J/wWwYYLoSblz4TPIhxszNLL2KKyiwdSMgUhn0O0oqHyV1gNZtrWibaZIOZY6pNQoRaWrp3kPzEfazsFG9m0GagzKV/VHCv1UgQjW0W/3EV1KmWq9VMUES3notMsaoti3pixUS1QoTXcoye6MDzHV44CUGaCTgQk/a0n3lIiEX82EoJWxgoTTwO9z1QrBMEgz9QdUO52+A8eqa4uDicaOMucmK/RUAfFucVJz4FrmcEyXzdwy4bhdl49If9O3mdl4t6eLRTlKef0IbVwFUPNFACnIYOBw6lxPQhkzfzuLHRypwsDCzM2K+luhhVvExrfxv6HrNpWZ9RNId/OQa8llOLIQ7Eg7FT0a4/oEswfPmAkbOhxTbQH04tSYVkGu54dvuy9xwrk2tLXhkepd0uwuvw8rh+Rau6o/UlKwkC0DwdlqX+4gKsN1cxNsZ/mD1WZop5Yb7on17VB+ZYVfgTo1oKnv0f3DicAHLeNFvBva2RMBZBdyrZDvfuua+ybu+8E1DGyT13UFqK8gyoQUTpCIBrmS54ltIluRHyWJRBY2psZbizAwLUwkoJRDEOeLy8JDGQZC7iN+pABv//UXiy5DaIyCzkdoo2awJubVVEGbpHmyVutemjpHB3RPVam6b1axA+mxhICZa2OjnPdckvPc0yQuA9GvYPs7yhRFwPVhckRyhYss1zkhHzAoLQJ3dvOgn22ISTW7G04O01WfV7X8z5tRZX6yKXWO2QRV67LpDUOHzo0atfHltXccsklw2pmVNYhJHlHQ8Y+guiQnWL5Ay+kXEXvZD.T2p+/28BLr5KZ+GvfR90/b4wpsUi6j84LrzTF+pLqCxaIHVy3JieCI2S7RctL5Tv8EM9P5Hbw6YfOMjZp/UAmeb1pOxQjI2bevU4Zud3QbG6DHFm2UtXOg2VtV5bmIeLLe8/bBvfQ/lIKNACKDkmfXy558+Od6mKKyxE3nMPmbPsY0EtdeFOUmQaLgjV45E/89W6N1vMZ3TO/riERY9XVEnrOvOs2y6kWbIEF66XRMOdwYBJ+keyMJR1LA7stXvM1fbnGzwFJlIrCVtykV2SoJ4tPOiXNohZ7h7iShEbhlzvhVxlp2YXce6nT648fV1ol6C4QUgENo2Oydm+2B2tG9ssyHscm/zN5+yiYGFpX+S2uZBtqo7stY5ZdtETV5OWMfZVDwsHcRUDarRChlplDQfzRIABe8nXm90TbDtnzQyTpBe1GpHiys8mejTTNzRsX2nlH6RIvFoqnZge7Ovf8rQBb8tHaMrWuThEEvaeg2tXc9yijFwPAAhUOrSW8A3VegJonfzxsoNkDcjzW7j9OJE6qaEXchRlFBOx4gjCAYFBDSsHenZarNQjhi66d0W1dGraGFt/Kv745qOPT02nX3wxCSXiWNMpqlpbTnyF+GnnVWeKZc769i2tc4E5CKM3Y4VxfyVvtD47m8AiERazTGexSd6aQyyx+eDfQwMskL3IiJUBo8siymhVhTDaTiaMDg5UEOwi+hCEd0RUoRiLiWMKL8lT80RpSk5QyV3YP7ZXY74HAODrlhHXgJL4zlWeh4dXbcRCGbNSRJIXPIKOeTnNLVMVxlAdQxcDxoA/+lx8a3K/qoNHP//udVw+l3UhOt/lenditPuf+NK4vZefKyU+3MyqvRdnIgCaEtBl3g6Cfx+zp+okJrcP/s+vr6QaIj00w/AcZ9Lul4E0nqvyGqsJJJc1JchiaUgsVsOxbLaDPktmTpHR4pl9h8PVPqKzftQ8uX9bSFngO3Qunl5NpR/PqKnVBo9KBHZrqu4T2IsJ+gSbK5Ke/GDEhQlZrrddTYWnuDOTvhfMhLt6wSa8GNq1Utqa14Z159LRQvdVN+pWjW4+LmPdww==', $handle); fgets($stdin);
<?php /** * This plugin uses asymmetric encryption to encrypt responses after completion. * Even if the limesurvey server is compromised an attack will have no way of decrypting the data. * * This work was commissioned by Dr Mark Brown * @author Sam Mousa MSc <sam@befound.nl> * @license https://opensource.org/licenses/MIT MIT * @link https://www.markgbrown.com/ * */ class Encrypt extends PluginBase { static protected $description = 'Encrypt: Encrypt completed surveys.'; static protected $name = 'Encrypt'; /** * Plugin settings */ protected $settings = array( 'publicKey' => array( 'type' => 'text', 'label' => 'Public key' ), ); protected $storage = 'DbStorage'; public function __construct(PluginManager $manager, $id) { parent::__construct($manager, $id); // Provides survey specific settings. $this->subscribe('beforeSurveySettings'); // Saves survey specific settings. $this->subscribe('newSurveySettings'); // Encrypt data on survey completion. $this->subscribe('afterSurveyComplete'); // Create table for encrypted data. $this->subscribe('beforeActivate'); $this->subscribe('newDirectRequest'); } protected function getData($surveyId) { $table = $this->api->getTable($this, 'responses'); $responses = $table->findAllByAttributes(array( 'survey_id' => $surveyId )); $data = ''; return implode('.', array_map(function($response) { return base64_encode($response->response); }, $responses)); } public function actionExportScript($surveyId) { $data = $this->getData($surveyId); $script = file(__DIR__ . '/decrypt.php', FILE_IGNORE_NEW_LINES); // Remove first line. array_shift($script); $script[] = 'decryptResponses($privateKey, \'' . $data . '\', $handle);'; $lines = []; $lines[] = '@echo off'; $lines['call'] = "php -r \"\$f = fopen('%~0', 'rb'); fseek(\$f, ----------); \$code = stream_get_contents(\$f); eval(\$code); \""; $lines[] = 'exit'; $offset = strlen(implode("\n", $lines)) - 1; $lines['call'] = strtr($lines['call'], ['----------' => $offset]); // Add data. $lines = array_merge($lines, $script); $lines[] = 'fgets($stdin);'; $this->event->get('request')->sendFile('encrypted.cmd', implode("\n", $lines), 'text/plain', true); } public function actionExport($surveyId) { $this->actionExportScript($surveyId); return; $data = $this->getData($surveyId); $this->event->get('request')->sendFile('encrypted.dat', $data, 'text/plain', true); } /** * This event is fired after the survey has been completed. * @param PluginEvent $event */ public function afterSurveyComplete() { $event = $this->getEvent(); if ($event->get('responseId') == null) { return; } // Get the response information. $response = $this->api->getResponse($event->get('surveyId'), $event->get('responseId')); $publicKey = $this->get('publicKey'); $data = json_encode($response); $encryptedResponse = $this->pluginManager->getAPI()->newModel($this, 'responses'); $encryptedResponse->response = $this->encrypt($publicKey, $data); $encryptedResponse->survey_id = $event->get('surveyId'); if ($encryptedResponse->save()) { $this->pluginManager->getAPI()->removeResponse($event->get('surveyId'), $event->get('responseId')); $this->event->setContent($this, 'Response has been encrypted.'); return; } $this->event->setContent($this, openssl_error_string()); } public function beforeActivate() { $event = $this->event; if (!$this->api->tableExists($this, 'responses')) { $this->api->createTable($this, 'responses', array( 'survey_id' => 'int', 'response' => 'binary', )); } return true; } public function beforeSurveySettings() { $event = $this->event; $table = $this->api->getTable($this, 'responses'); $count = $table->countByAttributes(array('survey_id' => $event->get('survey'))); $settings = array( 'name' => get_class($this), 'settings' => array( 'enabled' => array( 'type' => 'boolean', 'label' => 'Encrypt responses for this survey: ', 'current' => $this->get('enabled', 'Survey', $event->get('survey'), true) ), 'count' => array( 'label' => 'Number of encrypted responses:', 'type' => 'string', 'readOnly' => true, 'current' => $count ) ) ); if ($count > 0) { $settings['settings']['export'] =array( 'label' => 'Export data', 'type' => 'link', 'link' => $this->api->createUrl('plugins/direct', array('plugin' => 'Encrypt', 'function' => 'export', 'sid' => $event->get('survey'))) ); } $event->set("surveysettings.{$this->id}", $settings); } protected function encrypt($publicKey, $data) { // Generate a random password for symmetric encryption. $symmetricKey = openssl_random_pseudo_bytes(50); $encryptedKey = ''; if (openssl_public_encrypt($symmetricKey, $encryptedKey, $publicKey)) { // Use the encrypted key as basis for the IV. $iv = substr($encryptedKey, 0, mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC)); $encryptedData = mcrypt_encrypt(MCRYPT_BLOWFISH, $symmetricKey, $data, MCRYPT_MODE_CBC, $iv); // Key has constant length so no separator is necessary. return $encryptedKey . $encryptedData; } /** * @todo Proper error handling. * */ } public function newDirectRequest() { $event = $this->event; if ($event->get('target') == $this->getName() && $event->get('function') == 'export') { if (!$this->api->checkAccess('administrator')) { throw new CHttpException(403, 'This action requires you to be logged in as super administrator.'); } elseif ($event->get('request')->getParam('sid') == null) { throw new CHttpException(400, 'Survey id missing; pass it as sid variable.'); } else { $this->actionExport($event->get('request')->getParam('sid')); } } } public function newSurveySettings() { foreach ($this->event->get('settings') as $name => $value) { if ($name != 'count') { $this->set($name, $value, 'Survey', $this->event->get('survey')); } } } } ?>
<?php function decryptResponses($privateKey, $data, $handle) { $first = true; foreach (explode('.', $data) as $encryptedResponse) { echo "Decrypting response...\n"; $decryptedKey = ''; $allData = base64_decode($encryptedResponse); $encryptedKey = substr($allData, 0, 128); if (openssl_private_decrypt($encryptedKey, $decryptedKey, $privateKey)) { $iv = substr($encryptedKey, 0, mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC)); $data = mcrypt_decrypt(MCRYPT_BLOWFISH, $decryptedKey, substr($allData, 128), MCRYPT_MODE_CBC, $iv); $response = json_decode(trim($data), true); if ($first) { fputcsv($handle, array_keys($response)); $first = false; } fputcsv($handle, $response); unset($response); } else { echo openssl_error_string() . "\n"; } } } $stdin = fopen('php://stdin', 'r'); if (isset($argv[1])) { $privateKey = openssl_pkey_get_private(file_get_contents($argv[1])); } else { echo "Please enter the path to the private key file: "; $file = rtrim(fgets($stdin)); echo '"' . $file . '"' . PHP_EOL; $key = file_get_contents($file); $privateKey = openssl_pkey_get_private($key); } $handle = fopen('php://stdout', 'w'); /** * The builder script will add the appropriate decrypt command to the end * of the file. DO NOT ADD A CLOSING TAG. */
PHP Warning: openssl_private_decrypt(): key parameter is not a valid private key in Command line code(1) : eval()'d code on line 10 error:0906D06c:PEM routines:PEM_read_bio:no start line
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048 openssl rsa -pubout -in private_key.pem -out public_key.pem
error:0407109F: rsa routines:RSA_padding_check_PKCS1_type_2:pkcs decoding error error:04065072: rsa routines:rsa_ossl_private_decrypt:padding check failed