Please help us help you and fill where relevant:
LimeSurvey version: LimeSurvey Community Edition Version 6.5.17+240715
Own server or LimeSurvey Cloud: Own server
Survey theme/template: Fruity Twenty Three
==================
I have an email question in a survey that doesn't appear to be decrypting properly in the interface, on export or when I manually attempt to decrypt using the key and nonce from the security.php file.
Any words of wisdom? I'm beyond confused. I've attempted a number of decryption methods and tried to replicate the approach taken in
LimeSurvey/application/core/LSSodium.php at 4139afef7446f37e8a3bc2dfd9ce2423f8265d8a · LimeSurvey/LimeSurvey · GitHub
The key and nonce appear to be correct or my script itself fails - so i think I'm missing something at the end perhaps as readable text does not appear... but the same issue in limesurvey admin interface.
Heres a copy of my external code (its messy sorry as I have lots of different attempts at various methods!):
Code:
<!DOCTYPE html>
<html>
<head>
<title>Roger Roger Emails</title>
<meta name="robots" content="noindex, nofollow">
</head>
<body>
<form method="post" action="">
<label for="table_name">Enter the table name (e.g., lime_survey_x):</label><br>
<input type="text" id="table_name" name="table_name" required><br><br>
<label for="email_field_name">Enter the email field name:</label><br>
<input type="text" id="email_field_name" name="email_field_name" required><br><br>
<label for="ids">Enter the IDs to decrypt (comma separated):</label><br>
<input type="text" id="ids" name="ids" required><br><br>
<label for="encryption_key">Enter the encryption key (hex encoded):</label><br>
<input type="text" id="encryption_key" name="encryption_key" required><br><br>
<label for="encryption_nonce">Enter the encryption nonce (hex encoded):</label><br>
<input type="text" id="encryption_nonce" name="encryption_nonce" required><br><br>
<input type="submit" value="Decrypt">
</form>
<?php
require 'vendor/autoload.php'; // Ensure you have autoloaded the ParagonIE_Sodium_Compat library
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// Get the input values
$tableName = $_POST['table_name'];
$emailFieldName = $_POST['email_field_name'];
$idsInput = $_POST['ids'];
$ids = array_map('trim', explode(',', $idsInput));
$encryptionKeyHex = $_POST['encryption_key'];
$encryptionNonceHex = $_POST['encryption_nonce'];
// Debugging: Display raw input values
echo 'Raw Encryption Key: ' . htmlspecialchars($encryptionKeyHex) . '<br>';
echo 'Raw Encryption Nonce: ' . htmlspecialchars($encryptionNonceHex) . '<br>';
// Convert hex encryption key and nonce to binary
$key = ParagonIE_Sodium_Compat::hex2bin($encryptionKeyHex);
$nonce = ParagonIE_Sodium_Compat::hex2bin($encryptionNonceHex);
if ($key === false) {
echo 'Invalid hex encryption key.<br>';
exit;
}
if ($nonce === false) {
echo 'Invalid hex encryption nonce.<br>';
exit;
}
echo 'Hex Key: ' . htmlspecialchars($encryptionKeyHex) . '<br>';
echo 'Binary Key: ' . bin2hex($key) . '<br>';
echo 'Hex Nonce: ' . htmlspecialchars($encryptionNonceHex) . '<br>';
echo 'Binary Nonce: ' . bin2hex($nonce) . '<br>';
// Define the decryption function using ParagonIE_Sodium_Compat
function decryptData($encryptedData, $key, $nonce) {
// Debugging: Print the encrypted data
echo 'Encrypted Data: ' . htmlspecialchars($encryptedData) . '<br>';
// Decode the encrypted data from Base64
$ciphertext = base64_decode($encryptedData);
if ($ciphertext === false) {
echo 'Base64 decoding failed.<br>';
return false;
}
echo 'Ciphertext (Base64): ' . htmlspecialchars($encryptedData) . '<br>';
echo 'Ciphertext (Binary): ' . bin2hex($ciphertext) . '<br>';
// Decrypt the data using the shared key and nonce
try {
$decryptedData = ParagonIE_Sodium_Compat::crypto_secretbox_open($ciphertext, $nonce, $key);
if ($decryptedData === false) {
echo 'Decryption error.<br>';
return false;
} else {
echo 'Decrypted Data (Binary): ' . htmlspecialchars($decryptedData) . '<br>';
// Attempt to interpret the decrypted data as various formats
$decodedData = @base64_decode($decryptedData, true);
if ($decodedData !== false) {
echo 'Decrypted Data (Base64 Decoded): ' . htmlspecialchars($decodedData) . '<br>';
} else {
echo 'Decrypted Data (Base64 Decoding Failed)<br>';
}
$jsonDecodedData = @json_decode($decryptedData, true);
if (json_last_error() === JSON_ERROR_NONE) {
echo 'Decrypted Data (JSON Decoded): ' . htmlspecialchars(print_r($jsonDecodedData, true)) . '<br>';
} else {
echo 'Decrypted Data (JSON Decoding Failed)<br>';
}
return $decryptedData;
}
} catch (Exception $e) {
echo 'Decryption exception: ' . $e->getMessage() . '<br>';
return false;
}
return false;
}
// Database connection parameters
$host = 'localhost';
$db = 'xxx';
$user = 'xxx';
$pass = 'xxx';
// Create a new PDO instance
try {
$pdo = new PDO("mysql:host=$host;dbname=$db", $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Prepare the SQL query
$placeholders = implode(',', array_fill(0, count($ids), '?'));
$stmt = $pdo->prepare("SELECT id, $emailFieldName FROM $tableName WHERE id IN ($placeholders)");
// Execute the query with the provided IDs
$stmt->execute($ids);
// Loop through the results and decrypt the email field
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$encryptedEmails = $row[$emailFieldName];
echo 'Encrypted Emails: ' . htmlspecialchars($encryptedEmails) . '<br>'; // Debugging line
if (!$encryptedEmails) {
echo 'No data found for ID: ' . $row['id'] . '<br>';
continue;
}
// Handle both single and comma-separated encrypted email values
$encryptedEmailArray = strpos($encryptedEmails, ',') !== false ? explode(',', $encryptedEmails) : [$encryptedEmails];
$decryptedEmails = [];
foreach ($encryptedEmailArray as $encryptedEmail) {
$decryptedEmail = decryptData(trim($encryptedEmail), $key, $nonce);
if ($decryptedEmail !== false) {
$decryptedEmails[] = $decryptedEmail;
}
}
echo 'ID: ' . $row['id'] . ' - Decrypted Emails: ' . implode(', ', $decryptedEmails) . '<br>';
}
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
}
?>
</body>
</html>