For encrypting and decrypting files using a validator works quite well.
In our model we have something like:
Field('data',
'upload',
requires=[IS_NOT_EMPTY(),
IS_LENGTH(26214400, 0, error_message="File
too large."),
TypeValidator(), # use libmagic to
test file type
AVValidator(), # run antivirus
SecureValidator(KEY)],
Where SecureValidator is something like:
class SecureValidator:
'''
Encrypts files
'''
def __init__(self, phrase, error_message="Error"):
self.phrase = phrase
self.e = error_message
def __call__(self, value):
# Encrypt data here prior to passing to defualt web2py store method
val = buffer(value.file.read())
value.file.seek(0, os.SEEK_SET)
value.file.truncate() # Remove old data
val = encrypt_binary(val, phrase=self.phrase) # This is the
actual encryption
value.file.write(val)
value.file.seek(0, os.SEEK_SET)
return (value, None)
Although as you can see, the files are already stored on disk prior to this
method call.
We also have a method for downloading the files as follows:
def decrypt_download(request, db, key, chunk_size = DEFAULT_CHUNK_SIZE,
attachment=True):
"""
downloads from http://..../download/filename
"""
import contenttype as c
if not request.args:
raise HTTP(404)
name = request.args[-1]
items = re.compile('(?P<table>.*?)\.(?P<field>.*?)\..*')\
.match(name)
if not items:
raise HTTP(404)
(t, f) = (items.group('table'), items.group('field'))
field = db[t][f]
try:
(filename, stream) = field.retrieve(name)
# Decrypt stream here
retfile = cStringIO.StringIO()
val,error = decrypt_binary(stream.read(), key)
stream.close()
if error:
# Decryption Error encountered
raise HTTP(500, error)
retfile.write(str(val))
retfile.seek(0, os.SEEK_SET)
except IOError:
logger.error(loghelper(auth, request)+'IO error encountered when
decrypting download')
raise HTTP(404)
response.headers['Content-Type'] = c.contenttype(name)
if attachment:
response.headers['Content-Disposition'] = \
"attachment; filename=%s" % filename
logger.info(loghelper(auth, request)+'File downloaded')
return response.stream(retfile, chunk_size = chunk_size,
request=request)
Majority of the above is replication of web2py's 'file download' method.
There is probably a better way of doing this, but it seems to work well for
us.
Hope this helps,
-- Richard
On Thursday, April 26, 2012 11:50:10 AM UTC-5, minhcd wrote:
>
> Edit: I want to temporarily store uploaded file in memory, *then* call
> API to put this in-memory file to my Key/Value storage. When I put this
> in-memory file (Value) to Key/Value storage, i will get back a *Key* from
> it, and save this Key to RDBMS. When i want retrieve this "blob", i will
> get this Key from RDBMS, then query Key/Value storage to get file(Value)
> and streaming back to browser.
>
> On Thursday, April 26, 2012 11:41:18 PM UTC+7, minhcd wrote:
>>
>> Hi, I think your recipe will work ;)
>>
>> My situation is different a bit from Naveed. My database is RDBMS, but i
>> want to store uploaded file in a Key/Value storage(NoSQL). How can I
>> intervent to store/retrieve process?
>> I want to temporarily store uploaded file in memory, *then* call API to
>> put this in-memory file to my Key/Value storage. (and similar when have
>> "retrieve" request)
>>
>> Could you have me figure it out pls?
>> Thanks in advance!
>>
>> On Friday, April 13, 2012 8:22:02 PM UTC+7, Massimo Di Pierro wrote:
>>>
>>> I have not tried it but you can do
>>>
>>> class EncryptedField(Field):
>>> def __init__(self,*a,**b):
>>> self.password = b['password']
>>> del b['password']
>>> Field.__init__(self,*a,**b)
>>> def store(self,file, filename=None, path=None):
>>> newfile = encrypt(file,self.password)
>>> return Field.store(self,file,filename,path)
>>> def retrieve(self, name, path=None):
>>> (filename, file) = Field.retrieve(self,name,path)
>>> newfile = decrypt(file,self.password)
>>> return (filename, newfile)
>>>
>>> the use
>>>
>>> db.define_table('person',Field('name'),EncryptedField('secret','upload',password='too
>>>
>>> many secrets!'))
>>>
>>> On Thursday, 12 April 2012 16:35:36 UTC-5, naveed wrote:
>>>>
>>>> I wasn’t asking as how to encrypt the file itself, but how to
>>>> incorporate it in to web2py’s existing excellent form upload and download
>>>> system. Assuming that we have functions encrypt(file, password) and
>>>> decrypt(file, password) which return the encrypted and decrypted file
>>>> respectively.
>>>>
>>>>
>>>> *From:* Massimo Di Pierro <[email protected]>
>>>> *Sent:* Wednesday, April 11, 2012 13.31
>>>> *To:* [email protected]
>>>> *Subject:* Re: [web2py] Re: web2py: encrypt uploaded files
>>>>
>>>> Perhaps this can be useful:
>>>>
>>>> http://stackoverflow.com/questions/6309958/encrypting-a-file-with-rsa-in-python
>>>> (look at code in first answer)
>>>>
>>>> On Wednesday, 11 April 2012 12:35:05 UTC-5, naveed wrote:
>>>>>
>>>>> Thanks Massimo for getting back. I can’t use an encrypted file
>>>>> system as when the file system is mounted, it’s totally open. Every file
>>>>> can be encrypted with the same master password. I’m thinking of storing
>>>>> this master password which is itself encrypted using the user’s password
>>>>> (or it’s hash) in the auth_user table.
>>>>>
>>>>> On a related note, I am planning to encrypt some columns of other
>>>>> tables using the same master password. Your thoughts on this approach?
>>>>>
>>>>>
>>>>> *From:* Massimo Di Pierro <[email protected]>
>>>>> *Sent:* Wednesday, April 11, 2012 12.13
>>>>> *To:* [email protected]
>>>>> *Subject:* [web2py] Re: web2py: encrypt uploaded files
>>>>>
>>>>> What are the specs? Can you store them in an encrypted file system?
>>>>> can you encrypt them with the same password? Should every file be
>>>>> encrypted
>>>>> with a different password? Where should the passwords be stored?
>>>>>
>>>>> On Wednesday, 11 April 2012 11:54:24 UTC-5, naveed wrote:
>>>>>>
>>>>>> I need to encrypt uploaded files in web2py (for a HIPAA compliant
>>>>>> application) preferably with AES. How can I accomplish this?
>>>>>>
>>>>>