LSEncrypt - How to (decrypt?)

More
7 months 3 weeks ago - 7 months 3 weeks ago #164642 by socius
socius created the topic: LSEncrypt - How to (decrypt?)
Hi everybody!

first of all: thanks to @sammousa for contributing the LSEncrypt plugin for encrypting survey answers! It's crucial to protect the data of our respondents - and if we guarantee to them to do everything possible to keep their data safe, well we also have to do it.

Here is a description how to install the plugin, encrypt answers successfully, and how fail at the last step :-) namely in decrypting the encrypted data. Who can help here to bring a happy end to this story?

Ok. I'll describe what I did in a little HowTo - with some screenshots:

I installed the plugin ( github.com/SamMousa/limesurvey-encrypt with instructions)

I created an OpenSSL key pair on my linux computer following this guide: en.wikibooks.org/wiki/Cryptography/Generate_a_keypair_using_OpenSSL
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -pubout -in private_key.pem -out public_key.pem

I copied the public key into the according field of the plugin settings (s. attached img)

I enabled the plugin in the survey settings. Everything seems up and running. Then I made up a little survey containing one text- and some numeric inputs. I started this survey, and answered it three times.

First thing I learned (which seems obvious now): Encrypting answers brings that you do not see the responses anymore in Limesurvey, i.e. you do not see the answers in the response summary (below you see the Response summary with 3 encrypted responses). Since they are encrypted you can't browse them - clear. (s. attached img)

Instead you have to download these answers onto your computer first end decrypt these.



I downloaded the file ("encrypted.cmd.txt"), put it into a directory together with the decrypt.php, my private key (renamed to key.priv) as described in the instructions. The directory now contains:



Ok. everything should be in place. Now the instructions say:

[...]
4. Open a terminal in that directory.
5. Execute php decrypt.php > data.csv


My Windows PC didn't speak php yet, so I installed the latest XAMPP from www.apachefriends.org/de/index.html first. Then I started the Apache Server.

I opened a Terminal. With the XAMPP my Windows PC can handle php (at least in the XAMPP Terminal).

And now it's getting exciting.

If I naively enter
php decrypt.php > data.csv

the server does not finish my request (I have to enter STRG+C to stop it) and the result is

1) a warning




2) a data.csv file containing
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


I feel I'm close to where I want to be :-) What do I have to enter here to make this work?


Again: thanks to @sammousa for this great plugin! And thanks for any hint to master this last step!

Best, G


PS: The editor did not let me post this: "Error - You have too many links in your message, please decrease them!" So I got rid of the Links.
Last Edit: 7 months 3 weeks ago by socius. Reason: The editor dropped the images

Please Log in or Create an account to join the conversation.

More
7 months 3 weeks ago #164654 by jelo
jelo replied the topic: LSEncrypt - How to (decrypt?)
You should first check to decrypt under the same environment as encryption.
Executing php under windows is often messed up till you get the paths correct.
The instructions are made for POSIX (e.g.Linux) and not for Windows.

Under windows you might need to use the absolute paths.
Something like this (I'm not quite sure about getting ">" right). Never use PHP under Windows and not used the XAMPP shell.

php "C:\LSEncryption\Test\decrypt.php" > "C:\LSEncryption\Test\data.csv"

Are you a student conducting a survey? If yes, tell me why you use LimeSurvey?
www.limesurvey.org/forum/development/116...y-you-use-limesurvey

Please Log in or Create an account to join the conversation.

More
7 months 2 weeks ago #164665 by socius
socius replied the topic: LSEncrypt - How to (decrypt?)
Hi!

Thanks @jelo for your response! I just tested, whether it makes a difference to run this on Windows XAMPP or my Linux LAMP - it does not! Results (and warnings) are the same. It still was a good opportunity to play with local web servers which I didn’t do before.

I’ll describe two inputs and their respective outputs:

a) As the documentation on github.com/SamMousa/limesurvey-encrypt says:
php decrypt.php > data.csv  
# Process has to be interupted via STRG+C.
# Result: 1) “PHP Warning: file_get_contents(): Filename cannot be empty in /media/gp/PKBACK# 001/LSEncryption/Test/decrypt.php on line 42; 2) A csv-File containing the line “Please enter the path to the private key file: "" “

