Review of AES encryption concept for an open source project i'm working on an opensource project, A generator for static (html/js), password protected photo galleries. The generator AES 256 encrypts many images with the same key in PyCrypto, and decrypt them with CryptoJS. That's what my prototype does so far:

General


AES 256 mode=CBC, padding=Pkcs7
Encrypt many images with the same salted password
an unique iv for every image
store the unencrypted salt and the unencrypted iv with every encrypted image
store the plain sha1 of the unencrypted image with the encrypted image


Password


salt = 16 random bytes from Random()
aes_key = PBKDF2(dkLen=32, count=1000, salt=salt) of the user selected password
The user can select the password. ATM the only requirement is: min 8 chars.


IV

iv = 16 random bytes from Random()

Do you think this procedure is ok for my use case?
If so, can someone review my python code to encrypt the images? (I'll provide the code on github if general procedure  is ok)

Thank you very much for help and have a nice day,
Boerni
You're pretty much on the right track, I've got a few comments/suggestions though:


  store the plain sha1 of the unencrypted image with the encrypted image


I'm assuming the sha1 hash is to ensure the integrity of the data being encrypted?  If that's the case, you should have a read through this answer.

Assuming you're limited to non-authenticated modes (I don't see GCM, EAX or otherwise) as options in CryptoJS, then you'd probably do best to encrypt-then-MAC:


InitialKey = PBKDF2(dkLen=32, count=100000, salt=salt, password=password) — where dkLen is the native block size of the underlying hash algorithm, in this case, sha256 = 32 bytes.  Note: 1000 rounds of PBKDF2 is considered weak in 2013, if you must use PBKDF2 (as opposed to something stronger like Scrypt), then aim for as many rounds as is tolerable by the user
SecondaryKey = PBKDF2(dkLen=64, count=1, salt=salt, password=InitialKey) — Note; just one round here.  If you're wondering about this two-step PBKDF2 process, check out this excellent answer by D.W. 
AES_key = SecondaryKey:0-32
HMAC_key = SecondaryKey:32-64
HMAC = HMAC_SHA256((cipherText || iv || salt), HMAC_key) — where || denotes concatenation
cipherText = cipherText || HMAC


I'd be inclined to use CTR mode (and no padding) instead of CBC, but that's just a preference - CBC is perfectly fine.  Also, as @owlstead pointed out, you need to consider the implications of a user updating their password, and having to decrypt/re-encrypt all of their images, but that's beyond the scope of my answer.