2

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

Mike Edward Moras
  • 18,161
  • 12
  • 87
  • 240
ierror
  • 123
  • 3

1 Answers1

1

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.

hunter
  • 4,051
  • 6
  • 29
  • 42