I'm not a programmer obviously so I kind of played around and tryed with a number of input lines none of which worked out (uneducated guesses, I’d say).

b) I saw that the "encrypted.cmd.txt" contains the decrypt.php. That's why I tried:
php encrypted.cmd.txt > data.csv  
# Request finishes quick.
# Result: a csv that's a exact copy of the encrypted.cmd.txt

If the above command is right (and still does not yield the right output) I'd next think if I have the right keys - I noticed that within the function Blowfish is used - but I don't know whether this is critical for this problem. Maybe 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.)
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -pubout -in private_key.pem -out public_key.pem


So at least something but a warning is happening above (in b) ) - not yet decryption, but maybe we're not too far from there - are we? Thanks for all hints. Btw: Is @sammousa around? :-)


Thanks and all the best,
G

Please Log in or Create an account to join the conversation.

More
7 months 2 weeks ago #164667 by jelo
jelo replied the topic: LSEncrypt - How to (decrypt?)

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


Sam is no longer here. The script won't be running with anything else the current LTS


The responses are encrypted with the public-key. For decryption you need the privatekey.

You can try to enter the path of the public-key as a argument of the commandline
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);
    }

If $argv[1] is set, the privatekey will be read from that file.

secure.php.net/manual/en/reserved.variables.argv.php

Give this a try:
php encrypted.cmd.txt private_key.pem > data.csv

Ensure that the file is there.

Are you a student conducting a survey? If yes, tell me why you use LimeSurvey?
www.limesurvey.org/forum/development/116...y-you-use-limesurvey
The following user(s) said Thank You: socius

Please Log in or Create an account to join the conversation.

More
7 months 2 weeks ago #164710 by socius
socius replied the topic: LSEncrypt - How to (decrypt?)
Hi @jelo,

thanks a lot for your help - and thanks for your link to $argv. I still do not get this working :-(

The proposed line
php encrypted.cmd.txt private_key.pem > data.csv
just copies the content of encrypted.cmd.txt into the data.csv

When I change this to something that looks more like the instructions on github.com/SamMousa/limesurvey-encrypt (php decrypt.php > data.csv)
php decrypt.php private_key.pem encrypted.cmd.txt  > data.csv
This just produces an empty data.csv and there are no errors nor warnings.

I also tried some other combinations - no success - and yes: the "helloworld.php" works ... ;-)

As I said, I'm not a programmer, so I hope some of you have a better time going through this code than I had today :-) If you can help here, that would be great!

Btw: The exported file looks like this: the whole content of decrypt.php in the beginning and the encrypted data in the end, merged in one file.
@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);


I still think I'm doing something wrong here - but if anybody of you with programming experience has time to skim the code that would be great.

The code for Encrypt.php and decrypt.php by Sam Mousa can be found on github.com/SamMousa/limesurvey-encrypt (and here below). It wasn't changed for more than three years. Thanks to Mark G. Brown and Sam Mousa for making this open source!

Who has an idea? I think the encryption of our respondents' data is really essential - I started to think about this some time ago when I found myself not completely trusting everybody at my internet-provider and thought that I should not collect unencrypted readable data there.

Thanks for your time and all the best,
G


Encrypt.php
<?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 http://opensource.org/licenses/MIT MIT
     * @link http://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'));
                }
            }
        }
    }
?>



decrypt.php
<?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.
	 */

Please Log in or Create an account to join the conversation.

More
6 months 4 weeks ago #165577 by socius
socius replied the topic: LSEncrypt - How to (decrypt?)
Dear all,

it seems that not too many users have experiences with this plugin. Is there anybody who worked with LSEncrypt and could write a little about his/her work flow and how the encrypted data can finally be decrypted again? I'd love to use this plugin to protect my respondent's data and privacy - and I hope that some LS users where more successful yet.

Thanks for your time and all the best, G

Please Log in or Create an account to join the conversation.

