1
0
Fork 0
mirror of https://github.com/24eme/signaturepdf synced 2024-05-19 14:16:37 +02:00

Compare commits

...

11 commits

Author SHA1 Message Date
Tanguy Le Faucheur da9a342eef Ligne devenue inutile 2024-02-16 16:06:03 +01:00
Tanguy Le Faucheur 9edcac9ea8 Merge branch 'master' of github.com:24eme/signaturepdf 2024-02-16 15:48:13 +01:00
Tanguy Le Faucheur 4b82dae4f9 Force une valeur par défaut lors de la compression 2024-02-16 15:46:08 +01:00
tale-fau 47ef75562f key and hash created in the javascript 2023-11-09 17:25:42 +01:00
tale-fau 12043408cc change way to handle encryption 2023-11-07 19:51:38 +01:00
tale-fau 488f720284 add hardUnlink static method 2023-11-06 19:43:43 +01:00
tale-fau 87000db098 Pass the symmetric key through anchor in url 2023-11-06 18:22:28 +01:00
tale-fau 80a0104a7c symmetric key now transits with cookie 2023-11-06 14:26:36 +01:00
tale-fau 817325eea4 Add keypath getter and keyfile overwriter functions 2023-11-03 18:02:09 +01:00
tale-fau 579379318f Outsourcing of the cryptography functions 2023-11-03 15:13:09 +01:00
tale-fau aa951558fb Ajout de fonctionnalite de chiffrage dechiffrage 2023-11-02 17:35:10 +01:00
4 changed files with 148 additions and 17 deletions

28
app.php
View file

