CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
Perl CGI app - encrypting uploaded file before it hits the disk?

 



underdonk
Novice

Mar 20, 2008, 5:39 AM

Post #1 of 14 (3450 views)
Perl CGI app - encrypting uploaded file before it hits the disk? Can't Post

Hi all,

I have written a simple CGI app in Perl that accepts the upload of a file and save it to a directory on the web server. It works great, no problems there. The code I am using to do this is as follows:


Code
my upload_filehandle = $query->upload("data"); 

open(UPLOADFILE, "/blah/blah/$filename") or die "$!";
binmode UPLOADFILE;

while (<$upload_filehandle>){
print UPLOADFILE;
}

close UPLOADFILE;


I have a requirement to encrypt the file as it's being uploaded so no cleartext bits are ever written to the physical medium it's being stored on (the web server HDD's). The reasons for this are numerous. I think the answer is Crypt::CBC and buffering the input somehow, but I just don't know how to put it together. Has anyone out there done this before? Thanks for your time.


KevinR
Veteran


Mar 20, 2008, 9:13 AM

Post #2 of 14 (3448 views)
Re: [underdonk] Perl CGI app - encrypting uploaded file before it hits the disk? [In reply to] Can't Post

I don't think you can encrypt a file during transfer. The entire file will have to be encrypted at the same time, you can't encrypt it in bits and pieces while its being read and before it's written to a file, or at least I don't know how. I don't even know what to suggest.
-------------------------------------------------


underdonk
Novice

Mar 20, 2008, 10:32 AM

Post #3 of 14 (3445 views)
Re: [KevinR] Perl CGI app - encrypting uploaded file before it hits the disk? [In reply to] Can't Post


In Reply To
I don't think you can encrypt a file during transfer. The entire file will have to be encrypted at the same time, you can't encrypt it in bits and pieces while its being read and before it's written to a file, or at least I don't know how. I don't even know what to suggest.


Read the below (taken from http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation):

"In cryptography, a block cipher operates on blocks of fixed length, often 64 or 128 bits. Because messages may be of any length, and because encrypting the same plaintext under the same key always produces the same output (as described in the ECB section below), several modes of operation have been invented which allow block ciphers to provide confidentiality for messages of arbitrary length.

The earliest modes described in the literature (eg, ECB, CBC, OFB and CFB) provide only confidentiality, and do not ensure message integrity. Other modes have since been designed which ensure both confidentiality and message integrity, such as IAPM, CCM, EAX, GCM, and OCB modes. Tweakable narrow-block encryption (LRW) mode, and wide-block encryption (CMC and EME) modes, designed to securely encrypt sectors of a disk, are described in the article devoted to disk encryption theory.
"

With Crypt::CBC I should (according to the documentation on the module) be able to accomplish exactly what I need to do (it even pads data less than the required block size). I guess I'm just unsure about how to buffer the input during the upload so I can perform the operation on the buffered set of bits. Maybe that's how I should have worded my question. :-) So, I guess the real question is, how do I buffer the file upload during the upload process?


KevinR
Veteran


Mar 20, 2008, 11:06 AM

Post #4 of 14 (3443 views)
Re: [underdonk] Perl CGI app - encrypting uploaded file before it hits the disk? [In reply to] Can't Post

Well, then maybe you can try something like this:


Code
#load the encryption module here 

my upload_filehandle = $query->upload("data");

open(UPLOADFILE, "/blah/blah/$filename") or die "$!";
binmode UPLOADFILE;

while (<$upload_filehandle>){
print UPLOADFILE encrypt_it($_);
}

close UPLOADFILE;


where encrypt_it() is whatever the method or function of the particular module is you use. You can also use sysopen() instead of open() and read in chunks of the file at a time and encrypt those chunks and then print them to file. See the sysopen() function for more details.
-------------------------------------------------


underdonk
Novice

Mar 20, 2008, 6:03 PM

Post #5 of 14 (3433 views)
Re: [KevinR] Perl CGI app - encrypting uploaded file before it hits the disk? [In reply to] Can't Post


In Reply To
Well, then maybe you can try something like this:


Code
#load the encryption module here 

my upload_filehandle = $query->upload("data");

open(UPLOADFILE, "/blah/blah/$filename") or die "$!";
binmode UPLOADFILE;

while (<$upload_filehandle>){
print UPLOADFILE encrypt_it($_);
}

close UPLOADFILE;


where encrypt_it() is whatever the method or function of the particular module is you use. You can also use sysopen() instead of open() and read in chunks of the file at a time and encrypt those chunks and then print them to file. See the sysopen() function for more details.


Worked like a charm, in concept. Here it is as coded:


Code
my $buffer; 
my $upload_filehandle = $query->upload("data");
my $key = sha1_base64($passphrase);
my $cipher = Crypt::CBC->new(-key => $key, -cipher => 'Blowfish');

open(UPLOADFILE, ">$upload_dir/$filename") or die "$!";
binmode UPLOADFILE;

$cipher->start('encrypting');

while (read($upload_filehandle, $buffer, 1024)){
print UPLOADFILE $cipher->crypt($buffer);
}