More
6 months 2 weeks ago #166391 by EuroDyn
EuroDyn replied the topic: LSEncrypt - How to (decrypt?)
Dear socius,

I am also experiencing the same problems like you. Have you found a solution?

Kind Regards
-Alkis

Please Log in or Create an account to join the conversation.

More
6 months 2 weeks ago #166466 by socius
socius replied the topic: LSEncrypt - How to (decrypt?)
Hi Alkis,

thanks for you response - no, there is no solution yet, unfortunately. Maybe Sam can help here - I contacted him. It seems that LSEncrypt, maybe the decrypt.php needs a rework. The above used commands do not seem to fit the latest version of the Plugin. The exported file (encrypted.cmd.txt) already contains the whole content of the decrypt.php. So it might be a different command that leads to decryption, but I did not find it yet.

I tried (on Windows w/ XAMPP):
  • decrypt.php > data1.csv # As on github - Result: a csv with this content "Please enter the path to the private key file: "" and "Warning: file_get_contents(): Filename cannot be empty in C:\test180327" - this makes sense: I did not provide the private key)
  • decrypt.php key.priv > data1.csv # Result: no error/warning, but: empty data1.csv
  • decrypt.php key.priv encrypted.cmd.txt > data01.csv # Result: empty data1.csv

What did you try so far? Do you have the php-skills to check the script? For me this is becoming a reason to finally learn programming to gain some self-efficacy here :-)

I hope we find a solution here.
All the best, G

Please Log in or Create an account to join the conversation.

More
6 months 2 weeks ago #166515 by DenisChenu
DenisChenu replied the topic: LSEncrypt - How to (decrypt?)
I'm not on windows, but when you click on get data : you have a cmd file. a cmd file can be executed by windows, no ?
It's like a bat file , no ?

Assistance on LimeSurvey forum and LimeSurvey core development are on my free time.
I'm not a LimeSurvey GmbH member, professional service on demand (or search sondages pro).
An error happen ? Before make a new topic : remind the Debug mode .
The following user(s) said Thank You: socius

Please Log in or Create an account to join the conversation.

More
6 months 2 weeks ago #166520 by socius
socius replied the topic: LSEncrypt - How to (decrypt?)
Hi all,

thanks Denis! I think we now are getting somewhere close to a solution!

When I export the data it comes as a "encrypted.cmd.txt" - this file contains php code. I got rid of the .txt extension - so it's a .cmd File - and yes this seems a batch file (s. stackoverflow.com/questions/148968/windo...tch-files-bat-vs-cmd )

The encrypted.cmd contains php-Code. Since Windows does not speak php I have to execute this in an php-environment. I tried in a php directory - did not work, but: execution worked in XAMPP - with error messages that might be useful:

Decrypting starts, but with "decoding error" and "padding check failed".




I think we're close to a solution - I hope :-)
Thanks a lot for your time and help!
Best, G
Attachments:

Please Log in or Create an account to join the conversation.

More
6 months 2 weeks ago #166532 by DenisChenu
DenisChenu replied the topic: LSEncrypt - How to (decrypt?)
I start reworking on the plugin :
1. 3.0 compat
2. Allow to disable/unable by default
3. Allow to disable (really, currently broken)
4. 3 links : raw data / windows cmd / linux script