@ -87,6 +87,7 @@ $f3->route('GET /signature',
$f3->set('noSharingMode', true);
}
$f3->set('activeTab', 'sign');
echo View::instance()->render('signature.html.php');
}
);
@ -186,7 +187,6 @@ $f3->route('POST /sign',
shell_exec(sprintf("rsvg-convert -f pdf -o %s %s", $tmpfile.'.svg.pdf', $svgFiles));
shell_exec(sprintf("pdftk %s multistamp %s output %s", $tmpfile.".pdf", $tmpfile.'.svg.pdf', $tmpfile.'_signe.pdf'));
Web::instance()->send($tmpfile.'_signe.pdf', null, 0, TRUE, $filename);
if($f3->get('DEBUG')) {
@ -196,9 +196,11 @@ $f3->route('POST /sign',
}
);
require_once 'lib/cryptography.class.php';
$f3->route('POST /share',
function($f3) {
$hash = substr(hash('sha512', uniqid().rand()), 0, 20);
$hash = Web::instance()->slug($_POST['hash']);
$sharingFolder = $f3->get('PDF_STORAGE_PATH').$hash;
$f3->set('UPLOADS', $sharingFolder."/");
if (!is_dir($f3->get('PDF_STORAGE_PATH'))) {
@ -214,7 +216,6 @@ $f3->route('POST /share',
$filename = "original.pdf";
$tmpfile = tempnam($sharingFolder, date('YmdHis'));
$svgFiles = "";
$files = Web::instance()->receive(function($file,$formFieldName){
if($formFieldName == "pdf" && strpos(Web::instance()->mime($file['tmp_name'], true), 'application/pdf') !== 0) {
$f3->error(403);
@ -238,16 +239,19 @@ $f3->route('POST /share',
if(!count($files)) {
$f3->error(403);
}
if($svgFiles) {
shell_exec(sprintf("rsvg-convert -f pdf -o %s %s", $tmpfile.'.svg.pdf', $svgFiles));
}
if(!$f3->get('DEBUG')) {
array_map('unlink', glob($tmpfile."*.svg"));
array_map('cryptographyClass::hardUnlink', glob($tmpfile."*.svg"));
}
$f3->reroute($f3->get('REVERSE_PROXY_URL').'/signature/'.$hash."#informations");
$symmetricKey = $_COOKIE[$hash];
$encryptor = new CryptographyClass($_COOKIE[$hash], $f3->get('PDF_STORAGE_PATH').$hash);
$encryptor->encrypt();
$f3->reroute($f3->get('REVERSE_PROXY_URL').'/signature/'.$hash."#sk:".$symmetricKey);
}
);
@ -257,6 +261,12 @@ $f3->route('GET /signature/@hash/pdf',
$f3->set('activeTab', 'sign');
$hash = Web::instance()->slug($f3->get('PARAMS.hash'));
$sharingFolder = $f3->get('PDF_STORAGE_PATH').$hash;
$cryptor = new CryptographyClass(CryptographyClass::protectSymmetricKey($_COOKIE[$hash]), $f3->get('PDF_STORAGE_PATH').$hash);
if ($cryptor->decrypt() == false) {
$f3->error(403);
}
$files = scandir($sharingFolder);
$originalFile = $sharingFolder.'/original.pdf';
$finalFile = $sharingFolder.'/'.$f3->get('PARAMS.hash').uniqid().'.pdf';
@ -282,6 +292,8 @@ $f3->route('GET /signature/@hash/pdf',
}
Web::instance()->send($finalFile, null, 0, TRUE, $filename);
$cryptor->encrypt($hash);
if($f3->get('DEBUG')) {
return;
}
@ -399,7 +411,7 @@ $f3->route ('POST /compress',
$compressionType = '/ebook';
} elseif ($compressionType === 'low') {
$compressionType = '/printer';
} elseif ($compressionType === 'high') {
} else {
$compressionType = '/screen';
}

View file

@ -0,0 +1,77 @@
<?php
class CryptographyClass
{
private $symmetricKey = null;
private $pathHash = null;
function __construct($key, $pathHash) {
$this->symmetricKey = $key;
$this->pathHash = $pathHash;
}
private function getFiles($isGpg) {
$suffix = "";
if ($isGpg) {
$suffix = ".gpg";
}
$filesTab = glob($this->pathHash.'/*.pdf'.$suffix);
$filesTab[] = $this->pathHash."/filename.txt".$suffix;
return $filesTab;
}
public function encrypt() {
foreach ($this->getFiles(false) as $file) {
$outputFile = $file.".gpg";
$command = "gpg --batch --passphrase $this->symmetricKey --symmetric --cipher-algo AES256 -o $outputFile $file";
$result = shell_exec($command);
if ($result === false) {
echo "Cypher failure";
exit;
}
$this->hardUnlink($file);
}
}
public function decrypt() {
foreach ($this->getFiles(true) as $file) {
$outputFile = str_replace(".gpg", "", $file);
$command = "gpg --batch --passphrase $this->symmetricKey --decrypt -o $outputFile $file";
$result = shell_exec($command);
if ($result === false) {
echo "Decypher failure";
return $result;
}
$this->hardUnlink($file);
}
return true;
}
public static function hardUnlink($element) {
if (!$element) {
return;
}
$eraser = str_repeat(0, strlen(file_get_contents($element)));
file_put_contents($element, $eraser);
unlink($element);
}
public static function protectSymmetricKey($key) {
return preg_replace('/[^0-9a-zA-Z]*/', '', $key);
}
public static function createSymmetricKey() {
$length = 15;
$keySpace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$pieces = [];
$max = mb_strlen($keySpace, '8bit') - 1;
for ($i = 0; $i < $length; ++$i) {
$pieces []= $keySpace[random_int(0, $max)];
}
return implode('', $pieces);
}
}
?>

View file

@ -414,6 +414,7 @@ var displaysSVG = function() {
});
};
function dataURLtoBlob(dataurl) {
let arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
@ -835,6 +836,10 @@ var createEventsListener = function() {
}
document.getElementById('input_svg_share').files = dataTransfer.files;
hasModifications = false;
document.getElementById('input_pdf_hash').value = generatePdfHash();
document.getElementById('input_symmetric_key').value = generateSymmetricKey();
storeSymmetricKeyCookie(document.getElementById('input_pdf_hash').value, document.getElementById('input_symmetric_key').value);
});
}
@ -962,7 +967,7 @@ var createEventsListener = function() {
return true;
});
if(hash) {
if(pdfHash) {
updateNbLayers();
setInterval(function() {
updateNbLayers();
@ -1081,12 +1086,12 @@ var pageUpload = async function() {
var updateNbLayers = function() {
const xhr = new XMLHttpRequest();
xhr.open('GET', '/signature/'+hash+'/nblayers', true);
xhr.open('GET', '/signature/'+pdfHash+'/nblayers', true);
xhr.onload = function() {
if (xhr.status == 200) {
let newNblayers = xhr.response;
if(nblayers !== null && nblayers != newNblayers) {
reloadPDF('/signature/'+hash+'/pdf');
reloadPDF('/signature/'+pdfHash+'/pdf');
}
nblayers = newNblayers;
document.querySelectorAll('.nblayers').forEach(function(item) {
@ -1127,7 +1132,7 @@ var pageSignature = async function(url) {
let pdfBlob = null;
let filename = url.replace('/pdf/', '');
if(hash) {
if(pdfHash) {
let response = await fetch(url);
if(response.status != 200) {
return;
@ -1159,8 +1164,8 @@ var pageSignature = async function(url) {
if(sharingMode) {
setTimeout(function() { runCron() }, 2000);
}
if(hash) {
pageSignature('/signature/'+hash+'/pdf');
if(pdfHash) {
pageSignature('/signature/'+pdfHash+'/pdf');
window.addEventListener('hashchange', function() {
window.location.reload();
})
@ -1179,4 +1184,38 @@ var pageSignature = async function(url) {
window.addEventListener('hashchange', function() {
window.location.reload();
})
})();
})();
function storeSymmetricKeyCookie(hash, symmetricKey) {
if (symmetricKey.length != 15) {
console.error("Erreur taille cle symmetrique.");
return;
}
document.cookie = hash + "=" + symmetricKey + "; SameSite=Strict";
}
function generateSymmetricKey() {
const length = 15;
const keySpace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
let key = '';
for (let i = 0; i < length; ++i) {
const randomIndex = Math.floor(Math.random() * keySpace.length);
key += keySpace.charAt(randomIndex);
}
return key;
}
function generatePdfHash() {
const length = 20;
const keySpace = '0123456789abcdefghijklmnopqrstuvwxyz';
let key = '';
for (let i = 0; i < length; ++i) {
const randomIndex = Math.floor(Math.random() * keySpace.length);
key += keySpace.charAt(randomIndex);
}
return key;
}

View file

@ -116,6 +116,7 @@
</div>
<form id="form_pdf" action="<?php echo $REVERSE_PROXY_URL; ?>/signature/<?php echo $hash ?>/save" method="post" enctype="multipart/form-data" class="d-none d-sm-none d-md-block">
<input id="input_svg" name="svg[]" type="file" class="d-none" />
<button class="btn btn-primary w-100 mt-2" disabled="disabled" type="submit" id="save"><i class="bi bi-cloud-upload"></i> <?php echo _("Transmit my signature"); ?></button>
</form>
<?php endif; ?>
@ -201,6 +202,8 @@
<form id="form_sharing" clas action="<?php echo $REVERSE_PROXY_URL; ?>/share" method="post" enctype="multipart/form-data">
<input id="input_pdf_share" name="pdf" type="file" class="d-none" />
<input id="input_svg_share" name="svg[]" type="file" class="d-none" />
<input id="input_pdf_hash" name="hash" type="hidden" value="" />
<input id="input_symmetric_key" name="key" type="hidden" value="" />
<button class="btn col-9 col-md-6 btn-primary" type="submit" id="save_share"><?php echo sprintf(_("%s Start sharing"), '<i class="bi bi-cloud-upload"></i>'); ?></button>
</form>
</div>
@ -264,10 +267,10 @@
var maxSize = <?php echo $maxSize ?>;
var maxPage = <?php echo $maxPage ?>;
var sharingMode = <?php echo intval(!isset($noSharingMode)) ?>;
var hash = null;
var pdfHash = null;
var direction = '<?php echo $DIRECTION_LANGUAGE ?>';
<?php if(isset($hash)): ?>
hash = "<?php echo $hash ?>";
pdfHash = "<?php echo $hash ?>";
<?php endif; ?>
var trad = <?php echo json_encode([