I have some list of encrypted PDF files. On click of each pdf file, it should get decrypted and view using PDF.Js using AES 256 CBC. I have the following code (Sorry it's a little bit longer, I tried in JSFiddle but getting the issue of saving and attach encrypted and decrypted files) :
app.php
<?php
if($_POST['action'] == 'encrypt') {
my_encrypt($_POST['filename']);
}
if($_POST['action'] == 'decrypt') {
$result = my_decrypt($_POST['filename']);
echo $result;
}
function my_encrypt($filename) {
$filedata = file_get_contents($filename);
// Remove the base64 encoding from our key
$key = '8479768f48481eeb9c8304ce0a58481eeb9c8304ce0a5e3cb5e3cb58479768f4';
$encryption_key = base64_decode($key);
// Generate an initialization vector
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
// Encrypt the data using AES 256 encryption in CBC mode using our encryption key and initialization vector.
$encrypted = openssl_encrypt($filedata, 'aes-256-cbc', $encryption_key, 0, $iv);
// The $iv is just as important as the key for decrypting, so save it with our encrypted data using a unique separator (::)
$result = base64_encode($encrypted . '::' . $iv);
$file = fopen('./files/Sampleencrypt.pdf', 'wb');
fwrite($file, $result);
fclose($file);
echo $result;
return $result;
}
function my_decrypt($filename) {
$filedata = file_get_contents($filename);
// Remove the base64 encoding from our key
$key = '8479768f48481eeb9c8304ce0a58481eeb9c8304ce0a5e3cb5e3cb58479768f4';
$encryption_key = base64_decode($key);
// To decrypt, split the encrypted data from our IV - our unique separator used was "::"
list($encrypted_data, $iv) = explode('::', base64_decode($filedata), 2);
$result = openssl_decrypt($encrypted_data, 'aes-256-cbc', $encryption_key, 0, $iv);
return $result;
}
?>
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="build/pdf.js"></script>
<link rel="stylesheet" href="style.css">
<script>
function encrypt(filename){
$.ajax({
type: "POST",
url: "app.php",
data: { action:'encrypt', filename: filename }
}).done(function( msg ) {
alert( "Data returned: " + msg );
});
return false;
}
function decrypt(filename){
$.ajax({
type: "POST",
url: "app.php",
data: { action:'decrypt', filename: filename },
success: function (response) {
alert(response);
showPdf(response);
}
})
return false;
}
</script>
</head>
<body>
<a href="./files/Sampleencrypt.pdf" onclick="return decrypt(this.href);">Decrypt Sample</a> </br>
<a href="./files/A Sample PDF.pdf" onclick="return encrypt(this.href);">Encrypt Sample</a><br>
<br>
<h1>PDF.js Previous/Next example</h1>
<div>
<button id="prev">Previous</button>
<button id="next">Next</button>
<span>Page: <span id="page_num"></span> / <span id="page_count"></span></span>
</div>
<div>
<canvas id="can"></canvas>
</div>
<script type="text/javascript" src="test.js"></script>
</body>
</html>
test.js
var canvas = document.getElementById('can');
var context = canvas.getContext('2d');
var pdfDoc = null,
pageNum = 1,
pageRendering = false,
pageNumPending = null,
scale = 1.5;
function renderPage(num) {
pageRendering = true;
// Using promise to fetch the page
pdfDoc.getPage(num).then(function(page) {
var viewport = page.getViewport({scale: scale});
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context
var renderContext = {
canvasContext: context,
viewport: viewport
};
var renderTask = page.render(renderContext);
// Wait for rendering to finish
renderTask.promise.then(function() {
pageRendering = false;
if (pageNumPending !== null) {
// New page rendering is pending
renderPage(pageNumPending);
pageNumPending = null;
}
});
});
// Update page counters
document.getElementById('page_num').textContent = num;
}
function queueRenderPage(num) {
if (pageRendering) {
pageNumPending = num;
} else {
renderPage(num);
}
}
function onPrevPage() {
if (pageNum <= 1) {
return;
}
pageNum--;
queueRenderPage(pageNum);
}
document.getElementById('prev').addEventListener('click', onPrevPage);
function onNextPage() {
if (pageNum >= pdfDoc.numPages) {
return;
}
pageNum++;
queueRenderPage(pageNum);
}
document.getElementById('next').addEventListener('click', onNextPage);
function showPdf(pdfData){
// Loaded via <script> tag, create shortcut to access PDF.js exports.
var pdfjsLib = window['pdfjs-dist/build/pdf'];
// The workerSrc property shall be specified.
pdfjsLib.GlobalWorkerOptions.workerSrc = './build/pdf.worker.js';
// Using DocumentInitParameters object to load binary data.
var loadingTask = pdfjsLib.getDocument({data: pdfData});
loadingTask.promise.then(function(pdf) {
console.log('PDF loaded');
pdfDoc = pdf;
//display total page number.
document.getElementById('page_count').textContent = pdf.numPages;
renderPage(pageNum);
}, function (reason) {
// PDF loading error
console.error(reason);
});
}
I am using PDFJS (example base64 encoded PDF from documentation) to display the pdf file. Some files are okay with this functionality (which are very small and sample files). But for other pdf files, the decryption of encrypted file gives string output in which some text is unreadable (like S��*�AK����^����0) and they are loaded using pdf.js but not getting displayed. If I save this decrypted output in a file and open that file, it is as expected. Only PDFJS is not able to display it. I am not getting the exact problem. Is the problem is in decryption or PDFJS code? Please help.
Got the solution, Converted the decryption file result in base64 and decode this base-64 encoded string in PDF.js. Added the following code:
app.php
function my_decrypt($filename) {
$filedata = file_get_contents($filename);
// Remove the base64 encoding from our key
$key = '8479768f48481eeb9c8304ce0a58481eeb9c8304ce0a5e3cb5e3cb58479768f4';
$encryption_key = base64_decode($key);
// To decrypt, split the encrypted data from our IV - our unique separator used was "::"
list($encrypted_data, $iv) = explode('::', base64_decode($filedata), 2);
$result = openssl_decrypt($encrypted_data, 'aes-256-cbc', $encryption_key, 0, $iv);
$result = base64_encode($result);
return $result;
}
test.js
function showPdf(pdfData){
// Loaded via <script> tag, create shortcut to access PDF.js exports.
var pdfjsLib = window['pdfjs-dist/build/pdf'];
// The workerSrc property shall be specified.
pdfjsLib.GlobalWorkerOptions.workerSrc = './build/pdf.worker.js';
// Using DocumentInitParameters object to load binary data.
var loadingTask = pdfjsLib.getDocument({data: atob(pdfData)});
loadingTask.promise.then(function(pdf) {
console.log('PDF loaded');
pdfDoc = pdf;
//display total page number.
document.getElementById('page_count').textContent = pdf.numPages;
renderPage(pageNum);
}, function (reason) {
// PDF loading error
console.error(reason);
});
}
Thank you!