But for 4, … i allways have issue when try to decrypt currently … :(

Assistance on LimeSurvey forum and LimeSurvey core development are on my free time.
I'm not a LimeSurvey GmbH member, professional service on demand (or search sondages pro).
An error happen ? Before make a new topic : remind the Debug mode .
The following user(s) said Thank You: socius

Please Log in or Create an account to join the conversation.

More
6 months 2 weeks ago #166633 by socius
socius replied the topic: LSEncrypt - How to (decrypt?)
Dear all,

thanks so much for your efforts, Denis!

My feeling is, that the problems with decryption result from (my) inappropriate construction of the keys - length, algorithm, encoding, ... - something's wrong. I can only try around, which is frustrating and not very likely leading to success - but maybe I can contribute some error messages :-)

I just tried around with a new pair of keys I with key size 1024bit I generated at travistidwell.com/jsencrypt/Demo/index.html . This did not work - I got warnings/errors. There is probably an easy explanation here - as I understand this: the such constructed keys do not fit... they are not in PEM format or whatsoever...
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

So better go back to the key generation in the example in the beginning of this thread. I created an OpenSSL key pair on my linux computer following this guide: en.wikibooks.org/wiki/Cryptography/Generate_a_keypair_using_OpenSSL
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -pubout -in private_key.pem -out public_key.pem

The error messages when trying to decrypt (execute encrypt.cmd in lamp and enter the path of the key - see above) in this case are:
error:0407109F: rsa routines:RSA_padding_check_PKCS1_type_2:pkcs decoding error
error:04065072: rsa routines:rsa_ossl_private_decrypt:padding check failed


This stackoverflow thread I found for these messages says something about base64 encoding and Option -raw vs. -pkcs - is that some useful information here? Who can decipher this? :-)

stackoverflow.com/questions/39228128/can...a-data-with-open-ssl


I think we need a working example for a keypair for LSEncrypt or the right code for generating a working example.
Thanks for any hint on this - any encryption experts here? :-)

Thanks and all the best,
G

Please Log in or Create an account to join the conversation.

More
6 months 1 week ago #166701 by socius
socius replied the topic: LSEncrypt - How to (decrypt?)
Hi,

Just a short note: I tried again with shorter keys of length 512 bit and 1024 bit (with 2048 bit length I unsuccessfully tried before - s. above).

With 512 bit there is this message:



With length 1024 bit an error message pops up quickly before the terminal window closes.



I made a screenrecording, but the quality is bad unfortunately - but: it seems that somethings working here - at least the warning message points to something new:


Call to undefined function mcrypt_get_iv_size()

Does that help to solve this? :-)

Thanks for your time!
Best, G
Attachments:

Please Log in or Create an account to join the conversation.

More
6 months 1 week ago #166710 by socius
socius replied the topic: LSEncrypt - How to (decrypt?)
Hi again,

I also tried to avoid the built-in decryption via the decrypt.php inside encrypted.cmd. I tried to do the decryption with the openssl function in R ( cran.r-project.org/web/packages/openssl/ ). This seems promising ( cran.r-project.org/web/packages/openssl/openssl.pdf#page=7 )

I just cut out the encrypted responses from encrypted.cmd and tried to decrypt them - but as you can see in the specification of the command, I'm missing
  • IV, a "16 byte raw vector returned by encrypt_envelope" and
  • session, a "raw vector with encrypted session key as returned by encrypt_envelope"

since I did not encrypt with the function in the R package, but with LSencrypt. How can I get this information? The decrypt.php uses the IV
$iv = substr($encryptedKey, 0, mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC));

How could we get these into R - and would this work? Here comes a small reproducible example for encryption/decryption with R:
#install.packages("openssl")  # https://cran.r-project.org/web/packages/openssl
library(openssl)
 
key.priv <- rsa_keygen(bits = 1024)  # Generate RSA keypair
key.publ <- key.priv$pubkey  # Extract the public key
 
# The respective functions for encryption and decryption s. https://cran.r-project.org/web/packages/openssl/openssl.pdf#page=7
text <- charToRaw("Hello world!")  # This is the text we want to encrypt
 
encrypted <- encrypt_envelope(text, pubkey = key.publ)  # We encrypt using the public key
 
decrypted <- decrypt_envelope(encrypted$data, encrypted$iv, encrypted$session, key = key.priv)  # That's how we decrypt again, using the encrypted data, IV and the encrypted session (I just pretend to know what the latter are).
 
text <- rawToChar(decrypted)  # This is the text we want to encrypt
text  # Yes: it's "Hello world!" again


Thanks for reading - and for all hints that lead to the decryption - be it via the LSEncryption Plugin or with an R function - everythings welcome! :-)

Best, G
Attachments:

Please Log in or Create an account to join the conversation.

Start now!

Just create your account and start using Limesurvey today.

Register now
Join our Newsletter!