print $cipher->finish();

close UPLOADFILE;


The only problem I'm having now is, when some HTML is output from the application right below this code box, it's prompting to download instead of the browser simply rendering it. Thanks for your assistance!


KevinR
Veteran


Mar 20, 2008, 10:29 PM

Post #6 of 14 (3427 views)
Re: [underdonk] Perl CGI app - encrypting uploaded file before it hits the disk? [In reply to] Can't Post

anytime the browser does not know what to do with the data it is presented with it will prompt for a download. When printing data back to a browser you want to disply you also need to print the appropriate HTTP header first. You are already using the CGI module so you can use that to print a header then your html code.


Code
print $query->header(), 
$query->start_html(),
"some stuff to print here",
$query->end_html;


See the CGI module documentation for details.
-------------------------------------------------


underdonk
Novice

Mar 21, 2008, 5:59 AM

Post #7 of 14 (3421 views)
Re: [KevinR] Perl CGI app - encrypting uploaded file before it hits the disk? [In reply to] Can't Post


In Reply To
anytime the browser does not know what to do with the data it is presented with it will prompt for a download. When printing data back to a browser you want to disply you also need to print the appropriate HTTP header first. You are already using the CGI module so you can use that to print a header then your html code.


Code
print $query->header(), 
$query->start_html(),
"some stuff to print here",
$query->end_html;


See the CGI module documentation for details.


The strange thing is that I am doing that:


Code
print $query->header(); 
print <<END_HTML;
<html>
<head><title>Blah blah blah!</title></head>
<body>
Blah!
</body>
</html>
END_HTML


This block of code is immediately below the block posted above that encrypts the file upon upload. The strange thing is that if I use the code I originally posted, everything works find and the HTML is rendered in the browser. If I use the code that encrypts the file, it prompts me to download the response.The code which generates the response does not change. I have a feeling that something's being returned somewhere in the encryption process that's throwing "things" off.


KevinR
Veteran


Mar 21, 2008, 11:03 AM

Post #8 of 14 (3414 views)
Re: [underdonk] Perl CGI app - encrypting uploaded file before it hits the disk? [In reply to] Can't Post

Hmmm..... Is the encrypted file being written?
-------------------------------------------------


underdonk
Novice

Mar 21, 2008, 3:38 PM

Post #9 of 14 (3409 views)
Re: [KevinR] Perl CGI app - encrypting uploaded file before it hits the disk? [In reply to] Can't Post

Yup, confirmed - correctly even! Laugh Pre- and post- hash of the file match.


KevinR
Veteran


Mar 21, 2008, 6:19 PM

Post #10 of 14 (3407 views)
Re: [underdonk] Perl CGI app - encrypting uploaded file before it hits the disk? [In reply to] Can't Post

If you are printing the correct headers to display html code after the file upload, I don't know what is causing the file download to occur.
-------------------------------------------------


underdonk
Novice

Mar 23, 2008, 8:16 PM

Post #11 of 14 (3384 views)
Re: [KevinR] Perl CGI app - encrypting uploaded file before it hits the disk? [In reply to] Can't Post

Figured it out:


Code
  
print $cipher->finish();


I removed the "print" from this line and all works fine. I'm not sure why I was doing that. Smile This output came before the headers were sent to the client which was mucking things up. Thanks much for your help!


(This post was edited by underdonk on Mar 23, 2008, 8:35 PM)


KevinR
Veteran


Mar 23, 2008, 11:06 PM

Post #12 of 14 (3380 views)
Re: [underdonk] Perl CGI app - encrypting uploaded file before it hits the disk? [In reply to] Can't Post

ahhh, very good.
-------------------------------------------------


underdonk
Novice

Mar 26, 2008, 2:00 PM

Post #13 of 14 (3344 views)
Re: [KevinR] Perl CGI app - encrypting uploaded file before it hits the disk? [In reply to] Can't Post

The purpose of the above was to encrypt the data before it was written to disk so that no cleartext was ever stored on the physical drive. The above, in theory, should perform that task. The question is, does anyone know if this file, before it reaches the encrypt function, is written to a temporary file or swap space? How would I go about checking this? Thanks again for any insight anyone can provide.


BorisE
Novice

May 18, 2008, 10:21 AM

Post #14 of 14 (3245 views)
Re: [underdonk] Perl CGI app - encrypting uploaded file before it hits the disk? [In reply to] Can't Post


In Reply To
The purpose of the above was to encrypt the data before it was written to disk so that no cleartext was ever stored on the physical drive. The above, in theory, should perform that task. The question is, does anyone know if this file, before it reaches the encrypt function, is written to a temporary file or swap space? How would I go about checking this? Thanks again for any insight anyone can provide.



YMMV, I'm no authority on CGI.PM but the following seems to half answer your question:

http://search.cpan.org/dist/CGI.pm/CGI.pm#CREATING_A_FILE_UPLOAD_FIELD

In particular the section near the bottom about hooks. As I understand it the default behavior IS to put the data into a temporary file but the alternative is that you can suppress the temporary file in which case I think the data gets passed to your "hook" sub and then CGI.pm discards it.

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives